From 4a20389d8f42aba5ae5f8e6f328d5c4cde3a3939 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Thu, 1 Apr 2021 15:21:45 -0400 Subject: [PATCH] Fix #1266, use events for CFE test asserts Reports test failures as CFE events, which allows for more processing capability, and allows failures to be recieved externally (e.g. ground system). --- modules/cfe_assert/CMakeLists.txt | 8 +- modules/cfe_assert/inc/cfe_assert.h | 22 +++- modules/cfe_assert/src/cfe_assert_init.c | 10 +- modules/cfe_assert/src/cfe_assert_io.c | 114 ++++++++++-------- modules/cfe_assert/src/cfe_assert_priv.h | 59 +++++++++ modules/cfe_testrunner/CMakeLists.txt | 9 +- .../cfe_testrunner/src/cfe_testrunner_main.c | 58 +++++++++ 7 files changed, 219 insertions(+), 61 deletions(-) create mode 100644 modules/cfe_assert/src/cfe_assert_priv.h diff --git a/modules/cfe_assert/CMakeLists.txt b/modules/cfe_assert/CMakeLists.txt index c80330ab8..d4cc58182 100644 --- a/modules/cfe_assert/CMakeLists.txt +++ b/modules/cfe_assert/CMakeLists.txt @@ -1,8 +1,5 @@ project(CFE_ASSERT C) -include_directories("${CFE_ASSERT_SOURCE_DIR}/inc") -include_directories("${UT_ASSERT_SOURCE_DIR}/inc") - # Create the app module add_cfe_app(cfe_assert src/cfe_assert_io.c @@ -10,3 +7,8 @@ add_cfe_app(cfe_assert $ ) +# publicize the interface to cfe_assert (and ut_assert) +target_include_directories(cfe_assert PUBLIC + ${CFE_ASSERT_SOURCE_DIR}/inc + $ +) diff --git a/modules/cfe_assert/inc/cfe_assert.h b/modules/cfe_assert/inc/cfe_assert.h index c2cca7d7d..9ca074134 100644 --- a/modules/cfe_assert/inc/cfe_assert.h +++ b/modules/cfe_assert/inc/cfe_assert.h @@ -43,6 +43,8 @@ ** Type Definitions *************************************************************************/ +typedef void (*CFE_Assert_StatusCallback_t)(uint8 MessageType, const char *Prefix, const char *OutputMessage); + /************************************************************************* ** Exported Functions *************************************************************************/ @@ -57,9 +59,27 @@ ** \par Assumptions, External Events, and Notes: ** None ** -** \return Execution status, see \ref CFEReturnCodes +** \return None ** *************************************************************************/ void CFE_Assert_AppMain(void); +/************************************************************************/ +/** \brief Register a test status callback + * + * \par Description + * This user-supplied function will be invoked with the status + * of each test and the associated message. It may be used to + * write the test messages to a location other than CFE ES Syslog. + * + * \par Assumptions, External Events, and Notes: + * None + * + * \param[in] Callback Callback function to invoke after every test + * + * \return None + * + */ +void CFE_Assert_RegisterCallback(CFE_Assert_StatusCallback_t Callback); + #endif /* CFE_ASSERT_H */ diff --git a/modules/cfe_assert/src/cfe_assert_init.c b/modules/cfe_assert/src/cfe_assert_init.c index e4c2fa59f..57d0ac9b5 100644 --- a/modules/cfe_assert/src/cfe_assert_init.c +++ b/modules/cfe_assert/src/cfe_assert_init.c @@ -31,11 +31,19 @@ #include "cfe.h" -#include "cfe_assert.h" +#include "cfe_assert_priv.h" #include "uttest.h" #include "utbsp.h" +/* + * Allows the test reports to be redirected to another destination + */ +void CFE_Assert_RegisterCallback(CFE_Assert_StatusCallback_t Callback) +{ + CFE_Assert_Global.StatusCallback = Callback; +} + /* * Initialization Function for this library */ diff --git a/modules/cfe_assert/src/cfe_assert_io.c b/modules/cfe_assert/src/cfe_assert_io.c index cff4893a0..b68326e81 100644 --- a/modules/cfe_assert/src/cfe_assert_io.c +++ b/modules/cfe_assert/src/cfe_assert_io.c @@ -31,23 +31,16 @@ #include #include "cfe.h" +#include "cfe_assert_priv.h" #include "utbsp.h" #include "uttest.h" -/* -** Local Variables -*/ -typedef struct -{ - uint32 CurrVerbosity; -} BSP_UT_GlobalData_t; - -BSP_UT_GlobalData_t BSP_UT_Global; +CFE_Assert_Global_t CFE_Assert_Global; void UT_BSP_Setup(void) { - BSP_UT_Global.CurrVerbosity = (2 << UTASSERT_CASETYPE_PASS) - 1; + CFE_Assert_Global.CurrVerbosity = (2 << UTASSERT_CASETYPE_PASS) - 1; UT_BSP_DoText(UTASSERT_CASETYPE_BEGIN, "CFE FUNCTIONAL TEST"); } @@ -59,55 +52,70 @@ void UT_BSP_StartTestSegment(uint32 SegmentNumber, const char *SegmentName) UT_BSP_DoText(UTASSERT_CASETYPE_BEGIN, ReportBuffer); } -void UT_BSP_DoText(uint8 MessageType, const char *OutputMessage) +void UT_BSP_SysLogStatusReport(uint8 MessageType, const char *Prefix, const char *OutputMessage) { - const char *Prefix; - uint32 MsgEnabled = BSP_UT_Global.CurrVerbosity >> MessageType; + uint32 MsgEnabled = CFE_Assert_Global.CurrVerbosity >> MessageType; if (MsgEnabled & 1) { - switch (MessageType) - { - case UTASSERT_CASETYPE_ABORT: - Prefix = "ABORT"; - break; - case UTASSERT_CASETYPE_FAILURE: - Prefix = "FAIL"; - break; - case UTASSERT_CASETYPE_MIR: - Prefix = "MIR"; - break; - case UTASSERT_CASETYPE_TSF: - Prefix = "TSF"; - break; - case UTASSERT_CASETYPE_TTF: - Prefix = "TTF"; - break; - case UTASSERT_CASETYPE_NA: - Prefix = "N/A"; - break; - case UTASSERT_CASETYPE_BEGIN: - Prefix = "BEGIN"; - break; - case UTASSERT_CASETYPE_END: - Prefix = "END"; - break; - case UTASSERT_CASETYPE_PASS: - Prefix = "PASS"; - break; - case UTASSERT_CASETYPE_INFO: - Prefix = "INFO"; - break; - case UTASSERT_CASETYPE_DEBUG: - Prefix = "DEBUG"; - break; - default: - Prefix = "OTHER"; - break; - } - CFE_ES_WriteToSysLog("[%5s] %s\n", Prefix, OutputMessage); } +} + +void UT_BSP_DoText(uint8 MessageType, const char *OutputMessage) +{ + const char * Prefix; + CFE_Assert_StatusCallback_t StatusCallback; + + switch (MessageType) + { + case UTASSERT_CASETYPE_ABORT: + Prefix = "ABORT"; + break; + case UTASSERT_CASETYPE_FAILURE: + Prefix = "FAIL"; + break; + case UTASSERT_CASETYPE_MIR: + Prefix = "MIR"; + break; + case UTASSERT_CASETYPE_TSF: + Prefix = "TSF"; + break; + case UTASSERT_CASETYPE_TTF: + Prefix = "TTF"; + break; + case UTASSERT_CASETYPE_NA: + Prefix = "N/A"; + break; + case UTASSERT_CASETYPE_BEGIN: + Prefix = "BEGIN"; + break; + case UTASSERT_CASETYPE_END: + Prefix = "END"; + break; + case UTASSERT_CASETYPE_PASS: + Prefix = "PASS"; + break; + case UTASSERT_CASETYPE_INFO: + Prefix = "INFO"; + break; + case UTASSERT_CASETYPE_DEBUG: + Prefix = "DEBUG"; + break; + default: + Prefix = "OTHER"; + break; + } + + StatusCallback = CFE_Assert_Global.StatusCallback; + + /* If not set, report status to CFE ES Syslog facility */ + if (StatusCallback == NULL) + { + StatusCallback = UT_BSP_SysLogStatusReport; + } + + StatusCallback(MessageType, Prefix, OutputMessage); /* * If any ABORT (major failure) message is thrown, diff --git a/modules/cfe_assert/src/cfe_assert_priv.h b/modules/cfe_assert/src/cfe_assert_priv.h new file mode 100644 index 000000000..6bfb88b9d --- /dev/null +++ b/modules/cfe_assert/src/cfe_assert_priv.h @@ -0,0 +1,59 @@ +/************************************************************************* +** +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** File: cfe_assert.h +** +** Purpose: +** Specification for the CFE assert (UT assert wrapper) functions. +** +*************************************************************************/ + +/** + * @file + * + * Internal Declarations and prototypes for cfe_assert module + */ + +#ifndef CFE_ASSERT_PRIV_H +#define CFE_ASSERT_PRIV_H + +/************************************************************************ +** Includes +*************************************************************************/ +#include "common_types.h" +#include "cfe_assert.h" + +/************************************************************************ +** Type Definitions +*************************************************************************/ + +typedef struct +{ + uint32 CurrVerbosity; + + /** + * Function to invoke to report test status + */ + CFE_Assert_StatusCallback_t StatusCallback; +} CFE_Assert_Global_t; + +extern CFE_Assert_Global_t CFE_Assert_Global; + +#endif /* CFE_ASSERT_PRIV_H */ diff --git a/modules/cfe_testrunner/CMakeLists.txt b/modules/cfe_testrunner/CMakeLists.txt index 24d153262..b4df50bc6 100644 --- a/modules/cfe_testrunner/CMakeLists.txt +++ b/modules/cfe_testrunner/CMakeLists.txt @@ -1,10 +1,13 @@ project(CFE_TESTRUNNER C) -include_directories("inc") -include_directories("${UT_ASSERT_SOURCE_DIR}/inc") - # Create the app module add_cfe_app(cfe_testrunner src/cfe_testrunner_main.c ) +target_include_directories(cfe_testrunner PUBLIC + ${CFE_TESTRUNNER_SOURCE_DIR}/inc +) + +# register the dependency on cfe_assert +add_cfe_app_dependency(cfe_testrunner cfe_assert) diff --git a/modules/cfe_testrunner/src/cfe_testrunner_main.c b/modules/cfe_testrunner/src/cfe_testrunner_main.c index f866777c6..e2e8b0cbe 100644 --- a/modules/cfe_testrunner/src/cfe_testrunner_main.c +++ b/modules/cfe_testrunner/src/cfe_testrunner_main.c @@ -32,6 +32,7 @@ #include "cfe.h" #include "cfe_testrunner.h" +#include "cfe_assert.h" #include "uttest.h" #include "utbsp.h" @@ -56,6 +57,50 @@ */ #define CFE_TESTRUNNER_START_DELAY 4000 +/* + * This uses the message type as the event ID, because these are already + * sequential integers, and there is no need to redefine - this app has no other events. + */ +static CFE_EVS_BinFilter_t CFE_TR_EventFilters[] = { + {UTASSERT_CASETYPE_ABORT, CFE_EVS_NO_FILTER}, {UTASSERT_CASETYPE_FAILURE, CFE_EVS_NO_FILTER}, + {UTASSERT_CASETYPE_TSF, CFE_EVS_NO_FILTER}, {UTASSERT_CASETYPE_TTF, CFE_EVS_NO_FILTER}, + {UTASSERT_CASETYPE_MIR, CFE_EVS_NO_FILTER}, {UTASSERT_CASETYPE_NA, CFE_EVS_NO_FILTER}, + {UTASSERT_CASETYPE_BEGIN, CFE_EVS_NO_FILTER}, {UTASSERT_CASETYPE_END, CFE_EVS_NO_FILTER}, + {UTASSERT_CASETYPE_INFO, CFE_EVS_NO_FILTER}, {UTASSERT_CASETYPE_PASS, CFE_EVS_NO_FILTER}, + {UTASSERT_CASETYPE_DEBUG, CFE_EVS_NO_FILTER}, +}; + +void CFE_TR_StatusReport(uint8 MessageType, const char *Prefix, const char *OutputMessage) +{ + uint16 EventType; + + switch (MessageType) + { + case UTASSERT_CASETYPE_ABORT: + EventType = CFE_EVS_EventType_CRITICAL; + break; + case UTASSERT_CASETYPE_FAILURE: + case UTASSERT_CASETYPE_TSF: + case UTASSERT_CASETYPE_TTF: + EventType = CFE_EVS_EventType_ERROR; + break; + case UTASSERT_CASETYPE_INFO: + case UTASSERT_CASETYPE_MIR: + case UTASSERT_CASETYPE_NA: + EventType = CFE_EVS_EventType_INFORMATION; + break; + case UTASSERT_CASETYPE_BEGIN: + case UTASSERT_CASETYPE_END: + case UTASSERT_CASETYPE_PASS: + case UTASSERT_CASETYPE_DEBUG: + default: + EventType = CFE_EVS_EventType_DEBUG; + break; + } + + CFE_EVS_SendEvent(MessageType, EventType, "[%5s] %s", Prefix, OutputMessage); +} + /* * Entry point for this application */ @@ -64,6 +109,14 @@ void CFE_TR_AppMain(void) int32 rc; uint32 RunStatus; + rc = CFE_EVS_Register(CFE_TR_EventFilters, sizeof(CFE_TR_EventFilters) / sizeof(CFE_EVS_BinFilter_t), + CFE_EVS_EventFilter_BINARY); + if (rc != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("Error from CFE_EVS_Register: %08lx\n", (unsigned long)rc); + return; + } + /* * Delay until the system reaches "operational" state -- this is when all libs have initialized * and all apps have reached their RunLoop. @@ -80,6 +133,11 @@ void CFE_TR_AppMain(void) */ UtAssert_EndTest(); + /* + * Use the local status report function for the remainder of tests + */ + CFE_Assert_RegisterCallback(CFE_TR_StatusReport); + /* * Note - in a normal app this would be a while loop, * but is just an "if" right now as it only runs once.