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):
38 def __init__(self
, detail
):
42 def grep(regexp
, lines
, what
):
43 pattern
= re
.compile(regexp
)
45 for match
in re
.finditer(pattern
, line
):
47 raise FileFormatError(what
)
50 def check_empty(filename
):
51 with
open(filename
) as f
:
52 count
= sum(1 for line
in f
if line
.strip())
56 def check_includes(filename
):
57 # Check that each XML file in the xml directory is included in doc_main_file
58 with
open(filename
) as f
:
59 lines
= f
.read().splitlines()
61 for include
in glob('xml/*.xml'):
63 next(line
for line
in lines
if include
in line
)
66 print('%s:1:E: doesn\'t appear to include "%s"' % (filename
, include
))
71 def get_variable(env
, lines
, variable
):
72 value
= env
.get(variable
,
73 grep(r
'^\s*' + variable
+ '\s*=\s*(\S+)', lines
, variable
))
77 def read_file(filename
):
78 with
open(filename
) as f
:
79 return f
.read().splitlines()
82 def run_tests(workdir
, doc_module
, doc_main_file
):
85 print('Running suite(s): gtk-doc-' + doc_module
)
88 statusfilename
= os
.path
.join(workdir
, doc_module
+ '-undocumented.txt')
89 statusfile
= read_file(statusfilename
)
91 undocumented
= int(grep(r
'^(\d+)\s+not\s+documented\.\s*$',
92 statusfile
, 'number of undocumented symbols'))
93 incomplete
= int(grep(r
'^(\d+)\s+symbols?\s+incomplete\.\s*$',
94 statusfile
, 'number of incomplete symbols'))
95 except FileFormatError
as e
:
96 print('Cannot find %s in %s' % (e
.detail
, statusfilename
))
97 return checks
# consider all failed
99 total
= undocumented
+ incomplete
101 print(doc_module
+ '-undocumented.txt:1:E: %d undocumented or incomplete symbols' % total
)
104 undeclared
= check_empty(os
.path
.join(workdir
, doc_module
+ '-undeclared.txt'))
106 print(doc_module
+ '-undeclared.txt:1:E: %d undeclared symbols\n' % undeclared
)
109 unused
= check_empty(os
.path
.join(workdir
, doc_module
+ '-unused.txt'))
111 print(doc_module
+ '-unused.txt:1:E: %d unused documentation entries\n' % unused
)
114 missing_includes
= check_includes(os
.path
.join(workdir
, doc_main_file
))
117 failed
= (total
> 0) + (undeclared
!= 0) + (unused
!= 0) + (missing_includes
!= 0)
118 rate
= 100.0 * (checks
- failed
) / checks
119 print("%.1f%%: Checks %d, Failures: %d" % (rate
, checks
, failed
))
123 def run(options
=None):
127 int: a system exit code.
130 # Get parameters from test env, if not there try to grab them from the makefile
131 # We like Makefile.am more but builddir does not necessarily contain one.
132 makefilename
= 'Makefile.am'
133 if not os
.path
.exists(makefilename
):
134 makefilename
= 'Makefile'
135 makefile
= read_file(makefilename
)
137 # For historic reasons tests are launched in srcdir
138 workdir
= os
.environ
.get('BUILDDIR', None)
143 doc_module
= get_variable(os
.environ
, makefile
, 'DOC_MODULE')
144 doc_main_file
= get_variable(os
.environ
, makefile
, 'DOC_MAIN_SGML_FILE')
145 except FileFormatError
as e
:
146 print('Cannot find %s in %s' % (e
.detail
, makefilename
))
149 doc_main_file
= doc_main_file
.replace('$(DOC_MODULE)', doc_module
)
151 return run_tests(workdir
, doc_module
, doc_main_file
)