diff --git a/cmake/sample_defs/cpu1_msgids.h b/cmake/sample_defs/cpu1_msgids.h index 0da698f15..72f311c0e 100644 --- a/cmake/sample_defs/cpu1_msgids.h +++ b/cmake/sample_defs/cpu1_msgids.h @@ -86,8 +86,8 @@ /* ** cFE Command Message Id's */ -#define CFE_EVS_CMD_MID CFE_PLATFORM_CMD_MID_BASE + CFE_MISSION_EVS_CMD_MSG /* 0x1801 */ - /* Message ID 0x1802 is available */ +#define CFE_EVS_CMD_MID CFE_PLATFORM_CMD_MID_BASE + CFE_MISSION_EVS_CMD_MSG /* 0x1801 */ +#define CFE_TEST_CMD_MID CFE_PLATFORM_CMD_MID_BASE + CFE_MISSION_TEST_CMD_MSG /* 0x1802 */ #define CFE_SB_CMD_MID CFE_PLATFORM_CMD_MID_BASE + CFE_MISSION_SB_CMD_MSG /* 0x1803 */ #define CFE_TBL_CMD_MID CFE_PLATFORM_CMD_MID_BASE + CFE_MISSION_TBL_CMD_MSG /* 0x1804 */ #define CFE_TIME_CMD_MID CFE_PLATFORM_CMD_MID_BASE + CFE_MISSION_TIME_CMD_MSG /* 0x1805 */ @@ -114,9 +114,9 @@ /* ** CFE Telemetry Message Id's */ -#define CFE_ES_HK_TLM_MID CFE_PLATFORM_TLM_MID_BASE + CFE_MISSION_ES_HK_TLM_MSG /* 0x0800 */ -#define CFE_EVS_HK_TLM_MID CFE_PLATFORM_TLM_MID_BASE + CFE_MISSION_EVS_HK_TLM_MSG /* 0x0801 */ - /* Message ID 0x0802 is available */ +#define CFE_ES_HK_TLM_MID CFE_PLATFORM_TLM_MID_BASE + CFE_MISSION_ES_HK_TLM_MSG /* 0x0800 */ +#define CFE_EVS_HK_TLM_MID CFE_PLATFORM_TLM_MID_BASE + CFE_MISSION_EVS_HK_TLM_MSG /* 0x0801 */ +#define CFE_TEST_HK_TLM_MID CFE_PLATFORM_TLM_MID_BASE + CFE_MISSION_TEST_HK_TLM_MSG /* 0x0802 */ #define CFE_SB_HK_TLM_MID CFE_PLATFORM_TLM_MID_BASE + CFE_MISSION_SB_HK_TLM_MSG /* 0x0803 */ #define CFE_TBL_HK_TLM_MID CFE_PLATFORM_TLM_MID_BASE + CFE_MISSION_TBL_HK_TLM_MSG /* 0x0804 */ #define CFE_TIME_HK_TLM_MID CFE_PLATFORM_TLM_MID_BASE + CFE_MISSION_TIME_HK_TLM_MSG /* 0x0805 */ diff --git a/cmake/sample_defs/sample_mission_cfg.h b/cmake/sample_defs/sample_mission_cfg.h index 319587389..144a9d0f2 100644 --- a/cmake/sample_defs/sample_mission_cfg.h +++ b/cmake/sample_defs/sample_mission_cfg.h @@ -307,8 +307,8 @@ ** \par Limits ** Not Applicable */ -#define CFE_MISSION_EVS_CMD_MSG 1 -/* Offset 2 is available */ +#define CFE_MISSION_EVS_CMD_MSG 1 +#define CFE_MISSION_TEST_CMD_MSG 2 #define CFE_MISSION_SB_CMD_MSG 3 #define CFE_MISSION_TBL_CMD_MSG 4 #define CFE_MISSION_TIME_CMD_MSG 5 @@ -351,9 +351,9 @@ ** \par Limits ** Not Applicable */ -#define CFE_MISSION_ES_HK_TLM_MSG 0 -#define CFE_MISSION_EVS_HK_TLM_MSG 1 -/* Offset 2 is available */ +#define CFE_MISSION_ES_HK_TLM_MSG 0 +#define CFE_MISSION_EVS_HK_TLM_MSG 1 +#define CFE_MISSION_TEST_HK_TLM_MSG 2 #define CFE_MISSION_SB_HK_TLM_MSG 3 #define CFE_MISSION_TBL_HK_TLM_MSG 4 #define CFE_MISSION_TIME_HK_TLM_MSG 5 @@ -418,6 +418,7 @@ ** anticipated to be reasonably small (i.e. tens, not hundreds). Large ** values have not been tested. ** +** */ #define CFE_MISSION_ES_POOL_MAX_BUCKETS 17 diff --git a/modules/cfe_testcase/CMakeLists.txt b/modules/cfe_testcase/CMakeLists.txt index 8795cc96e..e943d681b 100644 --- a/modules/cfe_testcase/CMakeLists.txt +++ b/modules/cfe_testcase/CMakeLists.txt @@ -22,6 +22,8 @@ add_cfe_app(cfe_testcase src/message_id_test.c src/msg_api_test.c src/sb_pipe_mang_test.c + src/sb_sendrecv_test.c + src/sb_subscription_test.c src/tbl_content_access_test.c src/tbl_content_mang_test.c src/tbl_information_test.c diff --git a/modules/cfe_testcase/src/cfe_test.c b/modules/cfe_testcase/src/cfe_test.c index e970fc444..46014bc3d 100644 --- a/modules/cfe_testcase/src/cfe_test.c +++ b/modules/cfe_testcase/src/cfe_test.c @@ -75,6 +75,8 @@ void CFE_TestMain(void) MessageIdTestSetup(); MsgApiTestSetup(); SBPipeMangSetup(); + SBSendRecvTestSetup(); + SBSubscriptionTestSetup(); TBLContentAccessTestSetup(); TBLContentMangTestSetup(); TBLInformationTestSetup(); diff --git a/modules/cfe_testcase/src/cfe_test.h b/modules/cfe_testcase/src/cfe_test.h index 4931c5063..43f878fd5 100644 --- a/modules/cfe_testcase/src/cfe_test.h +++ b/modules/cfe_testcase/src/cfe_test.h @@ -110,6 +110,8 @@ void FSUtilTestSetup(void); void MessageIdTestSetup(void); void MsgApiTestSetup(void); void SBPipeMangSetup(void); +void SBSendRecvTestSetup(void); +void SBSubscriptionTestSetup(void); void TBLContentAccessTestSetup(void); void TBLContentMangTestSetup(void); void TBLInformationTestSetup(void); diff --git a/modules/cfe_testcase/src/sb_sendrecv_test.c b/modules/cfe_testcase/src/sb_sendrecv_test.c new file mode 100644 index 000000000..699a73123 --- /dev/null +++ b/modules/cfe_testcase/src/sb_sendrecv_test.c @@ -0,0 +1,283 @@ +/************************************************************************* +** +** 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 + * + * Functional test of SB transmit/receive APIs + * CFE_SB_TransmitMsg - Transmit a message. + * CFE_SB_ReceiveBuffer - Receive a message from a software bus pipe. + * CFE_SB_AllocateMessageBuffer - Get a buffer pointer to use for "zero copy" SB sends. + * CFE_SB_ReleaseMessageBuffer - Release an unused "zero copy" buffer pointer. + * CFE_SB_TransmitBuffer - Transmit a buffer. + */ + +#include "cfe_test.h" +#include "cfe_msgids.h" + +/* A simple command message */ +typedef struct +{ + CFE_MSG_CommandHeader_t CmdHeader; + uint32 CmdPayload; +} CFE_FT_TestCmdMessage_t; + +/* A simple telemetry message */ +typedef struct +{ + CFE_MSG_TelemetryHeader_t TlmHeader; + uint32 TlmPayload; +} CFE_FT_TestTlmMessage_t; + +/* A message intended to be (overall) larger than the CFE_MISSION_SB_MAX_SB_MSG_SIZE */ +typedef struct +{ + CFE_MSG_Message_t Hdr; + uint8 MaxSize[CFE_MISSION_SB_MAX_SB_MSG_SIZE]; +} CFE_FT_TestBigMessage_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); + +static CFE_FT_TestBigMessage_t CFE_FT_BigMsg; + +void TestBasicTransmitRecv(void) +{ + CFE_SB_PipeId_t PipeId1; + CFE_SB_PipeId_t PipeId2; + CFE_FT_TestCmdMessage_t CmdMsg; + CFE_FT_TestTlmMessage_t TlmMsg; + CFE_SB_MsgId_t MsgId; + CFE_MSG_SequenceCount_t Seq1, Seq2; + CFE_SB_Buffer_t * MsgBuf; + const CFE_FT_TestCmdMessage_t *CmdPtr; + const CFE_FT_TestTlmMessage_t *TlmPtr; + + UtPrintf("Testing: CFE_SB_TransmitMsg"); + + /* 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(&CmdMsg.CmdHeader.Msg, CFE_FT_CMD_MSGID, sizeof(CmdMsg)), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_Init(&TlmMsg.TlmHeader.Msg, CFE_FT_TLM_MSGID, sizeof(TlmMsg)), CFE_SUCCESS); + + CFE_MSG_SetSequenceCount(&CmdMsg.CmdHeader.Msg, 11); + CFE_MSG_SetSequenceCount(&TlmMsg.TlmHeader.Msg, 21); + + /* Sending with sequence update should ignore the sequence in the msg struct */ + CmdMsg.CmdPayload = 0x0c0ffee; + TlmMsg.TlmPayload = 0x0d00d1e; + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&CmdMsg.CmdHeader.Msg, true), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&TlmMsg.TlmHeader.Msg, true), CFE_SUCCESS); + + CmdMsg.CmdPayload = 0x1c0ffee; + TlmMsg.TlmPayload = 0x1d00d1e; + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&CmdMsg.CmdHeader.Msg, true), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&TlmMsg.TlmHeader.Msg, true), CFE_SUCCESS); + + /* Sending without sequence update should use the sequence in the msg struct */ + CmdMsg.CmdPayload = 0x2c0ffee; + TlmMsg.TlmPayload = 0x2d00d1e; + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&CmdMsg.CmdHeader.Msg, false), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&TlmMsg.TlmHeader.Msg, false), CFE_SUCCESS); + + /* Sending again should trigger MsgLimit errors on the pipe, however the call still returns CFE_SUCCESS */ + CmdMsg.CmdPayload = 0x3c0ffee; + TlmMsg.TlmPayload = 0x3d00d1e; + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&CmdMsg.CmdHeader.Msg, true), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&TlmMsg.TlmHeader.Msg, true), CFE_SUCCESS); + + /* Attempt to send a msg which does not have a valid msgid */ + memset(&CFE_FT_BigMsg, 0xFF, sizeof(CFE_FT_BigMsg)); + CFE_MSG_SetSize(&CFE_FT_BigMsg.Hdr, sizeof(CFE_MSG_Message_t) + 4); + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&CFE_FT_BigMsg.Hdr, true), CFE_SB_BAD_ARGUMENT); + + /* Attempt to send a msg which is too big */ + CFE_MSG_SetSize(&CFE_FT_BigMsg.Hdr, sizeof(CFE_FT_BigMsg)); + CFE_MSG_SetMsgId(&CFE_FT_BigMsg.Hdr, CFE_FT_CMD_MSGID); + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&CFE_FT_BigMsg.Hdr, true), CFE_SB_MSG_TOO_BIG); + + /* Attempt to send a msg which is NULL */ + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(NULL, true), CFE_SB_BAD_ARGUMENT); + + UtPrintf("Testing: CFE_SB_ReceiveBuffer"); + + /* off nominal / bad arguments */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, CFE_SB_INVALID_PIPE, 100), CFE_SB_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(NULL, PipeId1, 100), CFE_SB_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, -100), CFE_SB_BAD_ARGUMENT); + + /* + * Note, the CFE_SB_TransmitMsg ignores the "IncrementSequence" flag for commands. + * Thus, all the sequence numbers should come back with the original value set (11) + */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, 100), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf->Msg, &MsgId), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetSequenceCount(&MsgBuf->Msg, &Seq1), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_CMD_MSGID); + CmdPtr = (const CFE_FT_TestCmdMessage_t *)MsgBuf; + UtAssert_UINT32_EQ(CmdPtr->CmdPayload, 0x0c0ffee); + UtAssert_UINT32_EQ(Seq1, 11); + + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, 100), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf->Msg, &MsgId), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetSequenceCount(&MsgBuf->Msg, &Seq1), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_CMD_MSGID); + CmdPtr = (const CFE_FT_TestCmdMessage_t *)MsgBuf; + UtAssert_UINT32_EQ(CmdPtr->CmdPayload, 0x1c0ffee); + UtAssert_UINT32_EQ(Seq1, 11); + + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, 100), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf->Msg, &MsgId), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetSequenceCount(&MsgBuf->Msg, &Seq1), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_CMD_MSGID); + CmdPtr = (const CFE_FT_TestCmdMessage_t *)MsgBuf; + UtAssert_UINT32_EQ(CmdPtr->CmdPayload, 0x2c0ffee); + UtAssert_UINT32_EQ(Seq1, 11); + + /* Final should not be in the pipe, should have been rejected due to MsgLim */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, 100), CFE_SB_TIME_OUT); + + /* + * For TLM, the CFE_SB_TransmitMsg obeys the "IncrementSequence" flag. + * Thus, first message gets the reference point, next message should be one more. + */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId2, 100), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf->Msg, &MsgId), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetSequenceCount(&MsgBuf->Msg, &Seq1), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_TLM_MSGID); + TlmPtr = (const CFE_FT_TestTlmMessage_t *)MsgBuf; + UtAssert_UINT32_EQ(TlmPtr->TlmPayload, 0x0d00d1e); + + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId2, 100), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf->Msg, &MsgId), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetSequenceCount(&MsgBuf->Msg, &Seq2), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_TLM_MSGID); + TlmPtr = (const CFE_FT_TestTlmMessage_t *)MsgBuf; + UtAssert_UINT32_EQ(TlmPtr->TlmPayload, 0x1d00d1e); + UtAssert_UINT32_EQ(Seq2, CFE_MSG_GetNextSequenceCount(Seq1)); + + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId2, 100), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf->Msg, &MsgId), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetSequenceCount(&MsgBuf->Msg, &Seq2), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_TLM_MSGID); + TlmPtr = (const CFE_FT_TestTlmMessage_t *)MsgBuf; + UtAssert_UINT32_EQ(TlmPtr->TlmPayload, 0x2d00d1e); + UtAssert_UINT32_EQ(Seq2, 21); + + /* Final should not be in the pipe, should have been rejected due to MsgLim */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId2, 100), CFE_SB_TIME_OUT); + + /* Cleanup */ + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId2), CFE_SUCCESS); +} + +/* This is a variant of the message transmit API that does not copy */ +void TestZeroCopyTransmitRecv(void) +{ + CFE_SB_PipeId_t PipeId1; + CFE_SB_PipeId_t PipeId2; + CFE_SB_Buffer_t *CmdBuf; + CFE_SB_Buffer_t *TlmBuf; + CFE_SB_Buffer_t *MsgBuf; + CFE_SB_MsgId_t MsgId; + + /* 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); + + UtPrintf("Testing: CFE_SB_AllocateMessageBuffer"); + + /* Confirm bad size rejection */ + UtAssert_NULL(CFE_SB_AllocateMessageBuffer(CFE_MISSION_SB_MAX_SB_MSG_SIZE + 1)); + + /* Nominal */ + UtAssert_NOT_NULL(CmdBuf = CFE_SB_AllocateMessageBuffer(sizeof(CFE_FT_TestCmdMessage_t))); + UtAssert_NOT_NULL(TlmBuf = CFE_SB_AllocateMessageBuffer(sizeof(CFE_FT_TestTlmMessage_t))); + + UtPrintf("Testing: CFE_SB_ReleaseMessageBuffer"); + + /* allocate a buffer but then discard it without sending */ + UtAssert_NOT_NULL(MsgBuf = CFE_SB_AllocateMessageBuffer(sizeof(CFE_MSG_Message_t) + 4)); + UtAssert_INT32_EQ(CFE_SB_ReleaseMessageBuffer(MsgBuf), CFE_SUCCESS); + + /* Attempt to double-release, should fail validation */ + UtAssert_INT32_EQ(CFE_SB_ReleaseMessageBuffer(MsgBuf), CFE_SB_BUFFER_INVALID); + + /* Other bad input checking */ + UtAssert_INT32_EQ(CFE_SB_ReleaseMessageBuffer(NULL), CFE_SB_BAD_ARGUMENT); + + UtPrintf("Testing: CFE_SB_TransmitBuffer"); + + /* Initialize the message content */ + UtAssert_INT32_EQ(CFE_MSG_Init(&CmdBuf->Msg, CFE_FT_CMD_MSGID, sizeof(CFE_FT_TestCmdMessage_t)), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_Init(&TlmBuf->Msg, CFE_FT_TLM_MSGID, sizeof(CFE_FT_TestTlmMessage_t)), CFE_SUCCESS); + + UtAssert_INT32_EQ(CFE_SB_TransmitBuffer(CmdBuf, true), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitBuffer(TlmBuf, true), CFE_SUCCESS); + + /* Attempt to send a buffer which has been released */ + UtAssert_NOT_NULL(MsgBuf = CFE_SB_AllocateMessageBuffer(sizeof(CFE_MSG_Message_t) + 4)); + UtAssert_INT32_EQ(CFE_MSG_Init(&MsgBuf->Msg, CFE_FT_CMD_MSGID, sizeof(CFE_MSG_Message_t) + 4), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_ReleaseMessageBuffer(MsgBuf), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitBuffer(MsgBuf, true), CFE_SB_BUFFER_INVALID); + + /* Attempt to send a NULL buffer */ + UtAssert_INT32_EQ(CFE_SB_TransmitBuffer(NULL, true), CFE_SB_BAD_ARGUMENT); + + UtPrintf("Testing: CFE_SB_ReceiveBuffer"); + + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, 100), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf->Msg, &MsgId), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_CMD_MSGID); + UtAssert_ADDRESS_EQ(MsgBuf, CmdBuf); /* should be the same actual buffer (not a copy) */ + + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, 100), CFE_SB_TIME_OUT); + + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId2, 100), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf->Msg, &MsgId), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_TLM_MSGID); + UtAssert_ADDRESS_EQ(MsgBuf, TlmBuf); /* should be the same actual buffer (not a copy) */ + + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId2, 100), CFE_SB_TIME_OUT); + + /* Cleanup */ + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId2), CFE_SUCCESS); +} + +void SBSendRecvTestSetup(void) +{ + UtTest_Add(TestBasicTransmitRecv, NULL, NULL, "Test Basic Transmit/Receive"); + UtTest_Add(TestZeroCopyTransmitRecv, NULL, NULL, "Test Zero Copy Transmit/Receive"); +} diff --git a/modules/cfe_testcase/src/sb_subscription_test.c b/modules/cfe_testcase/src/sb_subscription_test.c new file mode 100644 index 000000000..7fe51de5d --- /dev/null +++ b/modules/cfe_testcase/src/sb_subscription_test.c @@ -0,0 +1,253 @@ +/************************************************************************* +** +** 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 + * + * Functional test of SB subscription APIs + * CFE_SB_Subscribe - Subscribe to a message on the software bus with default parameters. + * CFE_SB_SubscribeEx - Subscribe to a message on the software bus. + * CFE_SB_SubscribeLocal - Subscribe to a message while keeping the request local to a cpu. + * CFE_SB_Unsubscribe - Remove a subscription to a message on the software bus. + * CFE_SB_UnsubscribeLocal - Remove a subscription to a message on the software bus on the current CPU. + */ + +#include "cfe_test.h" +#include "cfe_msgids.h" + +/* + * 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 TestSubscribeUnsubscribe(void) +{ + CFE_SB_PipeId_t PipeId1; + CFE_SB_PipeId_t PipeId2; + + UtPrintf("Testing: CFE_SB_Subscribe, CFE_SB_Unsubscribe"); + + /* Setup, create some pipes */ + UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId1, 3, "TestPipe1"), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId2, 3, "TestPipe2"), CFE_SUCCESS); + + /* Subscribe - Confirm Bad MsgId Arg Rejection */ + UtAssert_INT32_EQ(CFE_SB_Subscribe(CFE_SB_INVALID_MSG_ID, PipeId1), CFE_SB_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_SB_Subscribe(CFE_SB_MSGID_RESERVED, PipeId2), CFE_SB_BAD_ARGUMENT); + + /* Subscribe - Confirm Bad PipeId Arg Rejection */ + UtAssert_INT32_EQ(CFE_SB_Subscribe(CFE_FT_CMD_MSGID, CFE_SB_INVALID_PIPE), CFE_SB_BAD_ARGUMENT); + + /* Subscribe - Nominal */ + UtAssert_INT32_EQ(CFE_SB_Subscribe(CFE_FT_CMD_MSGID, PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_Subscribe(CFE_FT_TLM_MSGID, PipeId2), CFE_SUCCESS); + + /* Subscribe - Duplicate */ + UtAssert_INT32_EQ(CFE_SB_Subscribe(CFE_FT_CMD_MSGID, PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_Subscribe(CFE_FT_TLM_MSGID, PipeId2), CFE_SUCCESS); + + /* Subscribe - Nominal 2 */ + UtAssert_INT32_EQ(CFE_SB_Subscribe(CFE_FT_TLM_MSGID, PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_Subscribe(CFE_FT_CMD_MSGID, PipeId2), CFE_SUCCESS); + + /* Unsubscribe - Confirm Bad MsgId Arg Rejection */ + UtAssert_INT32_EQ(CFE_SB_Unsubscribe(CFE_SB_INVALID_MSG_ID, PipeId1), CFE_SB_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_SB_Unsubscribe(CFE_SB_MSGID_RESERVED, PipeId2), CFE_SB_BAD_ARGUMENT); + + /* Unsubscribe - Confirm Bad PipeId Arg Rejection */ + UtAssert_INT32_EQ(CFE_SB_Unsubscribe(CFE_FT_CMD_MSGID, CFE_SB_INVALID_PIPE), CFE_SB_BAD_ARGUMENT); + + /* Unsubscribe - Nominal */ + UtAssert_INT32_EQ(CFE_SB_Unsubscribe(CFE_FT_CMD_MSGID, PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_Unsubscribe(CFE_FT_TLM_MSGID, PipeId2), CFE_SUCCESS); + + /* Unsubscribe - Already unsubscribed */ + UtAssert_INT32_EQ(CFE_SB_Unsubscribe(CFE_FT_CMD_MSGID, PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_Unsubscribe(CFE_FT_TLM_MSGID, PipeId2), CFE_SUCCESS); + + /* Unsubscribe - Nominal 2 */ + UtAssert_INT32_EQ(CFE_SB_Unsubscribe(CFE_FT_TLM_MSGID, PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_Unsubscribe(CFE_FT_CMD_MSGID, PipeId2), CFE_SUCCESS); + + /* Teardown - delete the pipes. */ + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId2), CFE_SUCCESS); +} + +void TestSubscribeUnsubscribeLocal(void) +{ + CFE_SB_PipeId_t PipeId1; + CFE_SB_PipeId_t PipeId2; + + UtPrintf("Testing: CFE_SB_SubscribeLocal, CFE_SB_UnsubscribeLocal"); + + /* Setup, create some pipes */ + UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId1, 3, "TestPipe1"), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId2, 3, "TestPipe2"), CFE_SUCCESS); + + /* Subscribe - Confirm Bad MsgId Arg Rejection */ + UtAssert_INT32_EQ(CFE_SB_SubscribeLocal(CFE_SB_INVALID_MSG_ID, PipeId1, 2), CFE_SB_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_SB_SubscribeLocal(CFE_SB_MSGID_RESERVED, PipeId2, 2), CFE_SB_BAD_ARGUMENT); + + /* Subscribe - Confirm Bad PipeId Arg Rejection */ + UtAssert_INT32_EQ(CFE_SB_SubscribeLocal(CFE_FT_CMD_MSGID, CFE_SB_INVALID_PIPE, 2), CFE_SB_BAD_ARGUMENT); + + /* Subscribe - Nominal */ + UtAssert_INT32_EQ(CFE_SB_SubscribeLocal(CFE_FT_CMD_MSGID, PipeId1, 2), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_SubscribeLocal(CFE_FT_TLM_MSGID, PipeId2, 2), CFE_SUCCESS); + + /* Subscribe - Duplicate */ + UtAssert_INT32_EQ(CFE_SB_SubscribeLocal(CFE_FT_CMD_MSGID, PipeId1, 2), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_SubscribeLocal(CFE_FT_TLM_MSGID, PipeId2, 2), CFE_SUCCESS); + + /* Subscribe - Nominal 2 */ + UtAssert_INT32_EQ(CFE_SB_SubscribeLocal(CFE_FT_TLM_MSGID, PipeId1, 2), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_SubscribeLocal(CFE_FT_CMD_MSGID, PipeId2, 2), CFE_SUCCESS); + + /* Unsubscribe - Confirm Bad MsgId Arg Rejection */ + UtAssert_INT32_EQ(CFE_SB_UnsubscribeLocal(CFE_SB_INVALID_MSG_ID, PipeId1), CFE_SB_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_SB_UnsubscribeLocal(CFE_SB_MSGID_RESERVED, PipeId2), CFE_SB_BAD_ARGUMENT); + + /* Unsubscribe - Confirm Bad PipeId Arg Rejection */ + UtAssert_INT32_EQ(CFE_SB_UnsubscribeLocal(CFE_FT_CMD_MSGID, CFE_SB_INVALID_PIPE), CFE_SB_BAD_ARGUMENT); + + /* Unsubscribe - Nominal */ + UtAssert_INT32_EQ(CFE_SB_UnsubscribeLocal(CFE_FT_CMD_MSGID, PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_UnsubscribeLocal(CFE_FT_TLM_MSGID, PipeId2), CFE_SUCCESS); + + /* Unsubscribe - Already unsubscribed */ + UtAssert_INT32_EQ(CFE_SB_UnsubscribeLocal(CFE_FT_CMD_MSGID, PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_UnsubscribeLocal(CFE_FT_TLM_MSGID, PipeId2), CFE_SUCCESS); + + /* Unsubscribe - Nominal 2 */ + UtAssert_INT32_EQ(CFE_SB_UnsubscribeLocal(CFE_FT_TLM_MSGID, PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_UnsubscribeLocal(CFE_FT_CMD_MSGID, PipeId2), CFE_SUCCESS); + + /* Teardown - delete the pipes. */ + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId2), CFE_SUCCESS); +} + +void TestSubscribeEx(void) +{ + CFE_SB_PipeId_t PipeId1; + CFE_SB_PipeId_t PipeId2; + + /* + * NOTE: CFE_SB_SubscribeEx adds a "Quality" parameter for Qos, which is + * not utilized in the current SB implementation (only "default" is available). + * + * Otherwise, it is basically the same as the regular "CFE_SB_Subscribe" call. + */ + UtPrintf("Testing: CFE_SB_SubscribeEx"); + + /* Setup, create some pipes */ + UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId1, 3, "TestPipe1"), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId2, 3, "TestPipe2"), CFE_SUCCESS); + + /* + * For completeness, repeat the bad arg rejection tests, even though internally + * it is likely identical (all going through CFE_SB_SubscribeFull). However + * this implementation detail should not be assumed in a black box test environment. + */ + + /* Subscribe - Confirm Bad MsgId Arg Rejection */ + UtAssert_INT32_EQ(CFE_SB_SubscribeEx(CFE_SB_INVALID_MSG_ID, PipeId1, CFE_SB_DEFAULT_QOS, 2), CFE_SB_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_SB_SubscribeEx(CFE_SB_MSGID_RESERVED, PipeId2, CFE_SB_DEFAULT_QOS, 2), CFE_SB_BAD_ARGUMENT); + + /* Subscribe - Confirm Bad PipeId Arg Rejection */ + UtAssert_INT32_EQ(CFE_SB_SubscribeEx(CFE_FT_CMD_MSGID, CFE_SB_INVALID_PIPE, CFE_SB_DEFAULT_QOS, 2), + CFE_SB_BAD_ARGUMENT); + + /* Subscribe - Nominal */ + UtAssert_INT32_EQ(CFE_SB_SubscribeEx(CFE_FT_CMD_MSGID, PipeId1, CFE_SB_DEFAULT_QOS, 2), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_SubscribeEx(CFE_FT_TLM_MSGID, PipeId2, CFE_SB_DEFAULT_QOS, 2), CFE_SUCCESS); + + /* Teardown - delete the pipes (this also unsubscribes automatically) */ + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId2), CFE_SUCCESS); +} + +void TestSBMaxSubscriptions(void) +{ + CFE_Status_t Status; + uint32 NumSubs; + CFE_SB_MsgId_t TestMsgId; + CFE_SB_PipeId_t PipeId; + + UtPrintf("Testing: CFE_SB_Subscribe, max routing table limit"); + + /* Setup, create a pipe */ + UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId, 2, "TestPipe"), CFE_SUCCESS); + + /* + * Test max subscriptions - note this depends on the actual number of _other_ apps + * that are running and have made other subscriptions. Therefore it is not predictable + * exactly how many iterations of this loop will succeed, but it should be fewer than + * CFE_PLATFORM_SB_MAX_MSG_IDS. + * + * NOTE: after this loop, it may not be possible to add any more routes at all, until + * a processor reset is done, because routes are never actually deleted for sequence number persistence. + */ + NumSubs = 0; + while (NumSubs <= CFE_PLATFORM_SB_MAX_MSG_IDS) + { + /* fabricate a msgid to subscribe to (this may overlap real msgids) */ + TestMsgId = CFE_SB_MSGID_WRAP_VALUE(CFE_PLATFORM_CMD_MID_BASE + NumSubs); + + Status = CFE_SB_Subscribe(TestMsgId, PipeId); + if (Status != CFE_SUCCESS) + { + break; + } + + ++NumSubs; + } + + /* Check that the number of subscriptions was within range */ + UtAssert_NONZERO(NumSubs); + UtAssert_UINT32_LTEQ(NumSubs, CFE_PLATFORM_SB_MAX_MSG_IDS); + + /* The last pass should have returned CFE_SB_MAX_MSGS_MET */ + UtAssert_True(Status == CFE_SB_MAX_MSGS_MET, + "CFE_SB_Subscribe(TestMsgId, PipeId1) (%ld) == CFE_SB_MAX_MSGS_MET (%ld)", (long)Status, + (long)CFE_SB_MAX_MSGS_MET); + + /* Note this should also remove any subscriptions from the above loop */ + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId), CFE_SUCCESS); +} + +void SBSubscriptionTestSetup(void) +{ + UtTest_Add(TestSubscribeUnsubscribe, NULL, NULL, "Test SB Subscribe/Unsubscribe"); + UtTest_Add(TestSubscribeUnsubscribeLocal, NULL, NULL, "Test SB SubscribeLocal/UnsubscribeLocal"); + UtTest_Add(TestSubscribeEx, NULL, NULL, "Test SB SubscribeEx"); + + /* + * NOTE: The TestSBMaxSubscriptions() is not included/added by default, as it will fill the + * routing table and make it not possible to add new routes until the system is reset. + * + * The test can be optionally enabled by the user and should pass, if this is not a concern. + */ +}