Merge branch 'development' into sha3
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
commit
d06c6fc45b
405 changed files with 28422 additions and 16737 deletions
File diff suppressed because it is too large
Load diff
|
@ -10,6 +10,8 @@ import argparse
|
|||
import sys
|
||||
import traceback
|
||||
import re
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
import check_test_cases
|
||||
|
||||
|
@ -51,6 +53,26 @@ class TestCaseOutcomes:
|
|||
"""
|
||||
return len(self.successes) + len(self.failures)
|
||||
|
||||
def execute_reference_driver_tests(ref_component, driver_component, outcome_file):
|
||||
"""Run the tests specified in ref_component and driver_component. Results
|
||||
are stored in the output_file and they will be used for the following
|
||||
coverage analysis"""
|
||||
# If the outcome file already exists, we assume that the user wants to
|
||||
# perform the comparison analysis again without repeating the tests.
|
||||
if os.path.exists(outcome_file):
|
||||
Results.log("Outcome file (" + outcome_file + ") already exists. " + \
|
||||
"Tests will be skipped.")
|
||||
return
|
||||
|
||||
shell_command = "tests/scripts/all.sh --outcome-file " + outcome_file + \
|
||||
" " + ref_component + " " + driver_component
|
||||
Results.log("Running: " + shell_command)
|
||||
ret_val = subprocess.run(shell_command.split(), check=False).returncode
|
||||
|
||||
if ret_val != 0:
|
||||
Results.log("Error: failed to run reference/driver components")
|
||||
sys.exit(ret_val)
|
||||
|
||||
def analyze_coverage(results, outcomes):
|
||||
"""Check that all available test cases are executed at least once."""
|
||||
available = check_test_cases.collect_available_test_cases()
|
||||
|
@ -82,7 +104,7 @@ def analyze_driver_vs_reference(outcomes, component_ref, component_driver,
|
|||
full_test_suite = key.split(';')[0] # retrieve full test suite name
|
||||
test_string = key.split(';')[1] # retrieve the text string of this test
|
||||
test_suite = full_test_suite.split('.')[0] # retrieve main part of test suite name
|
||||
if test_suite in ignored_suites:
|
||||
if test_suite in ignored_suites or full_test_suite in ignored_suites:
|
||||
continue
|
||||
if ((full_test_suite in ignored_test) and
|
||||
(test_string in ignored_test[full_test_suite])):
|
||||
|
@ -96,7 +118,7 @@ def analyze_driver_vs_reference(outcomes, component_ref, component_driver,
|
|||
if component_ref in entry:
|
||||
reference_test_passed = True
|
||||
if(reference_test_passed and not driver_test_passed):
|
||||
print(key)
|
||||
Results.log(key)
|
||||
result = False
|
||||
return result
|
||||
|
||||
|
@ -131,16 +153,19 @@ def do_analyze_coverage(outcome_file, args):
|
|||
"""Perform coverage analysis."""
|
||||
del args # unused
|
||||
outcomes = read_outcome_file(outcome_file)
|
||||
print("\n*** Analyze coverage ***\n")
|
||||
Results.log("\n*** Analyze coverage ***\n")
|
||||
results = analyze_outcomes(outcomes)
|
||||
return results.error_count == 0
|
||||
|
||||
def do_analyze_driver_vs_reference(outcome_file, args):
|
||||
"""Perform driver vs reference analyze."""
|
||||
execute_reference_driver_tests(args['component_ref'], \
|
||||
args['component_driver'], outcome_file)
|
||||
|
||||
ignored_suites = ['test_suite_' + x for x in args['ignored_suites']]
|
||||
|
||||
outcomes = read_outcome_file(outcome_file)
|
||||
print("\n*** Analyze driver {} vs reference {} ***\n".format(
|
||||
Results.log("\n*** Analyze driver {} vs reference {} ***\n".format(
|
||||
args['component_driver'], args['component_ref']))
|
||||
return analyze_driver_vs_reference(outcomes, args['component_ref'],
|
||||
args['component_driver'], ignored_suites,
|
||||
|
@ -152,9 +177,12 @@ TASKS = {
|
|||
'test_function': do_analyze_coverage,
|
||||
'args': {}
|
||||
},
|
||||
# How to use analyze_driver_vs_reference_xxx locally:
|
||||
# 1. tests/scripts/all.sh --outcome-file "$PWD/out.csv" <component_ref> <component_driver>
|
||||
# 2. tests/scripts/analyze_outcomes.py out.csv analyze_driver_vs_reference_xxx
|
||||
# There are 2 options to use analyze_driver_vs_reference_xxx locally:
|
||||
# 1. Run tests and then analysis:
|
||||
# - tests/scripts/all.sh --outcome-file "$PWD/out.csv" <component_ref> <component_driver>
|
||||
# - tests/scripts/analyze_outcomes.py out.csv analyze_driver_vs_reference_xxx
|
||||
# 2. Let this script run both automatically:
|
||||
# - tests/scripts/analyze_outcomes.py out.csv analyze_driver_vs_reference_xxx
|
||||
'analyze_driver_vs_reference_hash': {
|
||||
'test_function': do_analyze_driver_vs_reference,
|
||||
'args': {
|
||||
|
@ -162,24 +190,99 @@ TASKS = {
|
|||
'component_driver': 'test_psa_crypto_config_accel_hash_use_psa',
|
||||
'ignored_suites': [
|
||||
'shax', 'mdx', # the software implementations that are being excluded
|
||||
'md', # the legacy abstraction layer that's being excluded
|
||||
'md.psa', # purposefully depends on whether drivers are present
|
||||
],
|
||||
'ignored_tests': {
|
||||
}
|
||||
}
|
||||
},
|
||||
'analyze_driver_vs_reference_ecdsa': {
|
||||
'analyze_driver_vs_reference_all_ec_algs': {
|
||||
'test_function': do_analyze_driver_vs_reference,
|
||||
'args': {
|
||||
'component_ref': 'test_psa_crypto_config_reference_ecdsa_use_psa',
|
||||
'component_driver': 'test_psa_crypto_config_accel_ecdsa_use_psa',
|
||||
'component_ref': 'test_psa_crypto_config_reference_all_ec_algs_use_psa',
|
||||
'component_driver': 'test_psa_crypto_config_accel_all_ec_algs_use_psa',
|
||||
'ignored_suites': [
|
||||
'ecdsa', # the software implementation that's excluded
|
||||
'ecdsa',
|
||||
'ecdh',
|
||||
'ecjpake',
|
||||
],
|
||||
'ignored_tests': {
|
||||
'test_suite_random': [
|
||||
'PSA classic wrapper: ECDSA signature (SECP256R1)',
|
||||
],
|
||||
# In the accelerated test ECP_C is not set (only ECP_LIGHT is)
|
||||
# so we must ignore disparities in the tests for which ECP_C
|
||||
# is required.
|
||||
'test_suite_ecp': [
|
||||
'ECP check public-private #1 (OK)',
|
||||
'ECP check public-private #2 (group none)',
|
||||
'ECP check public-private #3 (group mismatch)',
|
||||
'ECP check public-private #4 (Qx mismatch)',
|
||||
'ECP check public-private #5 (Qy mismatch)',
|
||||
'ECP check public-private #6 (wrong Qx)',
|
||||
'ECP check public-private #7 (wrong Qy)',
|
||||
'ECP gen keypair [#1]',
|
||||
'ECP gen keypair [#2]',
|
||||
'ECP gen keypair [#3]',
|
||||
'ECP gen keypair wrapper',
|
||||
'ECP point muladd secp256r1 #1',
|
||||
'ECP point muladd secp256r1 #2',
|
||||
'ECP point multiplication Curve25519 (element of order 2: origin) #3',
|
||||
'ECP point multiplication Curve25519 (element of order 4: 1) #4',
|
||||
'ECP point multiplication Curve25519 (element of order 8) #5',
|
||||
'ECP point multiplication Curve25519 (normalized) #1',
|
||||
'ECP point multiplication Curve25519 (not normalized) #2',
|
||||
'ECP point multiplication rng fail Curve25519',
|
||||
'ECP point multiplication rng fail secp256r1',
|
||||
'ECP test vectors Curve25519',
|
||||
'ECP test vectors Curve448 (RFC 7748 6.2, after decodeUCoordinate)',
|
||||
'ECP test vectors brainpoolP256r1 rfc 7027',
|
||||
'ECP test vectors brainpoolP384r1 rfc 7027',
|
||||
'ECP test vectors brainpoolP512r1 rfc 7027',
|
||||
'ECP test vectors secp192k1',
|
||||
'ECP test vectors secp192r1 rfc 5114',
|
||||
'ECP test vectors secp224k1',
|
||||
'ECP test vectors secp224r1 rfc 5114',
|
||||
'ECP test vectors secp256k1',
|
||||
'ECP test vectors secp256r1 rfc 5114',
|
||||
'ECP test vectors secp384r1 rfc 5114',
|
||||
'ECP test vectors secp521r1 rfc 5114',
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
'analyze_driver_vs_reference_all_ec_algs_no_ecp': {
|
||||
'test_function': do_analyze_driver_vs_reference,
|
||||
'args': {
|
||||
'component_ref': 'test_psa_crypto_full_reference_all_ec_algs_no_ecp_use_psa',
|
||||
'component_driver': 'test_psa_crypto_full_accel_all_ec_algs_no_ecp_use_psa',
|
||||
'ignored_suites': [
|
||||
# Ignore test suites for the modules that are disabled in the
|
||||
# accelerated test case.
|
||||
'ecp',
|
||||
'ecdsa',
|
||||
'ecdh',
|
||||
'ecjpake',
|
||||
],
|
||||
'ignored_tests': {
|
||||
'test_suite_random': [
|
||||
'PSA classic wrapper: ECDSA signature (SECP256R1)',
|
||||
],
|
||||
'test_suite_psa_crypto': [
|
||||
'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1',
|
||||
'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1 (1 redraw)',
|
||||
'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1, exercise ECDSA',
|
||||
'PSA key derivation: HKDF-SHA-256 -> ECC secp384r1',
|
||||
'PSA key derivation: HKDF-SHA-256 -> ECC secp521r1 #0',
|
||||
'PSA key derivation: HKDF-SHA-256 -> ECC secp521r1 #1',
|
||||
'PSA key derivation: bits=7 invalid for ECC BRAINPOOL_P_R1 (ECC enabled)',
|
||||
'PSA key derivation: bits=7 invalid for ECC SECP_K1 (ECC enabled)',
|
||||
'PSA key derivation: bits=7 invalid for ECC SECP_R1 (ECC enabled)',
|
||||
'PSA key derivation: bits=7 invalid for ECC SECP_R2 (ECC enabled)',
|
||||
'PSA key derivation: bits=7 invalid for ECC SECT_K1 (ECC enabled)',
|
||||
'PSA key derivation: bits=7 invalid for ECC SECT_R1 (ECC enabled)',
|
||||
'PSA key derivation: bits=7 invalid for ECC SECT_R2 (ECC enabled)',
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -201,7 +304,7 @@ def main():
|
|||
|
||||
if options.list:
|
||||
for task in TASKS:
|
||||
print(task)
|
||||
Results.log(task)
|
||||
sys.exit(0)
|
||||
|
||||
result = True
|
||||
|
@ -213,7 +316,7 @@ def main():
|
|||
|
||||
for task in tasks:
|
||||
if task not in TASKS:
|
||||
print('Error: invalid task: {}'.format(task))
|
||||
Results.log('Error: invalid task: {}'.format(task))
|
||||
sys.exit(1)
|
||||
|
||||
for task in TASKS:
|
||||
|
@ -223,7 +326,7 @@ def main():
|
|||
|
||||
if result is False:
|
||||
sys.exit(1)
|
||||
print("SUCCESS :-)")
|
||||
Results.log("SUCCESS :-)")
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# Print the backtrace and exit explicitly with our chosen status.
|
||||
traceback.print_exc()
|
||||
|
|
|
@ -277,7 +277,7 @@ REVERSE_DEPENDENCIES = {
|
|||
# if a given define is the only one enabled from an exclusive group.
|
||||
EXCLUSIVE_GROUPS = {
|
||||
'MBEDTLS_SHA512_C': ['-MBEDTLS_SSL_COOKIE_C',
|
||||
'-MBEDTLS_SSL_PROTO_TLS1_3'],
|
||||
'-MBEDTLS_SSL_TLS_C'],
|
||||
'MBEDTLS_ECP_DP_CURVE448_ENABLED': ['-MBEDTLS_ECDSA_C',
|
||||
'-MBEDTLS_ECDSA_DETERMINISTIC',
|
||||
'-MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED',
|
||||
|
|
|
@ -49,7 +49,7 @@ class TestData:
|
|||
Take in test_suite_pkcs7.data file.
|
||||
Allow for new tests to be added.
|
||||
"""
|
||||
mandatory_dep = "MBEDTLS_SHA256_C"
|
||||
mandatory_dep = "MBEDTLS_MD_CAN_SHA256"
|
||||
test_name = "PKCS7 Parse Failure Invalid ASN1"
|
||||
test_function = "pkcs7_asn1_fail:"
|
||||
def __init__(self, file_name):
|
||||
|
|
|
@ -171,6 +171,28 @@ import string
|
|||
import argparse
|
||||
|
||||
|
||||
# Types recognized as signed integer arguments in test functions.
|
||||
SIGNED_INTEGER_TYPES = frozenset([
|
||||
'char',
|
||||
'short',
|
||||
'short int',
|
||||
'int',
|
||||
'int8_t',
|
||||
'int16_t',
|
||||
'int32_t',
|
||||
'int64_t',
|
||||
'intmax_t',
|
||||
'long',
|
||||
'long int',
|
||||
'long long int',
|
||||
'mbedtls_mpi_sint',
|
||||
'psa_status_t',
|
||||
])
|
||||
# Types recognized as string arguments in test functions.
|
||||
STRING_TYPES = frozenset(['char*', 'const char*', 'char const*'])
|
||||
# Types recognized as hex data arguments in test functions.
|
||||
DATA_TYPES = frozenset(['data_t*', 'const data_t*', 'data_t const*'])
|
||||
|
||||
BEGIN_HEADER_REGEX = r'/\*\s*BEGIN_HEADER\s*\*/'
|
||||
END_HEADER_REGEX = r'/\*\s*END_HEADER\s*\*/'
|
||||
|
||||
|
@ -192,9 +214,6 @@ CONDITION_REGEX = r'({})(?:\s*({})\s*({}))?$'.format(C_IDENTIFIER_REGEX,
|
|||
CONDITION_OPERATOR_REGEX,
|
||||
CONDITION_VALUE_REGEX)
|
||||
TEST_FUNCTION_VALIDATION_REGEX = r'\s*void\s+(?P<func_name>\w+)\s*\('
|
||||
INT_CHECK_REGEX = r'int\s+.*'
|
||||
CHAR_CHECK_REGEX = r'char\s*\*\s*.*'
|
||||
DATA_T_CHECK_REGEX = r'data_t\s*\*\s*.*'
|
||||
FUNCTION_ARG_LIST_END_REGEX = r'.*\)'
|
||||
EXIT_LABEL_REGEX = r'^exit:'
|
||||
|
||||
|
@ -303,7 +322,7 @@ def gen_function_wrapper(name, local_vars, args_dispatch):
|
|||
:param name: Test function name
|
||||
:param local_vars: Local variables declaration code
|
||||
:param args_dispatch: List of dispatch arguments.
|
||||
Ex: ['(char *)params[0]', '*((int *)params[1])']
|
||||
Ex: ['(char *) params[0]', '*((int *) params[1])']
|
||||
:return: Test function wrapper.
|
||||
"""
|
||||
# Then create the wrapper
|
||||
|
@ -444,6 +463,49 @@ def parse_function_dependencies(line):
|
|||
return dependencies
|
||||
|
||||
|
||||
ARGUMENT_DECLARATION_REGEX = re.compile(r'(.+?) ?(?:\bconst\b)? ?(\w+)\Z', re.S)
|
||||
def parse_function_argument(arg, arg_idx, args, local_vars, args_dispatch):
|
||||
"""
|
||||
Parses one test function's argument declaration.
|
||||
|
||||
:param arg: argument declaration.
|
||||
:param arg_idx: current wrapper argument index.
|
||||
:param args: accumulator of arguments' internal types.
|
||||
:param local_vars: accumulator of internal variable declarations.
|
||||
:param args_dispatch: accumulator of argument usage expressions.
|
||||
:return: the number of new wrapper arguments,
|
||||
or None if the argument declaration is invalid.
|
||||
"""
|
||||
# Normalize whitespace
|
||||
arg = arg.strip()
|
||||
arg = re.sub(r'\s*\*\s*', r'*', arg)
|
||||
arg = re.sub(r'\s+', r' ', arg)
|
||||
# Extract name and type
|
||||
m = ARGUMENT_DECLARATION_REGEX.search(arg)
|
||||
if not m:
|
||||
# E.g. "int x[42]"
|
||||
return None
|
||||
typ, _ = m.groups()
|
||||
if typ in SIGNED_INTEGER_TYPES:
|
||||
args.append('int')
|
||||
args_dispatch.append('((mbedtls_test_argument_t *) params[%d])->sint' % arg_idx)
|
||||
return 1
|
||||
if typ in STRING_TYPES:
|
||||
args.append('char*')
|
||||
args_dispatch.append('(char *) params[%d]' % arg_idx)
|
||||
return 1
|
||||
if typ in DATA_TYPES:
|
||||
args.append('hex')
|
||||
# create a structure
|
||||
pointer_initializer = '(uint8_t *) params[%d]' % arg_idx
|
||||
len_initializer = '((mbedtls_test_argument_t *) params[%d])->len' % (arg_idx+1)
|
||||
local_vars.append(' data_t data%d = {%s, %s};\n' %
|
||||
(arg_idx, pointer_initializer, len_initializer))
|
||||
args_dispatch.append('&data%d' % arg_idx)
|
||||
return 2
|
||||
return None
|
||||
|
||||
ARGUMENT_LIST_REGEX = re.compile(r'\((.*?)\)', re.S)
|
||||
def parse_function_arguments(line):
|
||||
"""
|
||||
Parses test function signature for validation and generates
|
||||
|
@ -455,42 +517,27 @@ def parse_function_arguments(line):
|
|||
:return: argument list, local variables for
|
||||
wrapper function and argument dispatch code.
|
||||
"""
|
||||
args = []
|
||||
local_vars = ''
|
||||
args_dispatch = []
|
||||
arg_idx = 0
|
||||
# Remove characters before arguments
|
||||
line = line[line.find('(') + 1:]
|
||||
# Process arguments, ex: <type> arg1, <type> arg2 )
|
||||
# This script assumes that the argument list is terminated by ')'
|
||||
# i.e. the test functions will not have a function pointer
|
||||
# argument.
|
||||
for arg in line[:line.find(')')].split(','):
|
||||
arg = arg.strip()
|
||||
if arg == '':
|
||||
continue
|
||||
if re.search(INT_CHECK_REGEX, arg.strip()):
|
||||
args.append('int')
|
||||
args_dispatch.append('*( (int *) params[%d] )' % arg_idx)
|
||||
elif re.search(CHAR_CHECK_REGEX, arg.strip()):
|
||||
args.append('char*')
|
||||
args_dispatch.append('(char *) params[%d]' % arg_idx)
|
||||
elif re.search(DATA_T_CHECK_REGEX, arg.strip()):
|
||||
args.append('hex')
|
||||
# create a structure
|
||||
pointer_initializer = '(uint8_t *) params[%d]' % arg_idx
|
||||
len_initializer = '*( (uint32_t *) params[%d] )' % (arg_idx+1)
|
||||
local_vars += """ data_t data%d = {%s, %s};
|
||||
""" % (arg_idx, pointer_initializer, len_initializer)
|
||||
|
||||
args_dispatch.append('&data%d' % arg_idx)
|
||||
arg_idx += 1
|
||||
else:
|
||||
m = ARGUMENT_LIST_REGEX.search(line)
|
||||
arg_list = m.group(1).strip()
|
||||
if arg_list in ['', 'void']:
|
||||
return [], '', []
|
||||
args = []
|
||||
local_vars = []
|
||||
args_dispatch = []
|
||||
arg_idx = 0
|
||||
for arg in arg_list.split(','):
|
||||
indexes = parse_function_argument(arg, arg_idx,
|
||||
args, local_vars, args_dispatch)
|
||||
if indexes is None:
|
||||
raise ValueError("Test function arguments can only be 'int', "
|
||||
"'char *' or 'data_t'\n%s" % line)
|
||||
arg_idx += 1
|
||||
arg_idx += indexes
|
||||
|
||||
return args, local_vars, args_dispatch
|
||||
return args, ''.join(local_vars), args_dispatch
|
||||
|
||||
|
||||
def generate_function_code(name, code, local_vars, args_dispatch,
|
||||
|
@ -705,7 +752,7 @@ def parse_test_data(data_f):
|
|||
execution.
|
||||
|
||||
:param data_f: file object of the data file.
|
||||
:return: Generator that yields test name, function name,
|
||||
:return: Generator that yields line number, test name, function name,
|
||||
dependency list and function argument list.
|
||||
"""
|
||||
__state_read_name = 0
|
||||
|
@ -748,7 +795,7 @@ def parse_test_data(data_f):
|
|||
parts = escaped_split(line, ':')
|
||||
test_function = parts[0]
|
||||
args = parts[1:]
|
||||
yield name, test_function, dependencies, args
|
||||
yield data_f.line_no, name, test_function, dependencies, args
|
||||
dependencies = []
|
||||
state = __state_read_name
|
||||
if state == __state_read_args:
|
||||
|
@ -846,6 +893,14 @@ def write_dependencies(out_data_f, test_dependencies, unique_dependencies):
|
|||
return dep_check_code
|
||||
|
||||
|
||||
INT_VAL_REGEX = re.compile(r'-?(\d+|0x[0-9a-f]+)$', re.I)
|
||||
def val_is_int(val: str) -> bool:
|
||||
"""Whether val is suitable as an 'int' parameter in the .datax file."""
|
||||
if not INT_VAL_REGEX.match(val):
|
||||
return False
|
||||
# Limit the range to what is guaranteed to get through strtol()
|
||||
return abs(int(val, 0)) <= 0x7fffffff
|
||||
|
||||
def write_parameters(out_data_f, test_args, func_args, unique_expressions):
|
||||
"""
|
||||
Writes test parameters to the intermediate data file, replacing
|
||||
|
@ -864,9 +919,9 @@ def write_parameters(out_data_f, test_args, func_args, unique_expressions):
|
|||
typ = func_args[i]
|
||||
val = test_args[i]
|
||||
|
||||
# check if val is a non literal int val (i.e. an expression)
|
||||
if typ == 'int' and not re.match(r'(\d+|0x[0-9a-f]+)$',
|
||||
val, re.I):
|
||||
# Pass small integer constants literally. This reduces the size of
|
||||
# the C code. Register anything else as an expression.
|
||||
if typ == 'int' and not val_is_int(val):
|
||||
typ = 'exp'
|
||||
if val not in unique_expressions:
|
||||
unique_expressions.append(val)
|
||||
|
@ -909,6 +964,24 @@ def gen_suite_dep_checks(suite_dependencies, dep_check_code, expression_code):
|
|||
return dep_check_code, expression_code
|
||||
|
||||
|
||||
def get_function_info(func_info, function_name, line_no):
|
||||
"""Look up information about a test function by name.
|
||||
|
||||
Raise an informative expression if function_name is not found.
|
||||
|
||||
:param func_info: dictionary mapping function names to their information.
|
||||
:param function_name: the function name as written in the .function and
|
||||
.data files.
|
||||
:param line_no: line number for error messages.
|
||||
:return Function information (id, args).
|
||||
"""
|
||||
test_function_name = 'test_' + function_name
|
||||
if test_function_name not in func_info:
|
||||
raise GeneratorInputError("%d: Function %s not found!" %
|
||||
(line_no, test_function_name))
|
||||
return func_info[test_function_name]
|
||||
|
||||
|
||||
def gen_from_test_data(data_f, out_data_f, func_info, suite_dependencies):
|
||||
"""
|
||||
This function reads test case name, dependencies and test vectors
|
||||
|
@ -931,7 +1004,7 @@ def gen_from_test_data(data_f, out_data_f, func_info, suite_dependencies):
|
|||
unique_expressions = []
|
||||
dep_check_code = ''
|
||||
expression_code = ''
|
||||
for test_name, function_name, test_dependencies, test_args in \
|
||||
for line_no, test_name, function_name, test_dependencies, test_args in \
|
||||
parse_test_data(data_f):
|
||||
out_data_f.write(test_name + '\n')
|
||||
|
||||
|
@ -940,18 +1013,15 @@ def gen_from_test_data(data_f, out_data_f, func_info, suite_dependencies):
|
|||
unique_dependencies)
|
||||
|
||||
# Write test function name
|
||||
test_function_name = 'test_' + function_name
|
||||
if test_function_name not in func_info:
|
||||
raise GeneratorInputError("Function %s not found!" %
|
||||
test_function_name)
|
||||
func_id, func_args = func_info[test_function_name]
|
||||
func_id, func_args = \
|
||||
get_function_info(func_info, function_name, line_no)
|
||||
out_data_f.write(str(func_id))
|
||||
|
||||
# Write parameters
|
||||
if len(test_args) != len(func_args):
|
||||
raise GeneratorInputError("Invalid number of arguments in test "
|
||||
raise GeneratorInputError("%d: Invalid number of arguments in test "
|
||||
"%s. See function %s signature." %
|
||||
(test_name, function_name))
|
||||
(line_no, test_name, function_name))
|
||||
expression_code += write_parameters(out_data_f, test_args, func_args,
|
||||
unique_expressions)
|
||||
|
||||
|
|
|
@ -352,7 +352,6 @@ class MbedTLSBase(TLSProgram):
|
|||
if self._named_groups:
|
||||
named_groups = ','.join(self._named_groups)
|
||||
ret += ["curves={named_groups}".format(named_groups=named_groups)]
|
||||
ret += ['force_version=tls13']
|
||||
return ret
|
||||
|
||||
def pre_checks(self):
|
||||
|
|
|
@ -485,9 +485,10 @@ class ParseFuncSignature(TestCase):
|
|||
args, local, arg_dispatch = parse_function_arguments(line)
|
||||
self.assertEqual(args, ['char*', 'int', 'int'])
|
||||
self.assertEqual(local, '')
|
||||
self.assertEqual(arg_dispatch, ['(char *) params[0]',
|
||||
'*( (int *) params[1] )',
|
||||
'*( (int *) params[2] )'])
|
||||
self.assertEqual(arg_dispatch,
|
||||
['(char *) params[0]',
|
||||
'((mbedtls_test_argument_t *) params[1])->sint',
|
||||
'((mbedtls_test_argument_t *) params[2])->sint'])
|
||||
|
||||
def test_hex_params(self):
|
||||
"""
|
||||
|
@ -499,22 +500,22 @@ class ParseFuncSignature(TestCase):
|
|||
self.assertEqual(args, ['char*', 'hex', 'int'])
|
||||
self.assertEqual(local,
|
||||
' data_t data1 = {(uint8_t *) params[1], '
|
||||
'*( (uint32_t *) params[2] )};\n')
|
||||
'((mbedtls_test_argument_t *) params[2])->len};\n')
|
||||
self.assertEqual(arg_dispatch, ['(char *) params[0]',
|
||||
'&data1',
|
||||
'*( (int *) params[3] )'])
|
||||
'((mbedtls_test_argument_t *) params[3])->sint'])
|
||||
|
||||
def test_unsupported_arg(self):
|
||||
"""
|
||||
Test unsupported arguments (not among int, char * and data_t)
|
||||
Test unsupported argument type
|
||||
:return:
|
||||
"""
|
||||
line = 'void entropy_threshold( char * a, data_t * h, char result )'
|
||||
line = 'void entropy_threshold( char * a, data_t * h, unknown_t result )'
|
||||
self.assertRaises(ValueError, parse_function_arguments, line)
|
||||
|
||||
def test_no_params(self):
|
||||
def test_empty_params(self):
|
||||
"""
|
||||
Test no parameters.
|
||||
Test no parameters (nothing between parentheses).
|
||||
:return:
|
||||
"""
|
||||
line = 'void entropy_threshold()'
|
||||
|
@ -523,6 +524,39 @@ class ParseFuncSignature(TestCase):
|
|||
self.assertEqual(local, '')
|
||||
self.assertEqual(arg_dispatch, [])
|
||||
|
||||
def test_blank_params(self):
|
||||
"""
|
||||
Test no parameters (space between parentheses).
|
||||
:return:
|
||||
"""
|
||||
line = 'void entropy_threshold( )'
|
||||
args, local, arg_dispatch = parse_function_arguments(line)
|
||||
self.assertEqual(args, [])
|
||||
self.assertEqual(local, '')
|
||||
self.assertEqual(arg_dispatch, [])
|
||||
|
||||
def test_void_params(self):
|
||||
"""
|
||||
Test no parameters (void keyword).
|
||||
:return:
|
||||
"""
|
||||
line = 'void entropy_threshold(void)'
|
||||
args, local, arg_dispatch = parse_function_arguments(line)
|
||||
self.assertEqual(args, [])
|
||||
self.assertEqual(local, '')
|
||||
self.assertEqual(arg_dispatch, [])
|
||||
|
||||
def test_void_space_params(self):
|
||||
"""
|
||||
Test no parameters (void with spaces).
|
||||
:return:
|
||||
"""
|
||||
line = 'void entropy_threshold( void )'
|
||||
args, local, arg_dispatch = parse_function_arguments(line)
|
||||
self.assertEqual(args, [])
|
||||
self.assertEqual(local, '')
|
||||
self.assertEqual(arg_dispatch, [])
|
||||
|
||||
|
||||
class ParseFunctionCode(TestCase):
|
||||
"""
|
||||
|
@ -1264,29 +1298,33 @@ dhm_selftest:
|
|||
# List of (name, function_name, dependencies, args)
|
||||
tests = list(parse_test_data(stream))
|
||||
test1, test2, test3, test4 = tests
|
||||
self.assertEqual(test1[0], 'Diffie-Hellman full exchange #1')
|
||||
self.assertEqual(test1[1], 'dhm_do_dhm')
|
||||
self.assertEqual(test1[2], [])
|
||||
self.assertEqual(test1[3], ['10', '"23"', '10', '"5"'])
|
||||
self.assertEqual(test1[0], 3)
|
||||
self.assertEqual(test1[1], 'Diffie-Hellman full exchange #1')
|
||||
self.assertEqual(test1[2], 'dhm_do_dhm')
|
||||
self.assertEqual(test1[3], [])
|
||||
self.assertEqual(test1[4], ['10', '"23"', '10', '"5"'])
|
||||
|
||||
self.assertEqual(test2[0], 'Diffie-Hellman full exchange #2')
|
||||
self.assertEqual(test2[1], 'dhm_do_dhm')
|
||||
self.assertEqual(test2[2], [])
|
||||
self.assertEqual(test2[3], ['10', '"93450983094850938450983409623"',
|
||||
self.assertEqual(test2[0], 6)
|
||||
self.assertEqual(test2[1], 'Diffie-Hellman full exchange #2')
|
||||
self.assertEqual(test2[2], 'dhm_do_dhm')
|
||||
self.assertEqual(test2[3], [])
|
||||
self.assertEqual(test2[4], ['10', '"93450983094850938450983409623"',
|
||||
'10', '"9345098304850938450983409622"'])
|
||||
|
||||
self.assertEqual(test3[0], 'Diffie-Hellman full exchange #3')
|
||||
self.assertEqual(test3[1], 'dhm_do_dhm')
|
||||
self.assertEqual(test3[2], [])
|
||||
self.assertEqual(test3[3], ['10',
|
||||
self.assertEqual(test3[0], 9)
|
||||
self.assertEqual(test3[1], 'Diffie-Hellman full exchange #3')
|
||||
self.assertEqual(test3[2], 'dhm_do_dhm')
|
||||
self.assertEqual(test3[3], [])
|
||||
self.assertEqual(test3[4], ['10',
|
||||
'"9345098382739712938719287391879381271"',
|
||||
'10',
|
||||
'"9345098792137312973297123912791271"'])
|
||||
|
||||
self.assertEqual(test4[0], 'Diffie-Hellman selftest')
|
||||
self.assertEqual(test4[1], 'dhm_selftest')
|
||||
self.assertEqual(test4[2], [])
|
||||
self.assertEqual(test4[0], 12)
|
||||
self.assertEqual(test4[1], 'Diffie-Hellman selftest')
|
||||
self.assertEqual(test4[2], 'dhm_selftest')
|
||||
self.assertEqual(test4[3], [])
|
||||
self.assertEqual(test4[4], [])
|
||||
|
||||
def test_with_dependencies(self):
|
||||
"""
|
||||
|
@ -1306,15 +1344,17 @@ dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
|
|||
# List of (name, function_name, dependencies, args)
|
||||
tests = list(parse_test_data(stream))
|
||||
test1, test2 = tests
|
||||
self.assertEqual(test1[0], 'Diffie-Hellman full exchange #1')
|
||||
self.assertEqual(test1[1], 'dhm_do_dhm')
|
||||
self.assertEqual(test1[2], ['YAHOO'])
|
||||
self.assertEqual(test1[3], ['10', '"23"', '10', '"5"'])
|
||||
self.assertEqual(test1[0], 4)
|
||||
self.assertEqual(test1[1], 'Diffie-Hellman full exchange #1')
|
||||
self.assertEqual(test1[2], 'dhm_do_dhm')
|
||||
self.assertEqual(test1[3], ['YAHOO'])
|
||||
self.assertEqual(test1[4], ['10', '"23"', '10', '"5"'])
|
||||
|
||||
self.assertEqual(test2[0], 'Diffie-Hellman full exchange #2')
|
||||
self.assertEqual(test2[1], 'dhm_do_dhm')
|
||||
self.assertEqual(test2[2], [])
|
||||
self.assertEqual(test2[3], ['10', '"93450983094850938450983409623"',
|
||||
self.assertEqual(test2[0], 7)
|
||||
self.assertEqual(test2[1], 'Diffie-Hellman full exchange #2')
|
||||
self.assertEqual(test2[2], 'dhm_do_dhm')
|
||||
self.assertEqual(test2[3], [])
|
||||
self.assertEqual(test2[4], ['10', '"93450983094850938450983409623"',
|
||||
'10', '"9345098304850938450983409622"'])
|
||||
|
||||
def test_no_args(self):
|
||||
|
@ -1335,7 +1375,7 @@ dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
|
|||
stream = StringIOWrapper('test_suite_ut.function', data)
|
||||
err = None
|
||||
try:
|
||||
for _, _, _, _ in parse_test_data(stream):
|
||||
for _, _, _, _, _ in parse_test_data(stream):
|
||||
pass
|
||||
except GeneratorInputError as err:
|
||||
self.assertEqual(type(err), GeneratorInputError)
|
||||
|
@ -1353,7 +1393,7 @@ depends_on:YAHOO
|
|||
stream = StringIOWrapper('test_suite_ut.function', data)
|
||||
err = None
|
||||
try:
|
||||
for _, _, _, _ in parse_test_data(stream):
|
||||
for _, _, _, _, _ in parse_test_data(stream):
|
||||
pass
|
||||
except GeneratorInputError as err:
|
||||
self.assertEqual(type(err), GeneratorInputError)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue