1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-08-08 17:42:09 +03:00

Merge remote-tracking branch 'origin/development' into sha-armce-thumb2

Signed-off-by: Dave Rodgman <dave.rodgman@arm.com>
This commit is contained in:
Dave Rodgman
2023-10-23 15:35:07 +01:00
54 changed files with 1697 additions and 1103 deletions

View File

@@ -50,10 +50,13 @@
# * G++
# * arm-gcc and mingw-gcc
# * ArmCC 5 and ArmCC 6, unless invoked with --no-armcc
# * OpenSSL and GnuTLS command line tools, recent enough for the
# interoperability tests. If they don't support old features which we want
# to test, then a legacy version of these tools must be present as well
# (search for LEGACY below).
# * OpenSSL and GnuTLS command line tools, in suitable versions for the
# interoperability tests. The following are the official versions at the
# time of writing:
# * GNUTLS_{CLI,SERV} = 3.4.10
# * GNUTLS_NEXT_{CLI,SERV} = 3.7.2
# * OPENSSL = 1.0.2g (without Debian/Ubuntu patches)
# * OPENSSL_NEXT = 1.1.1a
# See the invocation of check_tools below for details.
#
# This script must be invoked from the toplevel directory of a git
@@ -179,12 +182,9 @@ pre_initialize_variables () {
# Default commands, can be overridden by the environment
: ${OPENSSL:="openssl"}
: ${OPENSSL_LEGACY:="$OPENSSL"}
: ${OPENSSL_NEXT:="$OPENSSL"}
: ${GNUTLS_CLI:="gnutls-cli"}
: ${GNUTLS_SERV:="gnutls-serv"}
: ${GNUTLS_LEGACY_CLI:="$GNUTLS_CLI"}
: ${GNUTLS_LEGACY_SERV:="$GNUTLS_SERV"}
: ${OUT_OF_SOURCE_DIR:=./mbedtls_out_of_source_build}
: ${ARMC5_BIN_DIR:=/usr/bin}
: ${ARMC6_BIN_DIR:=/usr/bin}
@@ -300,10 +300,7 @@ Tool path options:
--gcc-latest=<GCC_latest_path> Latest version of GCC available
--gnutls-cli=<GnuTLS_cli_path> GnuTLS client executable to use for most tests.
--gnutls-serv=<GnuTLS_serv_path> GnuTLS server executable to use for most tests.
--gnutls-legacy-cli=<GnuTLS_cli_path> GnuTLS client executable to use for legacy tests.
--gnutls-legacy-serv=<GnuTLS_serv_path> GnuTLS server executable to use for legacy tests.
--openssl=<OpenSSL_path> OpenSSL executable to use for most tests.
--openssl-legacy=<OpenSSL_path> OpenSSL executable to use for legacy tests..
--openssl-next=<OpenSSL_path> OpenSSL executable to use for recent things like ARIA
EOF
}
@@ -474,8 +471,8 @@ pre_parse_command_line () {
--gcc-earliest) shift; GCC_EARLIEST="$1";;
--gcc-latest) shift; GCC_LATEST="$1";;
--gnutls-cli) shift; GNUTLS_CLI="$1";;
--gnutls-legacy-cli) shift; GNUTLS_LEGACY_CLI="$1";;
--gnutls-legacy-serv) shift; GNUTLS_LEGACY_SERV="$1";;
--gnutls-legacy-cli) shift;; # ignored for backward compatibility
--gnutls-legacy-serv) shift;; # ignored for backward compatibility
--gnutls-serv) shift; GNUTLS_SERV="$1";;
--help|-h) usage; exit;;
--keep-going|-k) KEEP_GOING=1;;
@@ -489,7 +486,6 @@ pre_parse_command_line () {
--no-memory) MEMORY=0;;
--no-quiet) QUIET=0;;
--openssl) shift; OPENSSL="$1";;
--openssl-legacy) shift; OPENSSL_LEGACY="$1";;
--openssl-next) shift; OPENSSL_NEXT="$1";;
--outcome-file) shift; MBEDTLS_TEST_OUTCOME_FILE="$1";;
--out-of-source-dir) shift; OUT_OF_SOURCE_DIR="$1";;
@@ -744,12 +740,9 @@ pre_print_configuration () {
echo "SEED: ${SEED-"UNSET"}"
echo
echo "OPENSSL: $OPENSSL"
echo "OPENSSL_LEGACY: $OPENSSL_LEGACY"
echo "OPENSSL_NEXT: $OPENSSL_NEXT"
echo "GNUTLS_CLI: $GNUTLS_CLI"
echo "GNUTLS_SERV: $GNUTLS_SERV"
echo "GNUTLS_LEGACY_CLI: $GNUTLS_LEGACY_CLI"
echo "GNUTLS_LEGACY_SERV: $GNUTLS_LEGACY_SERV"
echo "ARMC5_BIN_DIR: $ARMC5_BIN_DIR"
echo "ARMC6_BIN_DIR: $ARMC6_BIN_DIR"
}
@@ -773,13 +766,10 @@ pre_check_tools () {
if [ -n "${SEED-}" ]; then
export SEED
fi
set "$@" OPENSSL="$OPENSSL" OPENSSL_LEGACY="$OPENSSL_LEGACY"
set "$@" OPENSSL="$OPENSSL"
set "$@" GNUTLS_CLI="$GNUTLS_CLI" GNUTLS_SERV="$GNUTLS_SERV"
set "$@" GNUTLS_LEGACY_CLI="$GNUTLS_LEGACY_CLI"
set "$@" GNUTLS_LEGACY_SERV="$GNUTLS_LEGACY_SERV"
check_tools "$OPENSSL" "$OPENSSL_LEGACY" "$OPENSSL_NEXT" \
"$GNUTLS_CLI" "$GNUTLS_SERV" \
"$GNUTLS_LEGACY_CLI" "$GNUTLS_LEGACY_SERV"
check_tools "$OPENSSL" "$OPENSSL_NEXT" \
"$GNUTLS_CLI" "$GNUTLS_SERV"
;;
esac
@@ -874,7 +864,7 @@ pre_generate_files() {
# Example:
# loc_extra_list="ALG_SHA_224 ALG_SHA_256 ALG_SHA_384 ALG_SHA_512"
# helper_libtestdriver1_make_drivers "$loc_accel_list" "$loc_extra_list"
# 4b. Call helper_libtestdriver1_make_main "$loc_accel_list". Any
# 3b. Call helper_libtestdriver1_make_main "$loc_accel_list". Any
# additional arguments will be passed to make: this can be useful if
# you don't want to build everything when iterating during development.
# Example:
@@ -1073,6 +1063,9 @@ component_test_default_out_of_box () {
msg "selftest: make, default config (out-of-box)" # ~10s
programs/test/selftest
msg "program demos: make, default config (out-of-box)" # ~10s
tests/scripts/run_demos.py
}
component_test_default_cmake_gcc_asan () {
@@ -1083,6 +1076,9 @@ component_test_default_cmake_gcc_asan () {
msg "test: main suites (inc. selftests) (ASan build)" # ~ 50s
make test
msg "program demos (ASan build)" # ~10s
tests/scripts/run_demos.py
msg "test: selftest (ASan build)" # ~ 10s
programs/test/selftest
@@ -1872,6 +1868,9 @@ component_test_full_cmake_clang () {
msg "test: cpp_dummy_build (full config, clang)" # ~ 1s
programs/test/cpp_dummy_build
msg "program demos (full config, clang)" # ~10s
tests/scripts/run_demos.py
msg "test: psa_constant_names (full config, clang)" # ~ 1s
tests/scripts/test_psa_constant_names.py
@@ -1879,7 +1878,7 @@ component_test_full_cmake_clang () {
tests/ssl-opt.sh -f 'Default\|ECJPAKE\|SSL async private'
msg "test: compat.sh NULL (full config)" # ~ 2 min
env OPENSSL="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -e '^$' -f 'NULL'
tests/compat.sh -e '^$' -f 'NULL'
msg "test: compat.sh ARIA + ChachaPoly"
env OPENSSL="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
@@ -2055,6 +2054,9 @@ component_test_full_deprecated_warning () {
msg "test: full config + MBEDTLS_TEST_DEPRECATED" # ~ 30s
make test
msg "program demos: full config + MBEDTLS_TEST_DEPRECATED" # ~10s
tests/scripts/run_demos.py
}
# Check that the specified libraries exist and are empty.
@@ -2286,7 +2288,7 @@ component_test_no_use_psa_crypto_full_cmake_asan() {
tests/compat.sh
msg "test: compat.sh NULL (full minus MBEDTLS_USE_PSA_CRYPTO)"
env OPENSSL="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -f 'NULL'
tests/compat.sh -f 'NULL'
msg "test: compat.sh ARIA + ChachaPoly (full minus MBEDTLS_USE_PSA_CRYPTO)"
env OPENSSL="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
@@ -3526,21 +3528,21 @@ component_test_psa_crypto_config_reference_hash_use_psa() {
component_test_psa_crypto_config_accel_cipher () {
msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated cipher"
loc_accel_list="ALG_CBC_NO_PADDING ALG_CBC_PKCS7 ALG_CTR ALG_CFB ALG_OFB ALG_XTS KEY_TYPE_DES"
loc_accel_list="ALG_CBC_NO_PADDING ALG_CBC_PKCS7 \
ALG_CTR ALG_CFB ALG_OFB ALG_XTS \
KEY_TYPE_DES ALG_CMAC"
# Configure
# ---------
# Start from the default config (no TLS 1.3, no USE_PSA)
helper_libtestdriver1_adjust_config "default"
# There is no intended accelerator support for STREAM_CIPHER and
# ECB_NO_PADDING. Therefore, asking for them in the build implies the
# inclusion of the Mbed TLS cipher operations. As we want to test here with
# cipher operations solely supported by accelerators, disabled those
# PSA configuration options by helper_libtestdriver1_adjust_config.
# There is no intended accelerator support for ALG CMAC. Therefore, asking
# for it in the build implies the inclusion of the Mbed TLS cipher
# operations. As we want to test here with cipher operations solely
# supported by accelerators, disabled this PSA configuration option.
# (Note: the same applies to STREAM_CIPHER and ECB_NO_PADDING, which are
# already disabled by helper_libtestdriver1_adjust_config above.)
scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_CMAC
# Start from the full config
helper_libtestdriver1_adjust_config "full"
# Disable the things that are being accelerated
scripts/config.py unset MBEDTLS_CIPHER_MODE_CBC
@@ -3550,6 +3552,7 @@ component_test_psa_crypto_config_accel_cipher () {
scripts/config.py unset MBEDTLS_CIPHER_MODE_OFB
scripts/config.py unset MBEDTLS_CIPHER_MODE_XTS
scripts/config.py unset MBEDTLS_DES_C
scripts/config.py unset MBEDTLS_CMAC_C
# Build
# -----
@@ -3571,21 +3574,19 @@ component_test_psa_crypto_config_accel_cipher () {
component_test_psa_crypto_config_accel_aead () {
msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated AEAD"
loc_accel_list="ALG_GCM ALG_CCM ALG_CHACHA20_POLY1305 KEY_TYPE_AES KEY_TYPE_CHACHA20 KEY_TYPE_ARIA KEY_TYPE_CAMELLIA"
loc_accel_list="ALG_GCM ALG_CCM ALG_CHACHA20_POLY1305 \
KEY_TYPE_AES KEY_TYPE_CHACHA20 KEY_TYPE_ARIA KEY_TYPE_CAMELLIA"
# Configure
# ---------
# Start from default config (no TLS 1.3, no USE_PSA)
helper_libtestdriver1_adjust_config "default"
# Start from full config
helper_libtestdriver1_adjust_config "full"
# Disable things that are being accelerated
scripts/config.py unset MBEDTLS_GCM_C
scripts/config.py unset MBEDTLS_CCM_C
scripts/config.py unset MBEDTLS_CHACHAPOLY_C
# Features that depend on AEAD
scripts/config.py unset MBEDTLS_SSL_CONTEXT_SERIALIZATION
scripts/config.py unset MBEDTLS_SSL_TICKET_C
# Build
# -----
@@ -3919,45 +3920,107 @@ component_build_tfm() {
make lib CC="gcc" CFLAGS="-Os -std=c99 -Werror -Wall -Wextra -Wwrite-strings -Wpointer-arith -Wshadow -Wvla -Wformat=2 -Wno-format-nonliteral -Wshadow -Wformat-signedness -Wlogical-op -I../tests/include/spe"
}
component_build_aes_variations() { # ~45s
# Test that the given .o file builds with all (valid) combinations of the given options.
#
# Syntax: build_test_config_combos FILE VALIDATOR_FUNCTION OPT1 OPT2 ...
#
# The validator function is the name of a function to validate the combination of options.
# It may be "" if all combinations are valid.
# It receives a string containing a combination of options, as passed to the compiler,
# e.g. "-DOPT1 -DOPT2 ...". It must return 0 iff the combination is valid, non-zero if invalid.
build_test_config_combos() {
file=$1
shift
validate_options=$1
shift
options=("$@")
# clear all of the options so that they can be overridden on the clang commandline
for opt in "${options[@]}"; do
./scripts/config.py unset ${opt}
done
# enter the directory containing the target file & strip the dir from the filename
cd $(dirname ${file})
file=$(basename ${file})
# The most common issue is unused variables/functions, so ensure -Wunused is set.
warning_flags="-Werror -Wall -Wextra -Wwrite-strings -Wpointer-arith -Wimplicit-fallthrough -Wshadow -Wvla -Wformat=2 -Wno-format-nonliteral -Wshadow -Wasm-operand-widths -Wunused"
# Extract the command generated by the Makefile to build the target file.
# This ensures that we have any include paths, macro definitions, etc
# that may be applied by make.
# Add -fsyntax-only as we only want a syntax check and don't need to generate a file.
compile_cmd="clang \$(LOCAL_CFLAGS) ${warning_flags} -fsyntax-only -c"
makefile=$(TMPDIR=. mktemp)
deps=""
len=${#options[@]}
source_file=${file%.o}.c
targets=0
echo 'include Makefile' >${makefile}
for ((i = 0; i < $((2**${len})); i++)); do
# generate each of 2^n combinations of options
# each bit of $i is used to determine if options[i] will be set or not
target="t"
clang_args=""
for ((j = 0; j < ${len}; j++)); do
if (((i >> j) & 1)); then
opt=-D${options[$j]}
clang_args="${clang_args} ${opt}"
target="${target}${opt}"
fi
done
# if combination is not known to be invalid, add it to the makefile
if [[ -z $validate_options ]] || $validate_options "${clang_args}"; then
cmd="${compile_cmd} ${clang_args}"
echo "${target}: ${source_file}; $cmd ${source_file}" >> ${makefile}
deps="${deps} ${target}"
((++targets))
fi
done
echo "build_test_config_combos: ${deps}" >> ${makefile}
# execute all of the commands via Make (probably in parallel)
make -s -f ${makefile} build_test_config_combos
echo "$targets targets checked"
# clean up the temporary makefile
rm ${makefile}
}
validate_aes_config_variations() {
if [[ "$1" == *"MBEDTLS_AES_USE_HARDWARE_ONLY"* ]]; then
if [[ "$1" == *"MBEDTLS_PADLOCK_C"* ]]; then
return 1
fi
if [[ !(("$HOSTTYPE" == "aarch64" && "$1" != *"MBEDTLS_AESCE_C"*) || \
("$HOSTTYPE" == "x86_64" && "$1" != *"MBEDTLS_AESNI_C"*)) ]]; then
return 1
fi
fi
return 0
}
component_build_aes_variations() {
# 18s - around 90ms per clang invocation on M1 Pro
#
# aes.o has many #if defined(...) guards that intersect in complex ways.
# Test that all the combinations build cleanly. The most common issue is
# unused variables/functions, so ensure -Wunused is set.
# Test that all the combinations build cleanly.
msg "build: aes.o for all combinations of relevant config options"
for a in set unset; do
for b in set unset; do
for c in set unset; do
for d in set unset; do
for e in set unset; do
for f in set unset; do
for g in set unset; do
echo ./scripts/config.py $a MBEDTLS_AES_SETKEY_ENC_ALT
echo ./scripts/config.py $b MBEDTLS_AES_DECRYPT_ALT
echo ./scripts/config.py $c MBEDTLS_AES_ROM_TABLES
echo ./scripts/config.py $d MBEDTLS_AES_ENCRYPT_ALT
echo ./scripts/config.py $e MBEDTLS_AES_SETKEY_DEC_ALT
echo ./scripts/config.py $f MBEDTLS_AES_FEWER_TABLES
echo ./scripts/config.py $g MBEDTLS_PADLOCK_C
./scripts/config.py $a MBEDTLS_AES_SETKEY_ENC_ALT
./scripts/config.py $b MBEDTLS_AES_DECRYPT_ALT
./scripts/config.py $c MBEDTLS_AES_ROM_TABLES
./scripts/config.py $d MBEDTLS_AES_ENCRYPT_ALT
./scripts/config.py $e MBEDTLS_AES_SETKEY_DEC_ALT
./scripts/config.py $f MBEDTLS_AES_FEWER_TABLES
./scripts/config.py $g MBEDTLS_PADLOCK_C
rm -f library/aes.o
make -C library aes.o CC="clang" CFLAGS="-O0 -std=c99 -Werror -Wall -Wextra -Wwrite-strings -Wpointer-arith -Wimplicit-fallthrough -Wshadow -Wvla -Wformat=2 -Wno-format-nonliteral -Wshadow -Wasm-operand-widths -Wunused"
done
done
done
done
done
done
done
build_test_config_combos library/aes.o validate_aes_config_variations \
"MBEDTLS_AES_SETKEY_ENC_ALT" "MBEDTLS_AES_DECRYPT_ALT" \
"MBEDTLS_AES_ROM_TABLES" "MBEDTLS_AES_ENCRYPT_ALT" "MBEDTLS_AES_SETKEY_DEC_ALT" \
"MBEDTLS_AES_FEWER_TABLES" "MBEDTLS_PADLOCK_C" "MBEDTLS_AES_USE_HARDWARE_ONLY" \
"MBEDTLS_AESNI_C" "MBEDTLS_AESCE_C" "MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH"
}
component_test_no_platform () {
@@ -5220,6 +5283,9 @@ component_test_memsan () {
msg "test: main suites (MSan)" # ~ 10s
make test
msg "program demos (MSan)" # ~20s
tests/scripts/run_demos.py
msg "test: ssl-opt.sh (MSan)" # ~ 1 min
tests/ssl-opt.sh

View File

@@ -22,17 +22,23 @@ class Results:
self.error_count = 0
self.warning_count = 0
@staticmethod
def log(fmt, *args, **kwargs):
sys.stderr.write((fmt + '\n').format(*args, **kwargs))
def new_section(self, fmt, *args, **kwargs):
self._print_line('\n*** ' + fmt + ' ***\n', *args, **kwargs)
def info(self, fmt, *args, **kwargs):
self._print_line('Info: ' + fmt, *args, **kwargs)
def error(self, fmt, *args, **kwargs):
self.log('Error: ' + fmt, *args, **kwargs)
self.error_count += 1
self._print_line('Error: ' + fmt, *args, **kwargs)
def warning(self, fmt, *args, **kwargs):
self.log('Warning: ' + fmt, *args, **kwargs)
self.warning_count += 1
self._print_line('Warning: ' + fmt, *args, **kwargs)
@staticmethod
def _print_line(fmt, *args, **kwargs):
sys.stderr.write((fmt + '\n').format(*args, **kwargs))
class TestCaseOutcomes:
"""The outcomes of one test case across many configurations."""
@@ -53,25 +59,24 @@ class TestCaseOutcomes:
"""
return len(self.successes) + len(self.failures)
def execute_reference_driver_tests(ref_component, driver_component, outcome_file):
def execute_reference_driver_tests(results: Results, 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.")
results.info("Outcome file ({}) already exists. Tests will be skipped.", outcome_file)
return
shell_command = "tests/scripts/all.sh --outcome-file " + outcome_file + \
" " + ref_component + " " + driver_component
Results.log("Running: " + shell_command)
results.info("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)
results.error("failed to run reference/driver components")
def analyze_coverage(results, outcomes, allow_list, full_coverage):
"""Check that all available test cases are executed at least once."""
@@ -90,7 +95,8 @@ def analyze_coverage(results, outcomes, allow_list, full_coverage):
else:
results.warning('Allow listed test case was executed: {}', key)
def analyze_driver_vs_reference(outcomes, component_ref, component_driver,
def analyze_driver_vs_reference(results: Results, outcomes,
component_ref, component_driver,
ignored_suites, ignored_test=None):
"""Check that all tests executed in the reference component are also
executed in the corresponding driver component.
@@ -100,7 +106,6 @@ def analyze_driver_vs_reference(outcomes, component_ref, component_driver,
output string is provided
"""
available = check_test_cases.collect_available_test_cases()
result = True
for key in available:
# Continue if test was not executed by any component
@@ -125,16 +130,12 @@ 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):
Results.log(key)
result = False
return result
results.error("Did not pass with driver: {}", key)
def analyze_outcomes(outcomes, args):
def analyze_outcomes(results: Results, outcomes, args):
"""Run all analyses on the given outcome collection."""
results = Results()
analyze_coverage(results, outcomes, args['allow_list'],
args['full_coverage'])
return results
def read_outcome_file(outcome_file):
"""Parse an outcome file and return an outcome collection.
@@ -157,29 +158,30 @@ by a semicolon.
outcomes[key].failures.append(setup)
return outcomes
def do_analyze_coverage(outcome_file, args):
def do_analyze_coverage(results: Results, outcome_file, args):
"""Perform coverage analysis."""
results.new_section("Analyze coverage")
outcomes = read_outcome_file(outcome_file)
Results.log("\n*** Analyze coverage ***\n")
results = analyze_outcomes(outcomes, args)
return results.error_count == 0
analyze_outcomes(results, outcomes, args)
def do_analyze_driver_vs_reference(outcome_file, args):
def do_analyze_driver_vs_reference(results: Results, outcome_file, args):
"""Perform driver vs reference analyze."""
execute_reference_driver_tests(args['component_ref'], \
args['component_driver'], outcome_file)
results.new_section("Analyze driver {} vs reference {}",
args['component_driver'], args['component_ref'])
execute_reference_driver_tests(results, 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)
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,
args['ignored_tests'])
analyze_driver_vs_reference(results, outcomes,
args['component_ref'], args['component_driver'],
ignored_suites, args['ignored_tests'])
# List of tasks with a function that can handle this task and additional arguments if required
TASKS = {
KNOWN_TASKS = {
'analyze_coverage': {
'test_function': do_analyze_coverage,
'args': {
@@ -641,11 +643,13 @@ TASKS = {
}
def main():
main_results = Results()
try:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('outcomes', metavar='OUTCOMES.CSV',
help='Outcome file to analyze')
parser.add_argument('task', default='all', nargs='?',
parser.add_argument('specified_tasks', default='all', nargs='?',
help='Analysis to be done. By default, run all tasks. '
'With one or more TASK, run only those. '
'TASK can be the name of a single task or '
@@ -660,33 +664,31 @@ def main():
options = parser.parse_args()
if options.list:
for task in TASKS:
Results.log(task)
for task in KNOWN_TASKS:
print(task)
sys.exit(0)
result = True
if options.task == 'all':
tasks = TASKS.keys()
if options.specified_tasks == 'all':
tasks_list = KNOWN_TASKS.keys()
else:
tasks = re.split(r'[, ]+', options.task)
tasks_list = re.split(r'[, ]+', options.specified_tasks)
for task in tasks_list:
if task not in KNOWN_TASKS:
sys.stderr.write('invalid task: {}'.format(task))
sys.exit(2)
for task in tasks:
if task not in TASKS:
Results.log('Error: invalid task: {}'.format(task))
sys.exit(1)
KNOWN_TASKS['analyze_coverage']['args']['full_coverage'] = options.full_coverage
TASKS['analyze_coverage']['args']['full_coverage'] = \
options.full_coverage
for task in tasks_list:
test_function = KNOWN_TASKS[task]['test_function']
test_args = KNOWN_TASKS[task]['args']
test_function(main_results, options.outcomes, test_args)
for task in TASKS:
if task in tasks:
if not TASKS[task]['test_function'](options.outcomes, TASKS[task]['args']):
result = False
main_results.info("Overall results: {} warnings and {} errors",
main_results.warning_count, main_results.error_count)
sys.exit(0 if (main_results.error_count == 0) else 1)
if result is False:
sys.exit(1)
Results.log("SUCCESS :-)")
except Exception: # pylint: disable=broad-except
# Print the backtrace and exit explicitly with our chosen status.
traceback.print_exc()

View File

@@ -48,11 +48,8 @@ if [ -d library -a -d include -a -d tests ]; then :; else
fi
: ${OPENSSL:="openssl"}
: ${OPENSSL_LEGACY:="$OPENSSL"}
: ${GNUTLS_CLI:="gnutls-cli"}
: ${GNUTLS_SERV:="gnutls-serv"}
: ${GNUTLS_LEGACY_CLI:="$GNUTLS_CLI"}
: ${GNUTLS_LEGACY_SERV:="$GNUTLS_SERV"}
# Used to make ssl-opt.sh deterministic.
#
@@ -78,11 +75,8 @@ CONFIG_BAK="$CONFIG_H.bak"
# Step 0 - print build environment info
OPENSSL="$OPENSSL" \
OPENSSL_LEGACY="$OPENSSL_LEGACY" \
GNUTLS_CLI="$GNUTLS_CLI" \
GNUTLS_SERV="$GNUTLS_SERV" \
GNUTLS_LEGACY_CLI="$GNUTLS_LEGACY_CLI" \
GNUTLS_LEGACY_SERV="$GNUTLS_LEGACY_SERV" \
scripts/output_env.sh
echo
@@ -124,9 +118,7 @@ echo '################ compat.sh ################'
sh compat.sh
echo
echo '#### compat.sh: legacy (null)'
OPENSSL="$OPENSSL_LEGACY" \
GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" \
echo '#### compat.sh: null cipher'
sh compat.sh -e '^$' -f 'NULL'
echo

View File

@@ -162,24 +162,6 @@ def is_windows_file(filepath):
return ext in ('.bat', '.dsp', '.dsw', '.sln', '.vcxproj')
class PermissionIssueTracker(FileIssueTracker):
"""Track files with bad permissions.
Files that are not executable scripts must not be executable."""
heading = "Incorrect permissions:"
# .py files can be either full scripts or modules, so they may or may
# not be executable.
suffix_exemptions = frozenset({".py"})
def check_file_for_issue(self, filepath):
is_executable = os.access(filepath, os.X_OK)
should_be_executable = filepath.endswith((".sh", ".pl"))
if is_executable != should_be_executable:
self.files_with_issues[filepath] = None
class ShebangIssueTracker(FileIssueTracker):
"""Track files with a bad, missing or extraneous shebang line.
@@ -386,7 +368,6 @@ class IntegrityChecker:
self.logger = None
self.setup_logger(log_file)
self.issues_to_check = [
PermissionIssueTracker(),
ShebangIssueTracker(),
EndOfFileNewlineIssueTracker(),
Utf8BomIssueTracker(),

63
tests/scripts/run_demos.py Executable file
View File

@@ -0,0 +1,63 @@
#!/usr/bin/env python3
"""Run the Mbed TLS demo scripts.
"""
import argparse
import glob
import subprocess
import sys
def run_demo(demo, quiet=False):
"""Run the specified demo script. Return True if it succeeds."""
args = {}
if quiet:
args['stdout'] = subprocess.DEVNULL
args['stderr'] = subprocess.DEVNULL
returncode = subprocess.call([demo], **args)
return returncode == 0
def run_demos(demos, quiet=False):
"""Run the specified demos and print summary information about failures.
Return True if all demos passed and False if a demo fails.
"""
failures = []
for demo in demos:
if not quiet:
print('#### {} ####'.format(demo))
success = run_demo(demo, quiet=quiet)
if not success:
failures.append(demo)
if not quiet:
print('{}: FAIL'.format(demo))
if quiet:
print('{}: {}'.format(demo, 'PASS' if success else 'FAIL'))
else:
print('')
successes = len(demos) - len(failures)
print('{}/{} demos passed'.format(successes, len(demos)))
if failures and not quiet:
print('Failures:', *failures)
return not failures
def run_all_demos(quiet=False):
"""Run all the available demos.
Return True if all demos passed and False if a demo fails.
"""
all_demos = glob.glob('programs/*/*_demo.sh')
if not all_demos:
# Keep the message on one line. pylint: disable=line-too-long
raise Exception('No demos found. run_demos needs to operate from the Mbed TLS toplevel directory.')
return run_demos(all_demos, quiet=quiet)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--quiet', '-q',
action='store_true',
help="suppress the output of demos")
options = parser.parse_args()
success = run_all_demos(quiet=options.quiet)
sys.exit(0 if success else 1)
if __name__ == '__main__':
main()