From 09f8d56b5e8fe6d075f673a303073b4925e5ee68 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 6 Jul 2021 13:23:16 +0200 Subject: validation: Test bsp_interrupt_spurious() Update #3269 --- .../testsuites/validation/validation-smp-only.yml | 1 + testsuites/validation/tc-bsp-interrupt-spurious.c | 432 +++++++++++++++++++++ 2 files changed, 433 insertions(+) create mode 100644 testsuites/validation/tc-bsp-interrupt-spurious.c diff --git a/spec/build/testsuites/validation/validation-smp-only.yml b/spec/build/testsuites/validation/validation-smp-only.yml index ea13c050e7..812ddfdda2 100644 --- a/spec/build/testsuites/validation/validation-smp-only.yml +++ b/spec/build/testsuites/validation/validation-smp-only.yml @@ -11,6 +11,7 @@ includes: [] ldflags: [] links: [] source: +- testsuites/validation/tc-bsp-interrupt-spurious.c - testsuites/validation/tc-scheduler-smp-only.c - testsuites/validation/ts-validation-smp-only.c stlib: [] diff --git a/testsuites/validation/tc-bsp-interrupt-spurious.c b/testsuites/validation/tc-bsp-interrupt-spurious.c new file mode 100644 index 0000000000..a31e233c0a --- /dev/null +++ b/testsuites/validation/tc-bsp-interrupt-spurious.c @@ -0,0 +1,432 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseBspReqInterruptSpurious + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * 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 +#include + +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseBspReqInterruptSpurious \ + * spec:/bsp/req/interrupt-spurious + * + * @ingroup RTEMSTestSuiteTestsuitesValidationSmpOnly + * + * @{ + */ + +typedef enum { + BspReqInterruptSpurious_Pre_First_Null, + BspReqInterruptSpurious_Pre_First_Entry, + BspReqInterruptSpurious_Pre_First_NA +} BspReqInterruptSpurious_Pre_First; + +typedef enum { + BspReqInterruptSpurious_Post_Result_FatalError, + BspReqInterruptSpurious_Post_Result_Dispatch, + BspReqInterruptSpurious_Post_Result_NA +} BspReqInterruptSpurious_Post_Result; + +typedef enum { + BspReqInterruptSpurious_Post_FatalSource_SpuriousInterrupt, + BspReqInterruptSpurious_Post_FatalSource_NA +} BspReqInterruptSpurious_Post_FatalSource; + +typedef enum { + BspReqInterruptSpurious_Post_FatalCode_Vector, + BspReqInterruptSpurious_Post_FatalCode_NA +} BspReqInterruptSpurious_Post_FatalCode; + +/** + * @brief Test context for spec:/bsp/req/interrupt-spurious test case. + */ +typedef struct { + /** + * @brief This member provides a jump buffer to return from the fatal error. + */ + jmp_buf before_call; + + /** + * @brief This member provides an interrupt entry to be dispatched. + */ + rtems_interrupt_entry entry; + + /** + * @brief This member provides an entry dispatch counter. + */ + uint32_t entry_counter; + + /** + * @brief This member provides a fatal error counter. + */ + uint32_t fatal_counter; + + /** + * @brief This member contains the fatal source. + */ + rtems_fatal_source fatal_source; + + /** + * @brief This member contains a fatal code. + */ + rtems_fatal_code fatal_code; + + /** + * @brief This member contains a valid vector number. + */ + rtems_vector_number vector; + + /** + * @brief This member references the pointer to the first entry of the + * interrupt vector. + */ + rtems_interrupt_entry **first; + + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 1 ]; + + /** + * @brief This member indicates if the test action loop is currently + * executed. + */ + bool in_action_loop; +} BspReqInterruptSpurious_Context; + +static BspReqInterruptSpurious_Context + BspReqInterruptSpurious_Instance; + +static const char * const BspReqInterruptSpurious_PreDesc_First[] = { + "Null", + "Entry", + "NA" +}; + +static const char * const * const BspReqInterruptSpurious_PreDesc[] = { + BspReqInterruptSpurious_PreDesc_First, + NULL +}; + +typedef BspReqInterruptSpurious_Context Context; + +static void EntryRoutine( void *arg ) +{ + Context *ctx; + + ctx = arg; + ++ctx->entry_counter; +} + +static void FatalExtension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +) +{ + Context *ctx; + + ctx = T_fixture_context(); + T_false( always_set_to_false ); + ctx->fatal_source = source; + ctx->fatal_code = code; + ++ctx->fatal_counter; + longjmp( ctx->before_call, 1 ); +} + +static void BspReqInterruptSpurious_Pre_First_Prepare( + BspReqInterruptSpurious_Context *ctx, + BspReqInterruptSpurious_Pre_First state +) +{ + switch ( state ) { + case BspReqInterruptSpurious_Pre_First_Null: { + /* + * While the pointer to the first interrupt entry of the interrupt vector + * specified by the ``vector`` parameter is equal to NULL. + */ + *ctx->first = NULL; + break; + } + + case BspReqInterruptSpurious_Pre_First_Entry: { + /* + * While the pointer to the first interrupt entry of the interrupt vector + * specified by the ``vector`` parameter references an object of type + * rtems_interrupt_entry. + */ + *ctx->first = &ctx->entry; + break; + } + + case BspReqInterruptSpurious_Pre_First_NA: + break; + } +} + +static void BspReqInterruptSpurious_Post_Result_Check( + BspReqInterruptSpurious_Context *ctx, + BspReqInterruptSpurious_Post_Result state +) +{ + switch ( state ) { + case BspReqInterruptSpurious_Post_Result_FatalError: { + /* + * A fatal error shall occur. + */ + T_eq_u32( ctx->entry_counter, 0 ); + T_eq_u32( ctx->fatal_counter, 1 ); + break; + } + + case BspReqInterruptSpurious_Post_Result_Dispatch: { + /* + * The interrupt entries installed at the interrupt vector specified by + * the ``vector`` parameter shall be dispatched. + */ + T_eq_u32( ctx->entry_counter, 1 ); + T_eq_u32( ctx->fatal_counter, 0 ); + break; + } + + case BspReqInterruptSpurious_Post_Result_NA: + break; + } +} + +static void BspReqInterruptSpurious_Post_FatalSource_Check( + BspReqInterruptSpurious_Context *ctx, + BspReqInterruptSpurious_Post_FatalSource state +) +{ + switch ( state ) { + case BspReqInterruptSpurious_Post_FatalSource_SpuriousInterrupt: { + /* + * The fatal source shall be equal to + * RTEMS_FATAL_SOURCE_SPURIOUS_INTERRUPT. + */ + T_eq_int( ctx->fatal_source, RTEMS_FATAL_SOURCE_SPURIOUS_INTERRUPT ); + break; + } + + case BspReqInterruptSpurious_Post_FatalSource_NA: + break; + } +} + +static void BspReqInterruptSpurious_Post_FatalCode_Check( + BspReqInterruptSpurious_Context *ctx, + BspReqInterruptSpurious_Post_FatalCode state +) +{ + switch ( state ) { + case BspReqInterruptSpurious_Post_FatalCode_Vector: { + /* + * The fatal code shall be equal to the ``vector`` parameter. + */ + T_eq_ulong( ctx->fatal_code, ctx->vector ); + break; + } + + case BspReqInterruptSpurious_Post_FatalCode_NA: + break; + } +} + +static void BspReqInterruptSpurious_Setup( + BspReqInterruptSpurious_Context *ctx +) +{ + ctx->vector = GetValidInterruptVectorNumber( NULL ); + T_assert_lt_u32( ctx->vector, BSP_INTERRUPT_VECTOR_COUNT ); + + ctx->first = &bsp_interrupt_handler_table[ + bsp_interrupt_handler_index( ctx->vector ) + ]; + + rtems_interrupt_entry_initialize( &ctx->entry, EntryRoutine, ctx, "Info" ); + SetFatalExtension( FatalExtension ); +} + +static void BspReqInterruptSpurious_Setup_Wrap( void *arg ) +{ + BspReqInterruptSpurious_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + BspReqInterruptSpurious_Setup( ctx ); +} + +static void BspReqInterruptSpurious_Teardown( + BspReqInterruptSpurious_Context *ctx +) +{ + SetFatalExtension( NULL ); +} + +static void BspReqInterruptSpurious_Teardown_Wrap( void *arg ) +{ + BspReqInterruptSpurious_Context *ctx; + + ctx = arg; + ctx->in_action_loop = false; + BspReqInterruptSpurious_Teardown( ctx ); +} + +static void BspReqInterruptSpurious_Action( + BspReqInterruptSpurious_Context *ctx +) +{ + ctx->entry_counter = 0; + ctx->fatal_counter = 0; + ctx->fatal_source = RTEMS_FATAL_SOURCE_LAST; + ctx->fatal_code = UINT32_MAX; + + if ( setjmp( ctx->before_call ) == 0 ) { + bsp_interrupt_spurious( ctx->vector ); + } +} + +typedef struct { + uint8_t Skip : 1; + uint8_t Pre_First_NA : 1; + uint8_t Post_Result : 2; + uint8_t Post_FatalSource : 1; + uint8_t Post_FatalCode : 1; +} BspReqInterruptSpurious_Entry; + +static const BspReqInterruptSpurious_Entry +BspReqInterruptSpurious_Entries[] = { + { 0, 0, BspReqInterruptSpurious_Post_Result_FatalError, + BspReqInterruptSpurious_Post_FatalSource_SpuriousInterrupt, + BspReqInterruptSpurious_Post_FatalCode_Vector }, + { 0, 0, BspReqInterruptSpurious_Post_Result_Dispatch, + BspReqInterruptSpurious_Post_FatalSource_NA, + BspReqInterruptSpurious_Post_FatalCode_NA } +}; + +static const uint8_t +BspReqInterruptSpurious_Map[] = { + 0, 1 +}; + +static size_t BspReqInterruptSpurious_Scope( void *arg, char *buf, size_t n ) +{ + BspReqInterruptSpurious_Context *ctx; + + ctx = arg; + + if ( ctx->in_action_loop ) { + return T_get_scope( BspReqInterruptSpurious_PreDesc, buf, n, ctx->pcs ); + } + + return 0; +} + +static T_fixture BspReqInterruptSpurious_Fixture = { + .setup = BspReqInterruptSpurious_Setup_Wrap, + .stop = NULL, + .teardown = BspReqInterruptSpurious_Teardown_Wrap, + .scope = BspReqInterruptSpurious_Scope, + .initial_context = &BspReqInterruptSpurious_Instance +}; + +static inline BspReqInterruptSpurious_Entry BspReqInterruptSpurious_GetEntry( + size_t index +) +{ + return BspReqInterruptSpurious_Entries[ + BspReqInterruptSpurious_Map[ index ] + ]; +} + +/** + * @fn void T_case_body_BspReqInterruptSpurious( void ) + */ +T_TEST_CASE_FIXTURE( + BspReqInterruptSpurious, + &BspReqInterruptSpurious_Fixture +) +{ + BspReqInterruptSpurious_Context *ctx; + size_t index; + + ctx = T_fixture_context(); + ctx->in_action_loop = true; + index = 0; + + for ( + ctx->pcs[ 0 ] = BspReqInterruptSpurious_Pre_First_Null; + ctx->pcs[ 0 ] < BspReqInterruptSpurious_Pre_First_NA; + ++ctx->pcs[ 0 ] + ) { + BspReqInterruptSpurious_Entry entry; + + entry = BspReqInterruptSpurious_GetEntry( index ); + ++index; + + BspReqInterruptSpurious_Pre_First_Prepare( ctx, ctx->pcs[ 0 ] ); + BspReqInterruptSpurious_Action( ctx ); + BspReqInterruptSpurious_Post_Result_Check( ctx, entry.Post_Result ); + BspReqInterruptSpurious_Post_FatalSource_Check( + ctx, + entry.Post_FatalSource + ); + BspReqInterruptSpurious_Post_FatalCode_Check( ctx, entry.Post_FatalCode ); + } +} + +/** @} */ -- cgit v1.2.3