mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-26 11:45:39 +01:00
check_test_cases: move "walk" functions into a class
Make the structure more Pythonic: use classes for abstraction and refinement, rather than higher-order functions. Convert walk(function, state, data) into instance.walk(data) where instance has a method that implements function and state is a field of instance. No behavior change. Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
parent
d34e9e450f
commit
78c45dbb0f
@ -76,13 +76,41 @@ def check_description(results, seen, file_name, line_number, description):
|
|||||||
len(description))
|
len(description))
|
||||||
seen[description] = line_number
|
seen[description] = line_number
|
||||||
|
|
||||||
def walk_test_suite(function, results, descriptions, data_file_name):
|
class TestDescriptionExplorer:
|
||||||
"""Iterate over the test cases in the given unit test data file.
|
"""An iterator over test cases with descriptions.
|
||||||
|
|
||||||
Call function(results, descriptions, data_file_name, line_number, description)
|
The test cases that have descriptions are:
|
||||||
on each description.
|
* Individual unit tests (entries in a .data file) in test suites.
|
||||||
|
* Individual test cases in ssl-opt.sh.
|
||||||
|
|
||||||
|
This is an abstract class. To use it, derive a class that implements
|
||||||
|
the process_test_case method, and call walk_all().
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def process_test_case(self, per_file_state,
|
||||||
|
file_name, line_number, description):
|
||||||
|
"""Process a test case.
|
||||||
|
|
||||||
|
per_file_state: a new object returned by per_file_state() for each file.
|
||||||
|
file_name: a relative path to the file containing the test case.
|
||||||
|
line_number: the line number in the given file.
|
||||||
|
description: the test case description as a byte string.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def per_file_state(self):
|
||||||
|
"""Return a new per-file state object.
|
||||||
|
|
||||||
|
The default per-file state object is None. Child classes that require per-file
|
||||||
|
state may override this method.
|
||||||
|
"""
|
||||||
|
#pylint: disable=no-self-use
|
||||||
|
return None
|
||||||
|
|
||||||
|
def walk_test_suite(self, data_file_name):
|
||||||
|
"""Iterate over the test cases in the given unit test data file."""
|
||||||
in_paragraph = False
|
in_paragraph = False
|
||||||
|
descriptions = self.per_file_state() # pylint: disable=assignment-from-none
|
||||||
with open(data_file_name, 'rb') as data_file:
|
with open(data_file_name, 'rb') as data_file:
|
||||||
for line_number, line in enumerate(data_file, 1):
|
for line_number, line in enumerate(data_file, 1):
|
||||||
line = line.rstrip(b'\r\n')
|
line = line.rstrip(b'\r\n')
|
||||||
@ -93,16 +121,13 @@ on each description.
|
|||||||
continue
|
continue
|
||||||
if not in_paragraph:
|
if not in_paragraph:
|
||||||
# This is a test case description line.
|
# This is a test case description line.
|
||||||
function(results, descriptions,
|
self.process_test_case(descriptions,
|
||||||
data_file_name, line_number, line)
|
data_file_name, line_number, line)
|
||||||
in_paragraph = True
|
in_paragraph = True
|
||||||
|
|
||||||
def walk_ssl_opt_sh(function, results, descriptions, file_name):
|
def walk_ssl_opt_sh(self, file_name):
|
||||||
"""Iterate over the test cases in ssl-opt.sh or a file with a similar format.
|
"""Iterate over the test cases in ssl-opt.sh or a file with a similar format."""
|
||||||
|
descriptions = self.per_file_state() # pylint: disable=assignment-from-none
|
||||||
Call function(results, descriptions, file_name, line_number, description)
|
|
||||||
on each description.
|
|
||||||
"""
|
|
||||||
with open(file_name, 'rb') as file_contents:
|
with open(file_name, 'rb') as file_contents:
|
||||||
for line_number, line in enumerate(file_contents, 1):
|
for line_number, line in enumerate(file_contents, 1):
|
||||||
# Assume that all run_test calls have the same simple form
|
# Assume that all run_test calls have the same simple form
|
||||||
@ -112,23 +137,37 @@ on each description.
|
|||||||
if not m:
|
if not m:
|
||||||
continue
|
continue
|
||||||
description = m.group(1)
|
description = m.group(1)
|
||||||
function(results, descriptions,
|
self.process_test_case(descriptions,
|
||||||
file_name, line_number, description)
|
file_name, line_number, description)
|
||||||
|
|
||||||
def walk_all(function, results):
|
def walk_all(self):
|
||||||
"""Iterate over all named test cases.
|
"""Iterate over all named test cases."""
|
||||||
|
|
||||||
Call function(results, {}, file_name, line_number, description)
|
|
||||||
on each description.
|
|
||||||
"""
|
|
||||||
test_directories = collect_test_directories()
|
test_directories = collect_test_directories()
|
||||||
for directory in test_directories:
|
for directory in test_directories:
|
||||||
for data_file_name in glob.glob(os.path.join(directory, 'suites',
|
for data_file_name in glob.glob(os.path.join(directory, 'suites',
|
||||||
'*.data')):
|
'*.data')):
|
||||||
walk_test_suite(function, results, {}, data_file_name)
|
self.walk_test_suite(data_file_name)
|
||||||
ssl_opt_sh = os.path.join(directory, 'ssl-opt.sh')
|
ssl_opt_sh = os.path.join(directory, 'ssl-opt.sh')
|
||||||
if os.path.exists(ssl_opt_sh):
|
if os.path.exists(ssl_opt_sh):
|
||||||
walk_ssl_opt_sh(function, results, {}, ssl_opt_sh)
|
self.walk_ssl_opt_sh(ssl_opt_sh)
|
||||||
|
|
||||||
|
class DescriptionChecker(TestDescriptionExplorer):
|
||||||
|
"""Check all test case descriptions.
|
||||||
|
|
||||||
|
* Check that each description is valid (length, allowed character set, etc.).
|
||||||
|
* Check that there is no duplicated description inside of one test suite.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, results):
|
||||||
|
self.results = results
|
||||||
|
|
||||||
|
def per_file_state(self):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def process_test_case(self, per_file_state,
|
||||||
|
file_name, line_number, description):
|
||||||
|
check_description(self.results, per_file_state,
|
||||||
|
file_name, line_number, description)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description=__doc__)
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
@ -140,7 +179,8 @@ def main():
|
|||||||
help='Show warnings (default: on; undoes --quiet)')
|
help='Show warnings (default: on; undoes --quiet)')
|
||||||
options = parser.parse_args()
|
options = parser.parse_args()
|
||||||
results = Results(options)
|
results = Results(options)
|
||||||
walk_all(check_description, results)
|
checker = DescriptionChecker(results)
|
||||||
|
checker.walk_all()
|
||||||
if (results.warnings or results.errors) and not options.quiet:
|
if (results.warnings or results.errors) and not options.quiet:
|
||||||
sys.stderr.write('{}: {} errors, {} warnings\n'
|
sys.stderr.write('{}: {} errors, {} warnings\n'
|
||||||
.format(sys.argv[0], results.errors, results.warnings))
|
.format(sys.argv[0], results.errors, results.warnings))
|
||||||
|
Loading…
Reference in New Issue
Block a user