blob: 2576dc7d10c450d59bccdee2ed1214b81ddef09a [file] [log] [blame]
Minos Galanakis2c824b42025-03-20 09:28:45 +00001#!/usr/bin/env python3
2
3"""Sanity checks for test data."""
4
5# Copyright The Mbed TLS Contributors
6# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
7
8import argparse
9import re
10import sys
11
12from mbedtls_framework import collect_test_cases
13
14
15class DescriptionChecker(collect_test_cases.TestDescriptionExplorer):
16 """Check all test case descriptions.
17
18* Check that each description is valid (length, allowed character set, etc.).
19* Check that there is no duplicated description inside of one test suite.
20"""
21
22 def __init__(self, results):
23 self.results = results
24
25 def new_per_file_state(self):
26 """Dictionary mapping descriptions to their line number."""
27 return {}
28
29 def process_test_case(self, per_file_state,
30 file_name, line_number, description):
31 """Check test case descriptions for errors."""
32 results = self.results
33 seen = per_file_state
34 if description in seen:
35 results.error(file_name, line_number,
36 'Duplicate description (also line {})',
37 seen[description])
38 return
39 if re.search(br'[\t;]', description):
40 results.error(file_name, line_number,
41 'Forbidden character \'{}\' in description',
42 re.search(br'[\t;]', description).group(0).decode('ascii'))
43 if re.search(br'[^ -~]', description):
44 results.error(file_name, line_number,
45 'Non-ASCII character in description')
46 if len(description) > 66:
47 results.warning(file_name, line_number,
48 'Test description too long ({} > 66)',
49 len(description))
50 seen[description] = line_number
51
52def main():
53 parser = argparse.ArgumentParser(description=__doc__)
54 parser.add_argument('--list-all',
55 action='store_true',
56 help='List all test cases, without doing checks')
57 parser.add_argument('--quiet', '-q',
58 action='store_true',
59 help='Hide warnings')
60 parser.add_argument('--verbose', '-v',
61 action='store_false', dest='quiet',
62 help='Show warnings (default: on; undoes --quiet)')
63 options = parser.parse_args()
64 if options.list_all:
65 descriptions = collect_test_cases.collect_available_test_cases()
66 sys.stdout.write('\n'.join(descriptions + ['']))
67 return
68 results = collect_test_cases.Results(options)
69 checker = DescriptionChecker(results)
70 try:
71 checker.walk_all()
72 except collect_test_cases.ScriptOutputError as e:
73 results.error(e.script_name, e.idx,
74 '"{}" should be listed as "<suite_name>;<description>"',
75 e.line)
76 if (results.warnings or results.errors) and not options.quiet:
77 sys.stderr.write('{}: {} errors, {} warnings\n'
78 .format(sys.argv[0], results.errors, results.warnings))
79 sys.exit(1 if results.errors else 0)
80
81if __name__ == '__main__':
82 main()