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:
@@ -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
|
||||
|
||||
|
@@ -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()
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
63
tests/scripts/run_demos.py
Executable 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()
|
Reference in New Issue
Block a user