From 82d48438441bcdf0893e3d1aa6062937d74fdb67 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Tue, 10 Aug 2021 14:04:03 -0400 Subject: [PATCH] Fix #1784, add CFE assert macros to functional test Adds the following macros to CFE assert library in cfe_assert.h: - CFE_UtAssert_SETUP - CFE_UtAssert_SUCCESS - CFE_UtAssert_NOT_SUCCESS - CFE_UtAssert_TEARDOWN - CFE_UtAssert_RESOURCEID_EQ - CFE_UtAssert_RESOURCEID_UNDEFINED - CFE_UtAssert_MEMOFFSET_EQ - CFE_UtAssert_MSGID_EQ --- modules/cfe_assert/inc/cfe_assert.h | 158 +++++++++++++++++++++ modules/cfe_assert/src/cfe_assert_runner.c | 25 ++++ 2 files changed, 183 insertions(+) diff --git a/modules/cfe_assert/inc/cfe_assert.h b/modules/cfe_assert/inc/cfe_assert.h index 5e87f0942..1eebc0db0 100644 --- a/modules/cfe_assert/inc/cfe_assert.h +++ b/modules/cfe_assert/inc/cfe_assert.h @@ -39,6 +39,7 @@ *************************************************************************/ #include "common_types.h" #include "cfe_es_api_typedefs.h" +#include "utassert.h" /************************************************************************ ** Type Definitions @@ -46,6 +47,138 @@ typedef void (*CFE_Assert_StatusCallback_t)(uint8 MessageType, const char *Prefix, const char *OutputMessage); +/************************************************************************* +** CFE-specific assertion macros +** (similar to macros in the CFE coverage test) +*************************************************************************/ + +/*****************************************************************************/ +/** +** \brief Checks the successful execution of a setup function. +** +** \par Description +** Many tests require a number of steps of setup to configure CFE such +** that the actual test can be performed. Failure of any setup steps +** result in a text message and the test being considered failed. +** +** \par Assumptions, External Events, and Notes: +** To keep logs clean, this only generates a log message if it fails +** +******************************************************************************/ +#define CFE_UtAssert_SETUP(FN) CFE_UtAssert_SuccessCheck(FN, true, UTASSERT_CASETYPE_TSF, __FILE__, __LINE__, #FN) + +/*****************************************************************************/ +/** +** \brief Asserts the nominal execution of the function being tested. +** +** \par Description +** The core of each unit test is the execution of the function being tested. +** This function and macro should be used to test the nominal execution of the +** function; the expectation is that it will return CFE_SUCCESS or an +** unspecified positive value. +** +** \par Assumptions, External Events, and Notes: +** None +** +******************************************************************************/ +#define CFE_UtAssert_SUCCESS(FN) CFE_UtAssert_SuccessCheck(FN, true, UTASSERT_CASETYPE_FAILURE, __FILE__, __LINE__, #FN) + +/*****************************************************************************/ +/** +** \brief Asserts the off-nominal execution of the function being tested. +** +** \par Description +** The core of each unit test is the execution of the function being tested. +** This function and macro should be used to test the generic off-nominal execution +** of the function; the expectation is that it will return an unspecified negative +** value. +** +** \par Assumptions, External Events, and Notes: +** This should be used in cases where a specific error for a particular condition +** is not known/documented. Whenever a specific error is indicated by the documentation, +** tests should check for that error instead of using this. +** +******************************************************************************/ +#define CFE_UtAssert_NOT_SUCCESS(FN) \ + CFE_UtAssert_SuccessCheck(FN, false, UTASSERT_CASETYPE_FAILURE, __FILE__, __LINE__, #FN) + +/*****************************************************************************/ +/** +** \brief Checks the successful execution of a teardown function. +** +** \par Description +** Many tests require a number of steps of setup to configure CFE such that the actual test +** can be performed, and undoing that configuration is the role of the teardown steps. Failure +** of any teardown steps result in a text message and the test being considered failed. +** +** \par Assumptions, External Events, and Notes: +** To keep logs clean, this only generates a log message if it fails +** +******************************************************************************/ +#define CFE_UtAssert_TEARDOWN(FN) CFE_UtAssert_SuccessCheck(FN, true, UTASSERT_CASETYPE_TTF, __FILE__, __LINE__, #FN) + +/*****************************************************************************/ +/** +** \brief Macro to check CFE resource ID for equality +** +** \par Description +** A macro that checks two resource ID values for equality. +** +** \par Assumptions, External Events, and Notes: +** The generic #UtAssert_UINT32_EQ check should not be used, as ID values +** and integers may not be interchangable with strict type checking. +** +******************************************************************************/ +#define CFE_UtAssert_RESOURCEID_EQ(id1, id2) \ + UtAssert_GenericUnsignedCompare(CFE_RESOURCEID_TO_ULONG(id1), UtAssert_Compare_EQ, CFE_RESOURCEID_TO_ULONG(id2), \ + UtAssert_Radix_HEX, __FILE__, __LINE__, "Resource ID Check: ", #id1, #id2) + +/*****************************************************************************/ +/** +** \brief Check if a Resource ID is Undefined +** +** \par Description +** A macro that checks if resource ID value is undefined. +** +** \par Assumptions, External Events, and Notes: +** This utilizes the "TEST_DEFINED" macro provided by the resourceid module, as the +** set of undefined IDs is more than the single value of CFE_RESOURCEID_UNDEFINED. +** +******************************************************************************/ +#define CFE_UtAssert_RESOURCEID_UNDEFINED(id) \ + UtAssert_True(!CFE_RESOURCEID_TEST_DEFINED(id), "%s (0x%lx) not defined", #id, CFE_RESOURCEID_TO_ULONG(id)) + +/*****************************************************************************/ +/** +** \brief Macro to check CFE memory size/offset for equality +** +** \par Description +** A macro that checks two memory offset/size values for equality. +** +** \par Assumptions, External Events, and Notes: +** This is a simple unsigned comparison which logs the values as hexadecimal +** +******************************************************************************/ +#define CFE_UtAssert_MEMOFFSET_EQ(off1, off2) \ + UtAssert_GenericUnsignedCompare(off1, UtAssert_Compare_EQ, off2, UtAssert_Radix_HEX, __FILE__, __LINE__, \ + "Offset Check: ", #off1, #off2) + +/*****************************************************************************/ +/** +** \brief Macro to check CFE message ID for equality +** +** \par Description +** A macro that checks two message ID values for equality. +** +** \par Assumptions, External Events, and Notes: +** The generic #UtAssert_UINT32_EQ check should not be used, as CFE_SB_MsgId_t values +** and integers may not be interchangable with strict type checking. +** +******************************************************************************/ +#define CFE_UtAssert_MSGID_EQ(mid1, mid2) \ + UtAssert_GenericUnsignedCompare(CFE_SB_MsgIdToValue(mid1), UtAssert_Compare_EQ, CFE_SB_MsgIdToValue(mid2), \ + UtAssert_Radix_HEX, __FILE__, __LINE__, "MsgId Check: ", #mid1, #mid2) + /************************************************************************* ** Exported Functions *************************************************************************/ @@ -145,4 +278,29 @@ int32 CFE_Assert_OpenLogFile(const char *Filename); */ void CFE_Assert_CloseLogFile(void); +/*****************************************************************************/ +/** +** \brief Helper function for nominal CFE calls +** +** \par Description +** This helper function wraps the normal UtAssert function, intended for verifying +** CFE API calls that are expected to return successfully (#CFE_SUCCESS typically). +** +** This can also be used to confirm setup and teardown operations by passing the CaseType +** parameter appropriately (UTASSERT_CASETYPE_TSF or UTASSERT_CASETYPE_TTF, respectively). +** +** \par Assumptions, External Events, and Notes: +** When used for setup (TSF) or teardown (TTF) then the test case is only logged to +** the output if it fails. This is to keep logs more concise, by not including +** test cases that are not related to the main focus of the code under test. +** +** Note this will accept any non-negative value as logical "success", so it +** also works with functions that return a size or other non-error status. +** +** \returns Test pass status, returns true if status was successful, false if it failed. +** +******************************************************************************/ +bool CFE_UtAssert_SuccessCheck(CFE_Status_t Status, bool ExpectSuccess, UtAssert_CaseType_t CaseType, const char *File, + uint32 Line, const char *Text); + #endif /* CFE_ASSERT_H */ diff --git a/modules/cfe_assert/src/cfe_assert_runner.c b/modules/cfe_assert/src/cfe_assert_runner.c index cb8ff5796..f1f63c54f 100644 --- a/modules/cfe_assert/src/cfe_assert_runner.c +++ b/modules/cfe_assert/src/cfe_assert_runner.c @@ -69,6 +69,31 @@ static CFE_EVS_BinFilter_t CFE_TR_EventFilters[] = { {UTASSERT_CASETYPE_DEBUG, CFE_EVS_NO_FILTER}, }; +bool CFE_UtAssert_SuccessCheck(CFE_Status_t Status, bool ExpectSuccess, UtAssert_CaseType_t CaseType, const char *File, + uint32 Line, const char *Text) +{ + bool Result = (Status >= CFE_SUCCESS); + char Disp; + + if (ExpectSuccess) + { + Disp = '='; + } + else + { + /* expecting non-success; result should be inverted */ + Result = !Result; + Disp = '!'; + } + + if (!Result || (CaseType != UTASSERT_CASETYPE_TSF && CaseType != UTASSERT_CASETYPE_TTF)) + { + UtAssertEx(Result, CaseType, File, Line, "%s (0x%lx) %c= CFE_SUCCESS", Text, (unsigned long)Status, Disp); + } + + return Result; +} + void CFE_Assert_StatusReport(uint8 MessageType, const char *Prefix, const char *OutputMessage) { uint16 EventType;