diff --git a/.github/workflows/icbundle.yml b/.github/workflows/icbundle.yml index c943edd86..460cff552 100644 --- a/.github/workflows/icbundle.yml +++ b/.github/workflows/icbundle.yml @@ -58,11 +58,10 @@ jobs: see_entry="${see_entry}"$' ' done changelog_entry="${changelog_entry}\n${see_entry}\n" - echo "s|# Changelog|$changelog_entry|" - sed -ir "s|Changelog|$changelog_entry|" CHANGELOG.md + sed -ir "s|# Changelog|$changelog_entry|" CHANGELOG.md buildnumber_entry=$'#define CFE_BUILD_NUMBER '${rev_num}$' /**< @brief Development: Number of development git commits since CFE_BUILD_BASELINE */' - sed -ir "s|define CFE_BUILD_NUMBER.*|$buildnumber_entry|" modules/core_api/fsw/inc/cfe_version.h + sed -ir "s|#define CFE_BUILD_NUMBER.*|$buildnumber_entry|" modules/core_api/fsw/inc/cfe_version.h - name: Commit and Push Updates to IC Branch env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index e99c3ec74..3ce8c38fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Development Build: v7.0.0-rc4+dev384 +- Uninitialized PktTime in EVS_SendViaPorts +- Uninitialized ExceptionTaskID in CFE_ES_RunExceptionScan +- implement SB bulk transfer test +- TriggerMode unsigned compare with 0 +- Fixes errors in IC Bundle workflow file +- See: , , , , and + ## Development Build: v7.0.0-rc4+dev370 - 'Fix #2430, reinstate example header files.' - See: @@ -123,30 +131,7 @@ - See ## Development Build: v7.0.0-rc4+dev197 -- Remove # Changelog - -## Development Build: v7.0.0-rc4+dev366 -- 'Fix #2427, Race condition in TestCreateChild' -- See: - - -## Development Build: v7.0.0-rc4+dev362 -- 'Fix #2421, adjust dependencies on table lib' -- 'Fix #2423, avoid use of abspath make function' -- See: - - -## Development Build: v7.0.0-rc4+dev356 -- 'Fix #2415, use correct object extension in table build' -- See: - - -## Development Build: v7.0.0-rc4+dev342 -- 'Fix #2368, cFE Functional Test 23' -- 'Fix #1407, Add error report on EVS failure during log header write' -- 'Fix #1515, Remove unnecessary memset from CFE_TBL_LoadFromFile' -- See: - in Doxygen Config +- Remove Changelog in Doxygen Config - See ## Development Build: v7.0.0-rc4+dev193 diff --git a/modules/cfe_assert/inc/cfe_assert.h b/modules/cfe_assert/inc/cfe_assert.h index 082b0872e..a464432ac 100644 --- a/modules/cfe_assert/inc/cfe_assert.h +++ b/modules/cfe_assert/inc/cfe_assert.h @@ -163,6 +163,23 @@ typedef void (*CFE_Assert_StatusCallback_t)(uint8 MessageType, const char *Prefi */ #define CFE_Assert_STATUS_STORE(FN) CFE_Assert_Status_Store(FN, __FILE__, __LINE__, #FN) +/** +** \brief Check if the stored status matches a possible value +** +** Allows the caller to check the value from a previous invocation of CFE_Assert_STATUS_STORE() +** without directly asserting on the value or changing test state. +** +** This may be useful in situations where a large volume of tests are being performed, such as +** during performance or load testing, where reporting all "PASS" cases may add signficant +** extra CPU usage and log volume, interfering with the result. This macro can be followed +** or combined with CFE_Assert_STATUS_MAY_BE / CFE_Assert_STATUS_MUST_BE to do actual reporting. + +** \sa #CFE_Assert_STATUS_STORE, #CFE_Assert_STATUS_MAY_BE, #CFE_Assert_STATUS_MUST_BE +** +** \returns Actual CFE_Status_t value from the call +*/ +#define CFE_Assert_STATUS_SILENTCHECK(expected) CFE_Assert_Status_SilentCheck(expected) + /*****************************************************************************/ /** ** \brief Retroactively check for an acceptable status value from CFE_Assert_STATUS_STORE @@ -357,6 +374,17 @@ bool CFE_Assert_StatusCheck(CFE_Status_t Status, bool ExpectSuccess, UtAssert_Ca */ CFE_Status_t CFE_Assert_Status_Store(CFE_Status_t Status, const char *File, uint32 Line, const char *Text); +/** +** \brief Helper function to silently check status of a previously stored result +** +** \par Description +** This helper function will check the status previously stored to a +** temporary holding area, but does not assert on it. +** +** \returns true if status code matched, false if it did not match. +*/ +bool CFE_Assert_Status_SilentCheck(CFE_Status_t Status); + /** ** \brief Helper function for nominal CFE calls with deferred check ** diff --git a/modules/cfe_assert/src/cfe_assert_runner.c b/modules/cfe_assert/src/cfe_assert_runner.c index 5c5216d23..74a0b53a7 100644 --- a/modules/cfe_assert/src/cfe_assert_runner.c +++ b/modules/cfe_assert/src/cfe_assert_runner.c @@ -111,6 +111,11 @@ CFE_Status_t CFE_Assert_Status_Store(CFE_Status_t Status, const char *File, uint return Status; } +bool CFE_Assert_Status_SilentCheck(CFE_Status_t Status) +{ + return (Status == CFE_Assert_Global.StoredStatus); +} + bool CFE_Assert_Status_DeferredCheck(CFE_Status_t Status, UtAssert_CaseType_t CaseType, const char *File, uint32 Line, const char *Text) { @@ -125,7 +130,7 @@ bool CFE_Assert_Status_DeferredCheck(CFE_Status_t Status, UtAssert_CaseType_t Ca } else { - Result = (Status == CFE_Assert_Global.StoredStatus); + Result = CFE_Assert_Status_SilentCheck(Status); if (Result) { /* no extra tag added to "true" conditions */ diff --git a/modules/cfe_testcase/CMakeLists.txt b/modules/cfe_testcase/CMakeLists.txt index bed726c1a..6c83749ca 100644 --- a/modules/cfe_testcase/CMakeLists.txt +++ b/modules/cfe_testcase/CMakeLists.txt @@ -2,7 +2,7 @@ include_directories(inc) # Filenames based on doxygen groups. # Create the app module -add_cfe_app(cfe_testcase +add_cfe_app(cfe_testcase src/cfe_test.c src/cfe_test_table.c src/es_application_control_test.c @@ -23,6 +23,7 @@ add_cfe_app(cfe_testcase src/message_id_test.c src/msg_api_test.c src/resource_id_misc_test.c + src/sb_performance_test.c src/sb_pipe_mang_test.c src/sb_sendrecv_test.c src/sb_subscription_test.c diff --git a/modules/cfe_testcase/src/cfe_test.c b/modules/cfe_testcase/src/cfe_test.c index 9a655f0ea..388a289bf 100644 --- a/modules/cfe_testcase/src/cfe_test.c +++ b/modules/cfe_testcase/src/cfe_test.c @@ -78,6 +78,7 @@ void CFE_TestMain(void) SBPipeMangSetup(); SBSendRecvTestSetup(); SBSubscriptionTestSetup(); + SBPerformanceTestSetup(); TBLContentAccessTestSetup(); TBLContentMangTestSetup(); TBLInformationTestSetup(); diff --git a/modules/cfe_testcase/src/cfe_test.h b/modules/cfe_testcase/src/cfe_test.h index 1bd1c4e65..c31e83a5a 100644 --- a/modules/cfe_testcase/src/cfe_test.h +++ b/modules/cfe_testcase/src/cfe_test.h @@ -89,6 +89,7 @@ void FSUtilTestSetup(void); void MessageIdTestSetup(void); void MsgApiTestSetup(void); void ResourceIdMiscTestSetup(void); +void SBPerformanceTestSetup(void); void SBPipeMangSetup(void); void SBSendRecvTestSetup(void); void SBSubscriptionTestSetup(void); diff --git a/modules/cfe_testcase/src/sb_performance_test.c b/modules/cfe_testcase/src/sb_performance_test.c new file mode 100644 index 000000000..25f86ef44 --- /dev/null +++ b/modules/cfe_testcase/src/sb_performance_test.c @@ -0,0 +1,148 @@ +/************************************************************************ + * NASA Docket No. GSC-18,719-1, and identified as “core Flight System: Bootes” + * + * Copyright (c) 2020 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 + * + * Functional test of SB transmit/receive API performance + * + * The intent of this test is to perform a set of SB message transfers + * at a sufficiently high rate / volume such that the performance of + * the implementation can be characterized. Note that this + * cannot (currently) measure the performance directly, it merely implements a + * scenario that allows the performance to be measured by an external test + * harness. + */ + +#include "cfe_test.h" +#include "cfe_msgids.h" +#include "cfe_test_msgids.h" + +/* A simple command message */ +typedef struct +{ + CFE_MSG_CommandHeader_t CommandHeader; + uint32 CmdPayload; +} CFE_FT_TestCmdMessage_t; + +/* A simple telemetry message */ +typedef struct +{ + CFE_MSG_TelemetryHeader_t TelemetryHeader; + uint32 TlmPayload; +} CFE_FT_TestTlmMessage_t; + +/* + * This test procedure should be agnostic to specific MID values, but it should + * not overlap/interfere with real MIDs used by other apps. + */ +static const CFE_SB_MsgId_t CFE_FT_CMD_MSGID = CFE_SB_MSGID_WRAP_VALUE(CFE_TEST_CMD_MID); +static const CFE_SB_MsgId_t CFE_FT_TLM_MSGID = CFE_SB_MSGID_WRAP_VALUE(CFE_TEST_HK_TLM_MID); + +void TestBulkTransmitRecv(void) +{ + CFE_SB_PipeId_t PipeId1 = CFE_SB_INVALID_PIPE; + CFE_SB_PipeId_t PipeId2 = CFE_SB_INVALID_PIPE; + CFE_FT_TestCmdMessage_t CmdMsg; + CFE_FT_TestTlmMessage_t TlmMsg; + CFE_SB_Buffer_t * MsgBuf; + const CFE_FT_TestCmdMessage_t *CmdPtr; + const CFE_FT_TestTlmMessage_t *TlmPtr; + uint32 SendCount; + OS_time_t StartTime; + OS_time_t ElapsedTime; + + memset(&CmdMsg, 0, sizeof(CmdMsg)); + memset(&TlmMsg, 0, sizeof(TlmMsg)); + + UtPrintf("Testing: Bulk SB Transmit/Receive"); + CFE_PSP_GetTime(&StartTime); + + /* Setup, create a pipe and subscribe (one cmd, one tlm) */ + UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId1, 5, "TestPipe1"), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId2, 5, "TestPipe2"), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_SubscribeEx(CFE_FT_CMD_MSGID, PipeId1, CFE_SB_DEFAULT_QOS, 3), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_SubscribeEx(CFE_FT_TLM_MSGID, PipeId2, CFE_SB_DEFAULT_QOS, 3), CFE_SUCCESS); + + /* Initialize the message content */ + UtAssert_INT32_EQ(CFE_MSG_Init(CFE_MSG_PTR(CmdMsg.CommandHeader), CFE_FT_CMD_MSGID, sizeof(CmdMsg)), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_Init(CFE_MSG_PTR(TlmMsg.TelemetryHeader), CFE_FT_TLM_MSGID, sizeof(TlmMsg)), CFE_SUCCESS); + + for (SendCount = 0; SendCount < 1000000; ++SendCount) + { + CmdMsg.CmdPayload = SendCount; + TlmMsg.TlmPayload = ~SendCount; + + /* In order to not "flood" with test results, this should be silent unless a failure occurs */ + CFE_Assert_STATUS_STORE(CFE_SB_TransmitMsg(CFE_MSG_PTR(CmdMsg.CommandHeader), true)); + if (!CFE_Assert_STATUS_SILENTCHECK(CFE_SUCCESS)) + { + break; + } + + CFE_Assert_STATUS_STORE(CFE_SB_TransmitMsg(CFE_MSG_PTR(TlmMsg.TelemetryHeader), true)); + if (!CFE_Assert_STATUS_SILENTCHECK(CFE_SUCCESS)) + { + break; + } + + CFE_Assert_STATUS_STORE(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, CFE_SB_POLL)); + if (!CFE_Assert_STATUS_SILENTCHECK(CFE_SUCCESS)) + { + break; + } + + /* As above, to avoid flooding of test cases, only report mismatch here */ + CmdPtr = (const void *)MsgBuf; + if (CmdPtr->CmdPayload != CmdMsg.CmdPayload) + { + UtAssert_UINT32_EQ(CmdPtr->CmdPayload, CmdMsg.CmdPayload); + break; + } + + CFE_Assert_STATUS_STORE(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId2, CFE_SB_POLL)); + if (!CFE_Assert_STATUS_SILENTCHECK(CFE_SUCCESS)) + { + break; + } + + TlmPtr = (const void *)MsgBuf; + if (TlmPtr->TlmPayload != TlmMsg.TlmPayload) + { + UtAssert_UINT32_EQ(TlmPtr->TlmPayload, TlmMsg.TlmPayload); + break; + } + + /* report progress periodically */ + if ((SendCount % 50000) == 0) + { + UtPrintf("Success after %lu messages", (unsigned long)SendCount); + } + } + + CFE_PSP_GetTime(&ElapsedTime); + ElapsedTime = OS_TimeSubtract(ElapsedTime, StartTime); + + UtAssert_MIR("Elapsed time for SB bulk message test: %lu usec", + (unsigned long)OS_TimeGetTotalMicroseconds(ElapsedTime)); +} + +void SBPerformanceTestSetup(void) +{ + UtTest_Add(TestBulkTransmitRecv, NULL, NULL, "Test Bulk SB Transmit/Receive"); +} diff --git a/modules/core_api/fsw/inc/cfe_version.h b/modules/core_api/fsw/inc/cfe_version.h index 4052751d4..25dea4790 100644 --- a/modules/core_api/fsw/inc/cfe_version.h +++ b/modules/core_api/fsw/inc/cfe_version.h @@ -26,7 +26,7 @@ #define CFE_VERSION_H /* Development Build Macro Definitions */ -#define CFE_BUILD_NUMBER 370 /**< @brief Development: Number of development git commits since CFE_BUILD_BASELINE */ +#define CFE_BUILD_NUMBER 384 /**< @brief Development: Number of development git commits since CFE_BUILD_BASELINE */ #define CFE_BUILD_BASELINE "v7.0.0-rc4" /**< @brief Development: Reference git tag for build number */ /* See \ref cfsversions for definitions */ diff --git a/modules/es/fsw/src/cfe_es_erlog.c b/modules/es/fsw/src/cfe_es_erlog.c index 35e437288..e65163a1c 100644 --- a/modules/es/fsw/src/cfe_es_erlog.c +++ b/modules/es/fsw/src/cfe_es_erlog.c @@ -274,7 +274,7 @@ bool CFE_ES_RunExceptionScan(uint32 ElapsedTime, void *Arg) uint32 PspContextId; char ReasonString[CFE_ES_ERLOG_DESCRIPTION_MAX_LENGTH]; CFE_ES_TaskInfo_t EsTaskInfo; - osal_id_t ExceptionTaskID; + osal_id_t ExceptionTaskID = OS_OBJECT_ID_UNDEFINED; uint32 ResetType; CFE_ES_LogEntryType_Enum_t LogType; CFE_ES_AppRecord_t * AppRecPtr; diff --git a/modules/es/fsw/src/cfe_es_perf.c b/modules/es/fsw/src/cfe_es_perf.c index c6a86ad76..62233a6fa 100644 --- a/modules/es/fsw/src/cfe_es_perf.c +++ b/modules/es/fsw/src/cfe_es_perf.c @@ -155,8 +155,7 @@ int32 CFE_ES_StartPerfDataCmd(const CFE_ES_StartPerfDataCmd_t *data) PerfDumpState->PendingState == CFE_ES_PerfDumpState_IDLE) { /* Make sure Trigger Mode is valid */ - /* cppcheck-suppress unsignedPositive */ - if ((CmdPtr->TriggerMode >= CFE_ES_PERF_TRIGGER_START) && (CmdPtr->TriggerMode < CFE_ES_PERF_MAX_MODES)) + if (CmdPtr->TriggerMode < CFE_ES_PERF_MAX_MODES) { CFE_ES_Global.TaskData.CommandCounter++; diff --git a/modules/evs/fsw/src/cfe_evs_utils.c b/modules/evs/fsw/src/cfe_evs_utils.c index bf6057b05..f6fcc3260 100644 --- a/modules/evs/fsw/src/cfe_evs_utils.c +++ b/modules/evs/fsw/src/cfe_evs_utils.c @@ -540,7 +540,7 @@ void EVS_SendViaPorts(CFE_EVS_LongEventTlm_t *EVS_PktPtr) { char PortMessage[CFE_EVS_MAX_PORT_MSG_LENGTH]; char TimeBuffer[CFE_TIME_PRINTED_STRING_SIZE]; - CFE_TIME_SysTime_t PktTime; + CFE_TIME_SysTime_t PktTime = {0}; CFE_MSG_GetMsgTime(CFE_MSG_PTR(EVS_PktPtr->TelemetryHeader), &PktTime); CFE_TIME_Print(TimeBuffer, PktTime);