1 # Copyright (C) 2014-2022 Free Software Foundation, Inc.
2 #
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation, either version 3 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <https://www.gnu.org/licenses/>.
15 #
16 """Check that the list of test files in Makefile.am is complete and not redundant.
17
18 Usage:
19 checklists file-listing-configured-files test-root subdir-1-containing-tests [subdir-2-containing-tests ...]
20 """
21
22 import os
23 import os.path
24 import re
25 import sys
26
27 def report_unlisted(filename):
28 sys.stderr.write(
29 'Error: test file %s is not listed in Makefile.am but exists on disk.\n'
30 % (filename,))
31
32
33 def report_missing(filename):
34 sys.stderr.write(
35 'Error: test file %s is listed in Makefile.am but does not exist on disk.\n'
36 % (filename,))
37
38 def report_dupe(filename):
39 sys.stderr.write(
40 'Error: test file %s is listed more than once in Makefile.am.\n'
41 % (filename,))
42
43
44 def report_problems(problem_filenames, reporting_function):
45 for f in problem_filenames:
46 reporting_function(f)
47 return len(problem_filenames)
48
49
50 def file_names(listfile_name):
51 for line in open(listfile_name, 'r').readlines():
52 yield line.rstrip('\n')
53
54
55 def configured_file_names(listfile_name):
56 dupes = set()
57 result = set()
58 for filename in file_names(listfile_name):
59 if filename in result:
60 dupes.add(filename)
61 else:
62 result.add(filename)
63 return dupes, result
64
65
66 def find_test_files(roots):
67 testfile_rx = re.compile(r'\.(exp|xo)$')
68 for root in roots:
69 for parent, dirs, files in os.walk(root):
70 for file_basename in files:
71 if testfile_rx.search(file_basename):
72 yield os.path.join(parent, file_basename)
73
74
75 class ESC[4;38;5;81mTemporaryWorkingDirectory(ESC[4;38;5;149mobject):
76
77 def __init__(self, cwd):
78 self.new_cwd = cwd
79 self.old_cwd = os.getcwd()
80
81 def __enter__(self):
82 os.chdir(self.new_cwd)
83
84 def __exit__(self, *unused_args):
85 os.chdir(self.old_cwd)
86
87
88 def main(args):
89 if len(args) < 3:
90 sys.stderr.write(__doc__)
91 return 1
92 dupes, configured = configured_file_names(args[1])
93 with TemporaryWorkingDirectory(args[2]):
94 actual = set(find_test_files(args[3:]))
95 sys.stdout.write('%d test files configured for find, %s files on-disk'
96 % (len(configured), len(actual)))
97 problem_count = 0
98 problem_count += report_problems(dupes, report_dupe)
99 problem_count += report_problems(configured - actual, report_missing)
100 problem_count += report_problems(actual - configured, report_unlisted)
101 if problem_count:
102 return 1
103 else:
104 return 0
105
106 if __name__ == '__main__':
107 sys.exit(main(sys.argv))