Skip to content

Commit

Permalink
Merge pull request #2380 from jphickey:fix-2379-sb-perftest
Browse files Browse the repository at this point in the history
Fix #2379, implement SB bulk transfer test
  • Loading branch information
dzbaker committed Sep 1, 2023
2 parents 5309e80 + 8753a09 commit 92887fa
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 2 deletions.
28 changes: 28 additions & 0 deletions modules/cfe_assert/inc/cfe_assert.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
**
Expand Down
7 changes: 6 additions & 1 deletion modules/cfe_assert/src/cfe_assert_runner.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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 */
Expand Down
3 changes: 2 additions & 1 deletion modules/cfe_testcase/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions modules/cfe_testcase/src/cfe_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ void CFE_TestMain(void)
SBPipeMangSetup();
SBSendRecvTestSetup();
SBSubscriptionTestSetup();
SBPerformanceTestSetup();
TBLContentAccessTestSetup();
TBLContentMangTestSetup();
TBLInformationTestSetup();
Expand Down
1 change: 1 addition & 0 deletions modules/cfe_testcase/src/cfe_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
147 changes: 147 additions & 0 deletions modules/cfe_testcase/src/sb_performance_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/************************************************************************
* 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", OS_TimeGetTotalMicroseconds(ElapsedTime));
}

void SBPerformanceTestSetup(void)
{
UtTest_Add(TestBulkTransmitRecv, NULL, NULL, "Test Bulk SB Transmit/Receive");
}

0 comments on commit 92887fa

Please sign in to comment.