Merge pull request #4054 from chris-jones-arm/move-testing-functions

Move test infrastructure from `tests/suites/helpers.function` into `tests/src/helpers.c`
This commit is contained in:
Ronald Cron 2021-02-03 19:01:54 +01:00 committed by GitHub
commit 540320bf7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 163 additions and 110 deletions

View File

@ -49,9 +49,75 @@
#include <stddef.h>
#include <stdint.h>
typedef enum
{
MBEDTLS_TEST_RESULT_SUCCESS = 0,
MBEDTLS_TEST_RESULT_FAILED,
MBEDTLS_TEST_RESULT_SKIPPED
} mbedtls_test_result_t;
typedef struct
{
mbedtls_test_result_t result;
const char *test;
const char *filename;
int line_no;
unsigned long step;
}
mbedtls_test_info_t;
extern mbedtls_test_info_t mbedtls_test_info;
int mbedtls_test_platform_setup( void );
void mbedtls_test_platform_teardown( void );
/**
* \brief Record the current test case as a failure.
*
* This function can be called directly however it is usually
* called via macros such as TEST_ASSERT, TEST_EQUAL,
* PSA_ASSERT, etc...
*
* \note If the test case was already marked as failed, calling
* `mbedtls_test_fail( )` again will not overwrite any
* previous information about the failure.
*
* \param test Description of the failure or assertion that failed. This
* MUST be a string literal.
* \param line_no Line number where the failure originated.
* \param filename Filename where the failure originated.
*/
void mbedtls_test_fail( const char *test, int line_no, const char* filename );
/**
* \brief Record the current test case as skipped.
*
* This function can be called directly however it is usually
* called via the TEST_ASSUME macro.
*
* \param test Description of the assumption that caused the test case to
* be skipped. This MUST be a string literal.
* \param line_no Line number where the test case was skipped.
* \param filename Filename where the test case was skipped.
*/
void mbedtls_test_skip( const char *test, int line_no, const char* filename );
/**
* \brief Set the test step number for failure reports.
*
* Call this function to display "step NNN" in addition to the
* line number and file name if a test fails. Typically the "step
* number" is the index of a for loop but it can be whatever you
* want.
*
* \param step The step number to report.
*/
void mbedtls_test_set_step( unsigned long step );
/**
* \brief Reset mbedtls_test_info to a ready/starting state.
*/
void mbedtls_test_info_reset( void );
/**
* \brief This function decodes the hexadecimal representation of
* data.

View File

@ -44,6 +44,8 @@ static param_failed_ctx_t param_failed_ctx;
static mbedtls_platform_context platform_ctx;
#endif
mbedtls_test_info_t mbedtls_test_info;
/*----------------------------------------------------------------------------*/
/* Helper Functions */
@ -77,6 +79,42 @@ static int ascii2uc(const char c, unsigned char *uc)
return( 0 );
}
void mbedtls_test_fail( const char *test, int line_no, const char* filename )
{
if( mbedtls_test_info.result == MBEDTLS_TEST_RESULT_FAILED )
{
/* We've already recorded the test as having failed. Don't
* overwrite any previous information about the failure. */
return;
}
mbedtls_test_info.result = MBEDTLS_TEST_RESULT_FAILED;
mbedtls_test_info.test = test;
mbedtls_test_info.line_no = line_no;
mbedtls_test_info.filename = filename;
}
void mbedtls_test_skip( const char *test, int line_no, const char* filename )
{
mbedtls_test_info.result = MBEDTLS_TEST_RESULT_SKIPPED;
mbedtls_test_info.test = test;
mbedtls_test_info.line_no = line_no;
mbedtls_test_info.filename = filename;
}
void mbedtls_test_set_step( unsigned long step )
{
mbedtls_test_info.step = step;
}
void mbedtls_test_info_reset( void )
{
mbedtls_test_info.result = MBEDTLS_TEST_RESULT_SUCCESS;
mbedtls_test_info.step = (unsigned long)( -1 );
mbedtls_test_info.test = 0;
mbedtls_test_info.line_no = 0;
mbedtls_test_info.filename = 0;
}
int mbedtls_test_unhexify( unsigned char *obuf,
size_t obufmax,
const char *ibuf,

View File

@ -108,7 +108,7 @@ typedef struct data_tag
do { \
if( ! (TEST) ) \
{ \
test_fail( #TEST, __LINE__, __FILE__ ); \
mbedtls_test_fail( #TEST, __LINE__, __FILE__ ); \
goto exit; \
} \
} while( 0 )
@ -201,13 +201,13 @@ typedef struct data_tag
*
* \param TEST The test expression to be tested.
*/
#define TEST_ASSUME( TEST ) \
do { \
if( ! (TEST) ) \
{ \
test_skip( #TEST, __LINE__, __FILE__ ); \
goto exit; \
} \
#define TEST_ASSUME( TEST ) \
do { \
if( ! (TEST) ) \
{ \
mbedtls_test_skip( #TEST, __LINE__, __FILE__ ); \
goto exit; \
} \
} while( 0 )
#if defined(MBEDTLS_CHECK_PARAMS) && !defined(MBEDTLS_PARAM_FAILED_ALT)
@ -237,7 +237,7 @@ typedef struct data_tag
if( ( ( TEST ) != ( PARAM_ERR_VALUE ) ) || \
( mbedtls_test_param_failed_check_expected_call( ) != 0 ) ) \
{ \
test_fail( #TEST, __LINE__, __FILE__ ); \
mbedtls_test_fail( #TEST, __LINE__, __FILE__ ); \
goto exit; \
} \
mbedtls_test_param_failed_check_expected_call( ); \
@ -270,7 +270,7 @@ typedef struct data_tag
if( setjmp( mbedtls_test_param_failed_get_state_buf( ) ) == 0 ) \
{ \
TEST; \
test_fail( #TEST, __LINE__, __FILE__ ); \
mbedtls_test_fail( #TEST, __LINE__, __FILE__ ); \
goto exit; \
} \
mbedtls_test_param_failed_reset_state( ); \
@ -346,24 +346,6 @@ typedef struct data_tag
/*----------------------------------------------------------------------------*/
/* Global variables */
typedef enum
{
TEST_RESULT_SUCCESS = 0,
TEST_RESULT_FAILED,
TEST_RESULT_SKIPPED
} test_result_t;
typedef struct
{
test_result_t result;
const char *test;
const char *filename;
int line_no;
unsigned long step;
}
test_info_t;
static test_info_t test_info;
#if defined(MBEDTLS_CHECK_PARAMS)
jmp_buf jmp_tmp;
#endif
@ -386,41 +368,6 @@ jmp_buf jmp_tmp;
/*----------------------------------------------------------------------------*/
/* Helper Functions */
/** Set the test step number for failure reports.
*
* Call this function to display "step NNN" in addition to the line number
* and file name if a test fails. Typically the "step number" is the index
* of a for loop but it can be whatever you want.
*
* \param step The step number to report.
*/
void test_set_step( unsigned long step )
{
test_info.step = step;
}
void test_fail( const char *test, int line_no, const char* filename )
{
if( test_info.result == TEST_RESULT_FAILED )
{
/* We've already recorded the test as having failed. Don't
* overwrite any previous information about the failure. */
return;
}
test_info.result = TEST_RESULT_FAILED;
test_info.test = test;
test_info.line_no = line_no;
test_info.filename = filename;
}
void test_skip( const char *test, int line_no, const char* filename )
{
test_info.result = TEST_RESULT_SKIPPED;
test_info.test = test;
test_info.line_no = line_no;
test_info.filename = filename;
}
#if defined(MBEDTLS_PSA_CRYPTO_C)
/** Check that no PSA Crypto key slots are in use.
*
@ -435,7 +382,7 @@ int test_fail_if_psa_leaking( int line_no, const char *filename )
return 0;
else
{
test_fail( msg, line_no, filename );
mbedtls_test_fail( msg, line_no, filename );
return 1;
}
}

View File

@ -428,15 +428,15 @@ static void write_outcome_entry( FILE *outcome_file,
* \param unmet_dependencies The array of unmet dependencies.
* \param missing_unmet_dependencies Non-zero if there was a problem tracking
* all unmet dependencies, 0 otherwise.
* \param ret The test dispatch status (DISPATCH_xxx).
* \param test_info A pointer to the test info structure.
* \param ret The test dispatch status (DISPATCH_xxx).
* \param mbedtls_test_info A pointer to the test info structure.
*/
static void write_outcome_result( FILE *outcome_file,
size_t unmet_dep_count,
int unmet_dependencies[],
int missing_unmet_dependencies,
int ret,
const test_info_t *info )
const mbedtls_test_info_t *info )
{
if( outcome_file == NULL )
return;
@ -462,10 +462,10 @@ static void write_outcome_result( FILE *outcome_file,
}
switch( info->result )
{
case TEST_RESULT_SUCCESS:
case MBEDTLS_TEST_RESULT_SUCCESS:
mbedtls_fprintf( outcome_file, "PASS;" );
break;
case TEST_RESULT_SKIPPED:
case MBEDTLS_TEST_RESULT_SKIPPED:
mbedtls_fprintf( outcome_file, "SKIP;Runtime skip" );
break;
default:
@ -601,7 +601,7 @@ int execute_tests( int argc , const char ** argv )
}
/* Initialize the struct that holds information about the last test */
memset( &test_info, 0, sizeof( test_info ) );
mbedtls_test_info_reset( );
/* Now begin to execute the tests in the testfiles */
for ( testfile_index = 0;
@ -638,7 +638,8 @@ int execute_tests( int argc , const char ** argv )
if( ( ret = get_line( file, buf, sizeof(buf) ) ) != 0 )
break;
mbedtls_fprintf( stdout, "%s%.66s",
test_info.result == TEST_RESULT_FAILED ? "\n" : "", buf );
mbedtls_test_info.result == MBEDTLS_TEST_RESULT_FAILED ?
"\n" : "", buf );
mbedtls_fprintf( stdout, " " );
for( i = strlen( buf ) + 1; i < 67; i++ )
mbedtls_fprintf( stdout, "." );
@ -682,8 +683,7 @@ int execute_tests( int argc , const char ** argv )
// If there are no unmet dependencies execute the test
if( unmet_dep_count == 0 )
{
test_info.result = TEST_RESULT_SUCCESS;
test_info.step = (unsigned long)( -1 );
mbedtls_test_info_reset( );
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
/* Suppress all output from the library unless we're verbose
@ -723,7 +723,7 @@ int execute_tests( int argc , const char ** argv )
write_outcome_result( outcome_file,
unmet_dep_count, unmet_dependencies,
missing_unmet_dependencies,
ret, &test_info );
ret, &mbedtls_test_info );
if( unmet_dep_count > 0 || ret == DISPATCH_UNSUPPORTED_SUITE )
{
total_skipped++;
@ -753,11 +753,11 @@ int execute_tests( int argc , const char ** argv )
}
else if( ret == DISPATCH_TEST_SUCCESS )
{
if( test_info.result == TEST_RESULT_SUCCESS )
if( mbedtls_test_info.result == MBEDTLS_TEST_RESULT_SUCCESS )
{
mbedtls_fprintf( stdout, "PASS\n" );
}
else if( test_info.result == TEST_RESULT_SKIPPED )
else if( mbedtls_test_info.result == MBEDTLS_TEST_RESULT_SKIPPED )
{
mbedtls_fprintf( stdout, "----\n" );
total_skipped++;
@ -767,14 +767,15 @@ int execute_tests( int argc , const char ** argv )
total_errors++;
mbedtls_fprintf( stdout, "FAILED\n" );
mbedtls_fprintf( stdout, " %s\n at ",
test_info.test );
if( test_info.step != (unsigned long)( -1 ) )
mbedtls_test_info.test );
if( mbedtls_test_info.step != (unsigned long)( -1 ) )
{
mbedtls_fprintf( stdout, "step %lu, ",
test_info.step );
mbedtls_test_info.step );
}
mbedtls_fprintf( stdout, "line %d, %s",
test_info.line_no, test_info.filename );
mbedtls_test_info.line_no,
mbedtls_test_info.filename );
}
fflush( stdout );
}

View File

@ -179,10 +179,9 @@ void execute_function_ptr(TestWrapper_t fp, void **params)
{
/* Unexpected parameter validation error */
mbedtls_test_param_failed_get_location_record( &location_record );
test_fail( location_record.failure_condition,
location_record.line,
location_record.file );
test_info.result = TEST_RESULT_FAILED;
mbedtls_test_fail( location_record.failure_condition,
location_record.line,
location_record.file );
}
mbedtls_test_param_failed_reset_state( );

View File

@ -384,8 +384,7 @@ int execute_tests( int args, const char ** argv )
while ( 1 )
{
ret = 0;
test_info.result = TEST_RESULT_SUCCESS;
test_info.step = (unsigned long)( -1 );
mbedtls_test_info_reset( );
data_len = 0;
data = receive_data( &data_len );
@ -443,7 +442,7 @@ int execute_tests( int args, const char ** argv )
if ( ret )
send_failure( ret );
else
send_status( test_info.result );
send_status( mbedtls_test_info.result );
}
return( 0 );
}

View File

@ -130,7 +130,7 @@ int get_len_step( const data_t *input, size_t buffer_size,
size_t parsed_length;
int ret;
test_set_step( buffer_size );
mbedtls_test_set_step( buffer_size );
/* Allocate a new buffer of exactly the length to parse each time.
* This gives memory sanitizers a chance to catch buffer overreads. */
if( buffer_size == 0 )
@ -198,7 +198,7 @@ static int traverse_callback( void *ctx, int tag,
TEST_ASSERT( content > state->input_start );
offset = content - state->input_start;
test_set_step( offset );
mbedtls_test_set_step( offset );
if( *rest == 0 )
return( RET_TRAVERSE_STOP );
@ -252,7 +252,7 @@ void parse_prefixes( const data_t *input,
*/
for( buffer_size = 1; buffer_size <= input->len + 1; buffer_size++ )
{
test_set_step( buffer_size );
mbedtls_test_set_step( buffer_size );
/* Allocate a new buffer of exactly the length to parse each time.
* This gives memory sanitizers a chance to catch buffer overreads. */
ASSERT_ALLOC( buf, buffer_size );
@ -594,6 +594,7 @@ void get_sequence_of( const data_t *input, int tag,
unsigned char *p = input->x;
const char *rest = description;
unsigned long n;
unsigned int step = 0;
TEST_EQUAL( mbedtls_asn1_get_sequence_of( &p, input->x + input->len,
&head, tag ),
@ -614,7 +615,7 @@ void get_sequence_of( const data_t *input, int tag,
cur = &head;
while( *rest )
{
++test_info.step;
mbedtls_test_set_step( step );
TEST_ASSERT( cur != NULL );
TEST_EQUAL( cur->buf.tag, tag );
n = strtoul( rest, (char **) &rest, 0 );
@ -625,6 +626,7 @@ void get_sequence_of( const data_t *input, int tag,
if( *rest )
++rest;
cur = cur->next;
++step;
}
TEST_ASSERT( cur == NULL );
}

View File

@ -15,7 +15,7 @@ typedef struct
int generic_write_start_step( generic_write_data_t *data )
{
test_set_step( data->size );
mbedtls_test_set_step( data->size );
ASSERT_ALLOC( data->output, data->size == 0 ? 1 : data->size );
data->end = data->output + data->size;
data->p = data->end;

View File

@ -532,7 +532,8 @@ static int exercise_signature_key( mbedtls_svc_key_id_t key,
hash_alg = KNOWN_SUPPORTED_HASH_ALG;
alg ^= PSA_ALG_ANY_HASH ^ hash_alg;
#else
test_fail( "No hash algorithm for hash-and-sign testing", __LINE__, __FILE__ );
mbedtls_test_fail( "No hash algorithm for hash-and-sign testing",
__LINE__, __FILE__ );
return( 1 );
#endif
}
@ -992,7 +993,7 @@ static int exported_key_sanity_check( psa_key_type_t type, size_t bits,
mbedtls_snprintf( message, sizeof( message ),
"No sanity check for public key type=0x%08lx",
(unsigned long) type );
test_fail( message, __LINE__, __FILE__ );
mbedtls_test_fail( message, __LINE__, __FILE__ );
(void) p;
(void) end;
return( 0 );
@ -1115,8 +1116,8 @@ exit:
* asymmetric, also check \p psa_export_public_key.
*
* If the key fails the tests, this function calls the test framework's
* `test_fail` function and returns false. Otherwise this function returns
* true. Therefore it should be used as follows:
* `mbedtls_test_fail` function and returns false. Otherwise this function
* returns true. Therefore it should be used as follows:
* ```
* if( ! exercise_key( ... ) ) goto exit;
* ```
@ -1162,7 +1163,7 @@ static int exercise_key( mbedtls_svc_key_id_t key,
mbedtls_snprintf( message, sizeof( message ),
"No code to exercise alg=0x%08lx",
(unsigned long) alg );
test_fail( message, __LINE__, __FILE__ );
mbedtls_test_fail( message, __LINE__, __FILE__ );
ok = 0;
}
@ -2677,7 +2678,7 @@ void hash_compute_compare( int alg_arg, data_t *input,
/* Compare with corrupted value */
for( i = 0; i < output_length; i++ )
{
test_set_step( i );
mbedtls_test_set_step( i );
output[i] ^= 1;
TEST_EQUAL( psa_hash_compare( alg, input->x, input->len,
output, output_length ),
@ -3152,7 +3153,7 @@ void mac_sign( int key_type_arg,
( output_size >= expected_mac->len ? PSA_SUCCESS :
PSA_ERROR_BUFFER_TOO_SMALL );
test_set_step( output_size );
mbedtls_test_set_step( output_size );
ASSERT_ALLOC( actual_mac, output_size );
/* Calculate the MAC. */
@ -3238,7 +3239,7 @@ void mac_verify( int key_type_arg,
/* Test changing one byte. */
for( size_t i = 0; i < expected_mac->len; i++ )
{
test_set_step( i );
mbedtls_test_set_step( i );
perturbed_mac[i] ^= 1;
PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
PSA_ASSERT( psa_mac_update( &operation,

View File

@ -45,7 +45,7 @@
do { \
if( ! (TEST) ) \
{ \
test_fail( #TEST, __LINE__, __FILE__ ); \
mbedtls_test_fail( #TEST, __LINE__, __FILE__ ); \
return( PSA_ERROR_DETECTED_BY_DRIVER ); \
} \
} while( 0 )
@ -61,7 +61,7 @@
do { \
if( ! (TEST) ) \
{ \
test_fail( #TEST, __LINE__, __FILE__ ); \
mbedtls_test_fail( #TEST, __LINE__, __FILE__ ); \
status = PSA_ERROR_DETECTED_BY_DRIVER; \
goto exit; \
} \
@ -72,10 +72,10 @@
* Run the code \p expr. If this returns \p expected_status,
* do nothing. If this returns #PSA_ERROR_DETECTED_BY_DRIVER,
* jump directly to the `exit` label. If this returns any other
* status, call test_fail() then jump to `exit`.
* status, call mbedtls_test_fail() then jump to `exit`.
*
* The special case for #PSA_ERROR_DETECTED_BY_DRIVER is because in this
* case, the test driver code is expected to have called test_fail()
* case, the test driver code is expected to have called mbedtls_test_fail()
* already, so we make sure not to overwrite the failure information.
*/
#define PSA_ASSERT_VIA_DRIVER( expr, expected_status ) \
@ -85,7 +85,7 @@
goto exit; \
if( PSA_ASSERT_VIA_DRIVER_status != ( expected_status ) ) \
{ \
test_fail( #expr, __LINE__, __FILE__ ); \
mbedtls_test_fail( #expr, __LINE__, __FILE__ ); \
goto exit; \
} \
} while( 0 )

View File

@ -3609,7 +3609,7 @@ void ssl_decrypt_non_etm_cbc( int cipher_type, int hash_id, int trunc_hmac,
*/
for( i = block_size; i < buflen; i++ )
{
test_set_step( i );
mbedtls_test_set_step( i );
/* Restore correct pre-encryption record */
rec = rec_save;
@ -3646,7 +3646,7 @@ void ssl_decrypt_non_etm_cbc( int cipher_type, int hash_id, int trunc_hmac,
*/
for( i = padlen; i <= pad_max_len; i++ )
{
test_set_step( i );
mbedtls_test_set_step( i );
/* Restore correct pre-encryption record */
rec = rec_save;
@ -4466,7 +4466,7 @@ void ssl_cf_hmac( int hash )
*/
for( max_in_len = 0; max_in_len <= 255 + block_size; max_in_len++ )
{
test_set_step( max_in_len * 10000 );
mbedtls_test_set_step( max_in_len * 10000 );
/* Use allocated in buffer to catch overreads */
ASSERT_ALLOC( data, max_in_len );
@ -4474,7 +4474,7 @@ void ssl_cf_hmac( int hash )
min_in_len = max_in_len > 255 ? max_in_len - 255 : 0;
for( in_len = min_in_len; in_len <= max_in_len; in_len++ )
{
test_set_step( max_in_len * 10000 + in_len );
mbedtls_test_set_step( max_in_len * 10000 + in_len );
/* Set up dummy data and add_data */
rec_num++;
@ -4531,7 +4531,7 @@ void ssl_cf_memcpy_offset( int offset_min, int offset_max, int len )
for( secret = offset_min; secret <= (size_t) offset_max; secret++ )
{
test_set_step( (int) secret );
mbedtls_test_set_step( (int) secret );
TEST_CF_SECRET( &secret, sizeof( secret ) );
mbedtls_ssl_cf_memcpy_offset( dst, src, secret,