1 # -*- python; coding: utf-8 -*-
3 # gtk-doc - GTK DocBook documentation generator.
4 # Copyright (C) 2007 David Nečas
5 # 2007-2017 Stefan Sauer
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 The check tool runs various tests on built documentation and outputs test
24 results. Can be run druring make check, by adding this to the documentations
25 Makefile.am: TESTS = $(GTKDOC_CHECK).
28 # Support both Python 2 and 3
29 from __future__
import print_function
36 class FileFormatError(Exception):
40 def grep(regexp
, lines
, what
):
41 pattern
= re
.compile(regexp
)
43 for match
in re
.finditer(pattern
, line
):
45 raise FileFormatError(what
)
48 def check_empty(filename
):
49 with
open(filename
) as f
:
50 count
= sum(1 for line
in f
if line
.strip())
54 def check_includes(filename
):
55 # Check that each XML file in the xml directory is included in doc_main_file
56 with
open(filename
) as f
:
57 lines
= f
.read().splitlines()
59 for include
in glob('xml/*.xml'):
61 next(line
for line
in lines
if include
in line
)
64 print('%s:1:E: doesn\'t appear to include "%s"' % (filename
, include
))
69 def get_variable(env
, lines
, variable
):
70 value
= env
.get(variable
,
71 grep(r
'^\s*' + variable
+ r
'\s*=\s*(\S+)', lines
, variable
))
75 def read_file(filename
):
76 with
open(filename
) as f
:
77 return f
.read().splitlines()
80 def run_tests(workdir
, doc_module
, doc_main_file
):
83 print('Running suite(s): gtk-doc-' + doc_module
)
86 statusfilename
= os
.path
.join(workdir
, doc_module
+ '-undocumented.txt')
87 statusfile
= read_file(statusfilename
)
89 undocumented
= int(grep(r
'^(\d+)\s+not\s+documented\.\s*$',
90 statusfile
, 'number of undocumented symbols'))
91 incomplete
= int(grep(r
'^(\d+)\s+symbols?\s+incomplete\.\s*$',
92 statusfile
, 'number of incomplete symbols'))
93 except FileFormatError
as e
:
94 print('Cannot find %s in %s' % (str(e
), statusfilename
))
95 return checks
# consider all failed
97 total
= undocumented
+ incomplete
99 print(doc_module
+ '-undocumented.txt:1:E: %d undocumented or incomplete symbols' % total
)
102 undeclared
= check_empty(os
.path
.join(workdir
, doc_module
+ '-undeclared.txt'))
104 print(doc_module
+ '-undeclared.txt:1:E: %d undeclared symbols\n' % undeclared
)
107 unused
= check_empty(os
.path
.join(workdir
, doc_module
+ '-unused.txt'))
109 print(doc_module
+ '-unused.txt:1:E: %d unused documentation entries\n' % unused
)
112 missing_includes
= check_includes(os
.path
.join(workdir
, doc_main_file
))
115 failed
= (total
> 0) + (undeclared
!= 0) + (unused
!= 0) + (missing_includes
!= 0)
116 rate
= 100.0 * (checks
- failed
) / checks
117 print("%.1f%%: Checks %d, Failures: %d" % (rate
, checks
, failed
))
121 def run(options
=None):
125 int: a system exit code.
128 # Get parameters from test env, if not there try to grab them from the makefile
129 # We like Makefile.am more but builddir does not necessarily contain one.
130 makefilename
= 'Makefile.am'
131 if not os
.path
.exists(makefilename
):
132 makefilename
= 'Makefile'
133 makefile
= read_file(makefilename
)
135 # For historic reasons tests are launched in srcdir
136 workdir
= os
.environ
.get('BUILDDIR', None)
141 doc_module
= get_variable(os
.environ
, makefile
, 'DOC_MODULE')
142 doc_main_file
= get_variable(os
.environ
, makefile
, 'DOC_MAIN_SGML_FILE')
143 except FileFormatError
as e
:
144 print('Cannot find %s in %s' % (str(e
), makefilename
))
147 doc_main_file
= doc_main_file
.replace('$(DOC_MODULE)', doc_module
)
149 return run_tests(workdir
, doc_module
, doc_main_file
)