1*62c56f98SSadaf Ebrahimi"""Library for constructing an Mbed TLS test case. 2*62c56f98SSadaf Ebrahimi""" 3*62c56f98SSadaf Ebrahimi 4*62c56f98SSadaf Ebrahimi# Copyright The Mbed TLS Contributors 5*62c56f98SSadaf Ebrahimi# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6*62c56f98SSadaf Ebrahimi# 7*62c56f98SSadaf Ebrahimi 8*62c56f98SSadaf Ebrahimiimport binascii 9*62c56f98SSadaf Ebrahimiimport os 10*62c56f98SSadaf Ebrahimiimport sys 11*62c56f98SSadaf Ebrahimifrom typing import Iterable, List, Optional 12*62c56f98SSadaf Ebrahimi 13*62c56f98SSadaf Ebrahimifrom . import typing_util 14*62c56f98SSadaf Ebrahimi 15*62c56f98SSadaf Ebrahimidef hex_string(data: bytes) -> str: 16*62c56f98SSadaf Ebrahimi return '"' + binascii.hexlify(data).decode('ascii') + '"' 17*62c56f98SSadaf Ebrahimi 18*62c56f98SSadaf Ebrahimi 19*62c56f98SSadaf Ebrahimiclass MissingDescription(Exception): 20*62c56f98SSadaf Ebrahimi pass 21*62c56f98SSadaf Ebrahimi 22*62c56f98SSadaf Ebrahimiclass MissingFunction(Exception): 23*62c56f98SSadaf Ebrahimi pass 24*62c56f98SSadaf Ebrahimi 25*62c56f98SSadaf Ebrahimiclass TestCase: 26*62c56f98SSadaf Ebrahimi """An Mbed TLS test case.""" 27*62c56f98SSadaf Ebrahimi 28*62c56f98SSadaf Ebrahimi def __init__(self, description: Optional[str] = None): 29*62c56f98SSadaf Ebrahimi self.comments = [] #type: List[str] 30*62c56f98SSadaf Ebrahimi self.description = description #type: Optional[str] 31*62c56f98SSadaf Ebrahimi self.dependencies = [] #type: List[str] 32*62c56f98SSadaf Ebrahimi self.function = None #type: Optional[str] 33*62c56f98SSadaf Ebrahimi self.arguments = [] #type: List[str] 34*62c56f98SSadaf Ebrahimi 35*62c56f98SSadaf Ebrahimi def add_comment(self, *lines: str) -> None: 36*62c56f98SSadaf Ebrahimi self.comments += lines 37*62c56f98SSadaf Ebrahimi 38*62c56f98SSadaf Ebrahimi def set_description(self, description: str) -> None: 39*62c56f98SSadaf Ebrahimi self.description = description 40*62c56f98SSadaf Ebrahimi 41*62c56f98SSadaf Ebrahimi def set_dependencies(self, dependencies: List[str]) -> None: 42*62c56f98SSadaf Ebrahimi self.dependencies = dependencies 43*62c56f98SSadaf Ebrahimi 44*62c56f98SSadaf Ebrahimi def set_function(self, function: str) -> None: 45*62c56f98SSadaf Ebrahimi self.function = function 46*62c56f98SSadaf Ebrahimi 47*62c56f98SSadaf Ebrahimi def set_arguments(self, arguments: List[str]) -> None: 48*62c56f98SSadaf Ebrahimi self.arguments = arguments 49*62c56f98SSadaf Ebrahimi 50*62c56f98SSadaf Ebrahimi def check_completeness(self) -> None: 51*62c56f98SSadaf Ebrahimi if self.description is None: 52*62c56f98SSadaf Ebrahimi raise MissingDescription 53*62c56f98SSadaf Ebrahimi if self.function is None: 54*62c56f98SSadaf Ebrahimi raise MissingFunction 55*62c56f98SSadaf Ebrahimi 56*62c56f98SSadaf Ebrahimi def write(self, out: typing_util.Writable) -> None: 57*62c56f98SSadaf Ebrahimi """Write the .data file paragraph for this test case. 58*62c56f98SSadaf Ebrahimi 59*62c56f98SSadaf Ebrahimi The output starts and ends with a single newline character. If the 60*62c56f98SSadaf Ebrahimi surrounding code writes lines (consisting of non-newline characters 61*62c56f98SSadaf Ebrahimi and a final newline), you will end up with a blank line before, but 62*62c56f98SSadaf Ebrahimi not after the test case. 63*62c56f98SSadaf Ebrahimi """ 64*62c56f98SSadaf Ebrahimi self.check_completeness() 65*62c56f98SSadaf Ebrahimi assert self.description is not None # guide mypy 66*62c56f98SSadaf Ebrahimi assert self.function is not None # guide mypy 67*62c56f98SSadaf Ebrahimi out.write('\n') 68*62c56f98SSadaf Ebrahimi for line in self.comments: 69*62c56f98SSadaf Ebrahimi out.write('# ' + line + '\n') 70*62c56f98SSadaf Ebrahimi out.write(self.description + '\n') 71*62c56f98SSadaf Ebrahimi if self.dependencies: 72*62c56f98SSadaf Ebrahimi out.write('depends_on:' + ':'.join(self.dependencies) + '\n') 73*62c56f98SSadaf Ebrahimi out.write(self.function + ':' + ':'.join(self.arguments) + '\n') 74*62c56f98SSadaf Ebrahimi 75*62c56f98SSadaf Ebrahimidef write_data_file(filename: str, 76*62c56f98SSadaf Ebrahimi test_cases: Iterable[TestCase], 77*62c56f98SSadaf Ebrahimi caller: Optional[str] = None) -> None: 78*62c56f98SSadaf Ebrahimi """Write the test cases to the specified file. 79*62c56f98SSadaf Ebrahimi 80*62c56f98SSadaf Ebrahimi If the file already exists, it is overwritten. 81*62c56f98SSadaf Ebrahimi """ 82*62c56f98SSadaf Ebrahimi if caller is None: 83*62c56f98SSadaf Ebrahimi caller = os.path.basename(sys.argv[0]) 84*62c56f98SSadaf Ebrahimi tempfile = filename + '.new' 85*62c56f98SSadaf Ebrahimi with open(tempfile, 'w') as out: 86*62c56f98SSadaf Ebrahimi out.write('# Automatically generated by {}. Do not edit!\n' 87*62c56f98SSadaf Ebrahimi .format(caller)) 88*62c56f98SSadaf Ebrahimi for tc in test_cases: 89*62c56f98SSadaf Ebrahimi tc.write(out) 90*62c56f98SSadaf Ebrahimi out.write('\n# End of automatically generated file.\n') 91*62c56f98SSadaf Ebrahimi os.replace(tempfile, filename) 92