diff options
Diffstat (limited to 'testsuites/validation/tc-terminate.c')
-rw-r--r-- | testsuites/validation/tc-terminate.c | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/testsuites/validation/tc-terminate.c b/testsuites/validation/tc-terminate.c new file mode 100644 index 0000000000..b533092c19 --- /dev/null +++ b/testsuites/validation/tc-terminate.c @@ -0,0 +1,446 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup ScoreInterrValTerminate + */ + +/* + * Copyright (C) 2021 embedded brains GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <bsp.h> +#include <setjmp.h> +#include <string.h> +#include <rtems/bspIo.h> +#include <rtems/test-info.h> +#include <rtems/score/atomic.h> +#include <rtems/score/percpu.h> +#include <rtems/score/sysstate.h> + +#include "tc-userext.h" + +#include <rtems/test.h> + +/** + * @defgroup ScoreInterrValTerminate spec:/score/interr/val/terminate + * + * @ingroup TestsuitesTerminate + * + * @brief Tests system termination procedure. + * + * This test case performs the following actions: + * + * - Create five dynamic extensions. Call the system termination procedure. + * Delete three dynamic extension during the fatal extension invocation. + * Delete the two remaining dynamic extensions. + * + * - Where the system was built with SMP support enabled, check that a + * shutdown request was issued. + * + * - Delete the dynamic extension sets. + * + * - Check that the fatal extensions were invoked with the expected source. + * + * - Check that the fatal extensions were invoked with the expected always + * set to false argument. + * + * - Check that the fatal extensions were invoked with the expected code. + * + * - Check that the fatal extensions were invoked in forward order. + * + * - Check that the fatal extension in the deleted extension set was not + * invoked. + * + * - Check that the system state is terminated. + * + * - Check that the system was halted with the expected fatal source. + * + * - Check that the system was halted with the expected fatal code. + * + * - Check that the system was finally halted. + * + * @{ + */ + +typedef struct { + unsigned int counter; + rtems_fatal_source source; + bool always_set_to_false; + rtems_fatal_code code; +} FatalInfo; + +static Atomic_Uint counter; + +static FatalInfo info[ 7 ]; + +static bool test_case_active; + +static const rtems_extensions_table bsp = BSP_INITIAL_EXTENSION; + +static jmp_buf before_terminate; + +static unsigned int halt_counter; + +static rtems_fatal_source halt_source; + +static rtems_fatal_code halt_code; + +static rtems_id extension_ids[ 7 ]; + +static unsigned int GetCounter( void ) +{ + return _Atomic_Fetch_add_uint( &counter, 1, ATOMIC_ORDER_RELAXED ) + 1; +} + +void __real__CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr code ); + +void __wrap__CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr code ); + +void __wrap__CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr code ) +{ + if ( test_case_active ) { + halt_counter = GetCounter(); + halt_source = source; + halt_code = code; + longjmp( before_terminate, 1 ); + } else { +#if defined(RTEMS_GCOV_COVERAGE) + rtems_test_gcov_dump_info(); +#endif + __real__CPU_Fatal_halt( source, code ); + } +} + +static void FatalExtension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code, + size_t index +) +{ + if ( test_case_active ) { + info[ index ].counter = GetCounter(); + info[ index ].source = source; + info[ index ].always_set_to_false = always_set_to_false; + info[ index ].code = code; + } else { + ( *bsp.fatal )( source, always_set_to_false, code ); + } +} + +void FatalExtension0( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +) +{ + FatalExtension( source, always_set_to_false, code, 0 ); +} + +void FatalExtension1( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +) +{ + FatalExtension( source, always_set_to_false, code, 1 ); +} + +static void FatalExtension2( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +) +{ + rtems_status_code sc; + + FatalExtension( source, always_set_to_false, code, 2 ); + + sc = rtems_extension_delete( extension_ids[ 3 ] ); + T_quiet_rsc_success( sc ); +} + +static void FatalExtension3( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +) +{ + FatalExtension( source, always_set_to_false, code, 3 ); +} + +static void FatalExtension4( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +) +{ + FatalExtension( source, always_set_to_false, code, 4 ); +} + +static void FatalExtension5( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +) +{ + rtems_status_code sc; + + FatalExtension( source, always_set_to_false, code, 5 ); + + sc = rtems_extension_delete( extension_ids[ 5 ] ); + T_quiet_rsc_success( sc ); +} + +static void FatalExtension6( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +) +{ + rtems_status_code sc; + + FatalExtension( source, always_set_to_false, code, 6 ); + + sc = rtems_extension_delete( extension_ids[ 4 ] ); + T_quiet_rsc_success( sc ); +} + +/** + * @brief Create five dynamic extensions. Call the system termination + * procedure. Delete three dynamic extension during the fatal extension + * invocation. Delete the two remaining dynamic extensions. + */ +static void ScoreInterrValTerminate_Action_0( void ) +{ + rtems_status_code sc; + rtems_extensions_table table; + bool shutdown_ok; + + #if defined(RTEMS_SMP) + shutdown_ok = + ( _Per_CPU_Get_state( _Per_CPU_Get_snapshot() ) == PER_CPU_STATE_UP ); + #else + shutdown_ok = true; + #endif + + memset( &table, 0, sizeof( table ) ); + + table.fatal = FatalExtension2; + sc = rtems_extension_create( + rtems_build_name( ' ', ' ', ' ', '2' ), + &table, + &extension_ids[ 2 ] + ); + T_step_rsc_success( 0, sc ); + + table.fatal = FatalExtension3; + sc = rtems_extension_create( + rtems_build_name( ' ', ' ', ' ', '3' ), + &table, + &extension_ids[ 3 ] + ); + T_step_rsc_success( 1, sc ); + + table.fatal = FatalExtension4; + sc = rtems_extension_create( + rtems_build_name( ' ', ' ', ' ', '4' ), + &table, + &extension_ids[ 4 ] + ); + T_step_rsc_success( 2, sc ); + + table.fatal = FatalExtension5; + sc = rtems_extension_create( + rtems_build_name( ' ', ' ', ' ', '5' ), + &table, + &extension_ids[ 5 ] + ); + T_step_rsc_success( 3, sc ); + + table.fatal = FatalExtension6; + sc = rtems_extension_create( + rtems_build_name( ' ', ' ', ' ', '6' ), + &table, + &extension_ids[ 6 ] + ); + T_step_rsc_success( 4, sc ); + + test_case_active = true; + + if ( setjmp( before_terminate ) == 0 ) { + _Terminate( RTEMS_FATAL_SOURCE_APPLICATION, 123456 ); + } + + test_case_active = false; + + /* + * Where the system was built with SMP support enabled, check that a shutdown + * request was issued. + */ + #if defined(RTEMS_SMP) + shutdown_ok = ( shutdown_ok && _ISR_Get_level() != 0 && + _Per_CPU_Get_state( _Per_CPU_Get() ) == PER_CPU_STATE_SHUTDOWN ); + _ISR_Set_level( 0 ); + #endif + T_step_true( 5, shutdown_ok ); + + /* + * Delete the dynamic extension sets. + */ + sc = rtems_extension_delete( extension_ids[ 2 ] ); + T_step_rsc_success( 6, sc ); + + sc = rtems_extension_delete( extension_ids[ 6 ] ); + T_step_rsc_success( 7, sc ); + + /* + * Check that the fatal extensions were invoked with the expected source. + */ + T_step_eq_int( + 8, + info[ 0 ].source, + RTEMS_FATAL_SOURCE_APPLICATION + ); + T_step_eq_int( + 9, + info[ 1 ].source, + RTEMS_FATAL_SOURCE_APPLICATION + ); + T_step_eq_int( + 10, + info[ 2 ].source, + RTEMS_FATAL_SOURCE_APPLICATION + ); + T_step_eq_int( + 11, + info[ 4 ].source, + RTEMS_FATAL_SOURCE_APPLICATION + ); + T_step_eq_int( + 12, + info[ 5 ].source, + RTEMS_FATAL_SOURCE_APPLICATION + ); + T_step_eq_int( + 13, + info[ 6 ].source, + RTEMS_FATAL_SOURCE_APPLICATION + ); + + /* + * Check that the fatal extensions were invoked with the expected always set + * to false argument. + */ + T_step_false( 14, info[ 0 ].always_set_to_false ); + T_step_false( 15, info[ 1 ].always_set_to_false ); + T_step_false( 16, info[ 2 ].always_set_to_false ); + T_step_false( 17, info[ 4 ].always_set_to_false ); + T_step_false( 18, info[ 5 ].always_set_to_false ); + T_step_false( 19, info[ 6 ].always_set_to_false ); + + /* + * Check that the fatal extensions were invoked with the expected code. + */ + T_step_eq_ulong( 20, info[ 0 ].code, 123456 ); + T_step_eq_ulong( 21, info[ 1 ].code, 123456 ); + T_step_eq_ulong( 22, info[ 2 ].code, 123456 ); + T_step_eq_ulong( 23, info[ 4 ].code, 123456 ); + T_step_eq_ulong( 24, info[ 5 ].code, 123456 ); + T_step_eq_ulong( 25, info[ 6 ].code, 123456 ); + + /* + * Check that the fatal extensions were invoked in forward order. + */ + T_step_eq_uint( 26, info[ 0 ].counter, 1 ); + T_step_eq_uint( 27, info[ 1 ].counter, 2 ); + T_step_eq_uint( 28, info[ 2 ].counter, 3 ); + T_step_eq_uint( 29, info[ 4 ].counter, 4 ); + T_step_eq_uint( 30, info[ 5 ].counter, 5 ); + T_step_eq_uint( 31, info[ 6 ].counter, 6 ); + + /* + * Check that the fatal extension in the deleted extension set was not + * invoked. + */ + T_step_eq_int( 32, info[ 3 ].source, 0 ); + T_step_false( 33, info[ 3 ].always_set_to_false ); + T_step_eq_ulong( 34, info[ 3 ].code, 0 ); + T_step_eq_uint( 35, info[ 3 ].counter, 0 ); + + /* + * Check that the system state is terminated. + */ + T_step_eq_int( 36, _System_state_Get(), SYSTEM_STATE_TERMINATED ); + + /* + * Check that the system was halted with the expected fatal source. + */ + T_step_eq_int( 37, halt_source, RTEMS_FATAL_SOURCE_APPLICATION ); + + /* + * Check that the system was halted with the expected fatal code. + */ + T_step_eq_ulong( 38, halt_code, 123456 ); + + /* + * Check that the system was finally halted. + */ + T_step_eq_uint( 39, counter, 7 ); +} + +/** + * @fn void T_case_body_ScoreInterrValTerminate( void ) + */ +T_TEST_CASE( ScoreInterrValTerminate ) +{ + T_plan( 40 ); + + ScoreInterrValTerminate_Action_0(); +} + +/** @} */ |