diff --git a/README.md b/README.md index b38adf224..ca8fc797a 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,33 @@ The detailed cFE user's guide can be viewed at and + ### Development Build: v6.8.0-rc1+dev933 - Add software bus tests diff --git a/cmake/arch_build.cmake b/cmake/arch_build.cmake index e51547e1c..72e934e1b 100644 --- a/cmake/arch_build.cmake +++ b/cmake/arch_build.cmake @@ -585,7 +585,7 @@ function(process_arch SYSVAR) set(CFE_PSP_EXPECTED_OSAL_BSPTYPE ${CFE_SYSTEM_PSPNAME}) # Include any specific compiler flags or config from the selected PSP - include(${MISSION_SOURCE_DIR}/psp/fsw/${CFE_SYSTEM_PSPNAME}/make/build_options.cmake) + include(${psp_MISSION_DIR}/fsw/${CFE_SYSTEM_PSPNAME}/make/build_options.cmake) if (NOT DEFINED OSAL_SYSTEM_BSPTYPE) # Implicitly use the OSAL BSP that corresponds with the CFE PSP diff --git a/cmake/sample_defs/targets.cmake b/cmake/sample_defs/targets.cmake index 6301a0984..3f11bf4eb 100644 --- a/cmake/sample_defs/targets.cmake +++ b/cmake/sample_defs/targets.cmake @@ -82,7 +82,7 @@ SET(SPACECRAFT_ID 0x42) #list(APPEND MISSION_CORE_MODULES mymodule) # The "MISSION_GLOBAL_APPLIST" is a set of apps/libs that will be built -# for every defined and target. These are built as dynamic modules +# for every defined target. These are built as dynamic modules # and must be loaded explicitly via startup script or command. # This list is effectively appended to every TGTx_APPLIST in targets.cmake. # Example: diff --git a/docs/cFE Application Developers Guide.md b/docs/cFE Application Developers Guide.md index 324a2189e..565284f5d 100644 --- a/docs/cFE Application Developers Guide.md +++ b/docs/cFE Application Developers Guide.md @@ -179,10 +179,9 @@ software interface. ## 1.3 Applicable Documents -| **Location** | **Documents** | **Description** | -|:---------------------------------------------|:----------------------|:-------------------| -| https://github.com/nasa/osal/tree/master/doc | OSAL Library API.doc | Describes OSAL API | -| TBD | PSP API (TBD) | Describes PSP API | +Autogenerated documentation can be found at the cFS gh-pages branch, https://github.com/nasa/cFS/tree/gh-pages. + +Other documentation can be found in the associated repository's docs directory. ## 1.4 Acronyms diff --git a/modules/cfe_testcase/src/cfe_test.h b/modules/cfe_testcase/src/cfe_test.h index f011eab3b..e156a8c1d 100644 --- a/modules/cfe_testcase/src/cfe_test.h +++ b/modules/cfe_testcase/src/cfe_test.h @@ -50,7 +50,7 @@ typedef struct CFE_FS_FileWriteMetaData_t FuncTestState; /* Generic utility counter */ - int Count; + int32 Count; /* Table information used by all table tests */ CFE_TBL_Handle_t TblHandle; diff --git a/modules/cfe_testcase/src/es_counter_test.c b/modules/cfe_testcase/src/es_counter_test.c index 544d0fa4d..8dbda779d 100644 --- a/modules/cfe_testcase/src/es_counter_test.c +++ b/modules/cfe_testcase/src/es_counter_test.c @@ -30,7 +30,7 @@ void TestCounterCreateDelete(void) { - CFE_ES_CounterId_t Ids[CFE_PLATFORM_ES_MAX_GEN_COUNTERS]; + CFE_ES_CounterId_t Ids[CFE_PLATFORM_ES_MAX_GEN_COUNTERS + 1]; CFE_ES_CounterId_t TestId; CFE_ES_CounterId_t CheckId; char CounterName[CFE_MISSION_MAX_API_LEN]; @@ -48,22 +48,26 @@ void TestCounterCreateDelete(void) UtAssert_INT32_EQ(CFE_ES_RegisterGenCounter(NULL, CounterName), CFE_ES_BAD_ARGUMENT); /* Create up to CFE_PLATFORM_ES_MAX_GEN_COUNTERS and confirm success */ - for (NumCounters = 0; NumCounters < CFE_PLATFORM_ES_MAX_GEN_COUNTERS; ++NumCounters) + /* Note that this loop may execute fewer than CFE_PLATFORM_ES_MAX_GEN_COUNTERS times, + * if another unrelated app has already registered a counter. Because this test + * cannot control for those pre-conditions, anything within range is acceptable */ + for (NumCounters = 0; NumCounters <= CFE_PLATFORM_ES_MAX_GEN_COUNTERS; ++NumCounters) { snprintf(CounterName, sizeof(CounterName), "C%u", (unsigned int)NumCounters); - Status = CFE_ES_RegisterGenCounter(&Ids[NumCounters], CounterName); - if (Status != CFE_SUCCESS) + CFE_Assert_STATUS_STORE(CFE_ES_RegisterGenCounter(&Ids[NumCounters], CounterName)); + + /* When the max limit is reached, should return CFE_ES_NO_RESOURCE_IDS_AVAILABLE */ + if (CFE_Assert_STATUS_MAY_BE(CFE_ES_NO_RESOURCE_IDS_AVAILABLE)) { break; } + + /* If max limit not reached, should return CFE_SUCCESS, anything else is a test fail */ + CFE_Assert_STATUS_MAY_BE(CFE_SUCCESS); } /* Confirm that the expected number of counters were created */ - UtAssert_UINT32_EQ(NumCounters, CFE_PLATFORM_ES_MAX_GEN_COUNTERS); - - /* Attempt to create one too many */ - snprintf(CounterName, sizeof(CounterName), "extra"); - UtAssert_INT32_EQ(CFE_ES_RegisterGenCounter(&TestId, CounterName), CFE_ES_NO_RESOURCE_IDS_AVAILABLE); + UtAssert_UINT32_LTEQ(NumCounters, CFE_PLATFORM_ES_MAX_GEN_COUNTERS); /* pick a single counter ID from the middle of the set for more detail testing of support APIs */ TestId = Ids[NumCounters / 2]; diff --git a/modules/cfe_testcase/src/es_info_test.c b/modules/cfe_testcase/src/es_info_test.c index 4bbedd85e..3f3cd635d 100644 --- a/modules/cfe_testcase/src/es_info_test.c +++ b/modules/cfe_testcase/src/es_info_test.c @@ -125,11 +125,12 @@ void TestAppInfo(void) CFE_UtAssert_RESOURCEID_UNDEFINED(AppIdByName); UtAssert_INT32_EQ(CFE_ES_GetAppID(NULL), CFE_ES_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_ES_GetAppIDByName(NULL, TEST_EXPECTED_APP_NAME), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_GetAppIDByName(&AppIdByName, NULL), CFE_ES_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_ES_GetAppName(AppNameBuf, CFE_ES_APPID_UNDEFINED, sizeof(AppNameBuf)), CFE_ES_ERR_RESOURCEID_NOT_VALID); UtAssert_INT32_EQ(CFE_ES_GetAppName(NULL, TestAppId, sizeof(AppNameBuf)), CFE_ES_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_ES_GetAppInfo(&TestAppInfo, CFE_ES_APPID_UNDEFINED), CFE_ES_ERR_RESOURCEID_NOT_VALID); - UtAssert_INT32_EQ(CFE_ES_GetAppInfo(NULL, CFE_ES_APPID_UNDEFINED), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_GetAppInfo(NULL, TestAppId), CFE_ES_BAD_ARGUMENT); } void TestTaskInfo(void) @@ -158,13 +159,14 @@ void TestTaskInfo(void) UtAssert_INT32_EQ(TaskInfo.ExecutionCounter, AppInfo.ExecutionCounter); UtAssert_INT32_EQ(CFE_ES_GetTaskInfo(&TaskInfo, CFE_ES_TASKID_UNDEFINED), CFE_ES_ERR_RESOURCEID_NOT_VALID); - UtAssert_INT32_EQ(CFE_ES_GetTaskInfo(NULL, CFE_ES_TASKID_UNDEFINED), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_GetTaskInfo(NULL, TaskId), CFE_ES_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_ES_GetTaskID(NULL), CFE_ES_BAD_ARGUMENT); } void TestLibInfo(void) { - CFE_ES_LibId_t LibIdByName; + CFE_ES_LibId_t LibId; + CFE_ES_LibId_t CheckId; CFE_ES_AppInfo_t LibInfo; const char * LibName = "ASSERT_LIB"; const char * InvalidName = "INVALID_NAME"; @@ -172,9 +174,9 @@ void TestLibInfo(void) UtPrintf("Testing: CFE_ES_GetLibIDByName, CFE_ES_GetLibName, CFE_ES_GetLibInfo"); - UtAssert_INT32_EQ(CFE_ES_GetLibIDByName(&LibIdByName, LibName), CFE_SUCCESS); - UtAssert_INT32_EQ(CFE_ES_GetLibInfo(&LibInfo, LibIdByName), CFE_SUCCESS); - UtAssert_INT32_EQ(CFE_ES_GetLibName(LibNameBuf, LibIdByName, sizeof(LibNameBuf)), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_ES_GetLibIDByName(&LibId, LibName), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_ES_GetLibInfo(&LibInfo, LibId), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_ES_GetLibName(LibNameBuf, LibId, sizeof(LibNameBuf)), CFE_SUCCESS); UtAssert_StrCmp(LibNameBuf, LibName, "CFE_ES_GetLibName() = %s", LibNameBuf); UtAssert_True(LibInfo.Type == CFE_ES_AppType_LIBRARY, "Lib Info -> Type = %d", (int)LibInfo.Type); UtAssert_StrCmp(LibInfo.Name, LibName, "Lib Info -> Name = %s", LibInfo.Name); @@ -210,13 +212,17 @@ void TestLibInfo(void) UtAssert_True(strlen(LibInfo.MainTaskName) == 0, "Lib Info -> Task Name = %s", LibInfo.MainTaskName); UtAssert_True(LibInfo.NumOfChildTasks == 0, "Lib Info -> Child Tasks = %d", (int)LibInfo.NumOfChildTasks); - UtAssert_INT32_EQ(CFE_ES_GetLibIDByName(&LibIdByName, InvalidName), CFE_ES_ERR_NAME_NOT_FOUND); - UtAssert_INT32_EQ(CFE_ES_GetLibInfo(&LibInfo, LibIdByName), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_ES_GetLibIDByName(&CheckId, InvalidName), CFE_ES_ERR_NAME_NOT_FOUND); + CFE_UtAssert_RESOURCEID_UNDEFINED(CheckId); + UtAssert_INT32_EQ(CFE_ES_GetLibInfo(&LibInfo, CFE_ES_LIBID_UNDEFINED), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_ES_GetLibInfo(NULL, LibId), CFE_ES_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_ES_GetLibIDByName(NULL, LibName), CFE_ES_BAD_ARGUMENT); - UtAssert_INT32_EQ(CFE_ES_GetLibInfo(NULL, LibIdByName), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_GetLibIDByName(&CheckId, NULL), CFE_ES_BAD_ARGUMENT); + CFE_UtAssert_RESOURCEID_UNDEFINED(CheckId); UtAssert_INT32_EQ(CFE_ES_GetLibName(LibNameBuf, CFE_ES_LIBID_UNDEFINED, sizeof(LibNameBuf)), CFE_ES_ERR_RESOURCEID_NOT_VALID); - UtAssert_INT32_EQ(CFE_ES_GetLibName(NULL, LibIdByName, sizeof(LibNameBuf)), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_GetLibName(LibNameBuf, LibId, 0), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_GetLibName(NULL, LibId, sizeof(LibNameBuf)), CFE_ES_BAD_ARGUMENT); } void TestResetType(void) diff --git a/modules/cfe_testcase/src/es_mempool_test.c b/modules/cfe_testcase/src/es_mempool_test.c index 32fe359b6..a3f97354e 100644 --- a/modules/cfe_testcase/src/es_mempool_test.c +++ b/modules/cfe_testcase/src/es_mempool_test.c @@ -33,52 +33,96 @@ #include "cfe_test.h" +typedef struct +{ + uint32 Mem[128]; +} CFE_FT_PoolMemBlock_t; + +static CFE_FT_PoolMemBlock_t CFE_FT_PoolMemBlock[CFE_PLATFORM_ES_MAX_MEMORY_POOLS + 1]; + void TestMemPoolCreate(void) { CFE_ES_MemHandle_t PoolID; - int8 Pool[1024]; UtPrintf("Testing: CFE_ES_PoolCreateNoSem, CFE_ES_PoolCreate, CFE_ES_PoolCreateEx"); - UtAssert_INT32_EQ(CFE_ES_PoolCreateNoSem(&PoolID, Pool, sizeof(Pool)), CFE_SUCCESS); - UtAssert_INT32_EQ(CFE_ES_PoolCreateNoSem(NULL, Pool, sizeof(Pool)), CFE_ES_BAD_ARGUMENT); - UtAssert_INT32_EQ(CFE_ES_PoolCreateNoSem(&PoolID, NULL, sizeof(Pool)), CFE_ES_BAD_ARGUMENT); - UtAssert_INT32_EQ(CFE_ES_PoolCreateNoSem(&PoolID, Pool, 0), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_PoolCreateNoSem(&PoolID, CFE_FT_PoolMemBlock, sizeof(CFE_FT_PoolMemBlock)), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_ES_PoolCreateNoSem(NULL, CFE_FT_PoolMemBlock, sizeof(CFE_FT_PoolMemBlock)), + CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_PoolCreateNoSem(&PoolID, NULL, sizeof(CFE_FT_PoolMemBlock)), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_PoolCreateNoSem(&PoolID, CFE_FT_PoolMemBlock, 0), CFE_ES_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_ES_PoolDelete(PoolID), CFE_SUCCESS); - UtAssert_INT32_EQ(CFE_ES_PoolCreate(&PoolID, Pool, sizeof(Pool)), CFE_SUCCESS); - UtAssert_INT32_EQ(CFE_ES_PoolCreate(NULL, Pool, sizeof(Pool)), CFE_ES_BAD_ARGUMENT); - UtAssert_INT32_EQ(CFE_ES_PoolCreate(&PoolID, NULL, sizeof(Pool)), CFE_ES_BAD_ARGUMENT); - UtAssert_INT32_EQ(CFE_ES_PoolCreate(&PoolID, Pool, 0), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_PoolCreate(&PoolID, CFE_FT_PoolMemBlock, sizeof(CFE_FT_PoolMemBlock)), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_ES_PoolCreate(NULL, CFE_FT_PoolMemBlock, sizeof(CFE_FT_PoolMemBlock)), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_PoolCreate(&PoolID, NULL, sizeof(CFE_FT_PoolMemBlock)), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_PoolCreate(&PoolID, CFE_FT_PoolMemBlock, 0), CFE_ES_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_ES_PoolDelete(PoolID), CFE_SUCCESS); - UtAssert_INT32_EQ(CFE_ES_PoolCreateEx(&PoolID, Pool, sizeof(Pool), 0, NULL, CFE_ES_NO_MUTEX), CFE_SUCCESS); - UtAssert_INT32_EQ(CFE_ES_PoolCreateEx(NULL, Pool, sizeof(Pool), 0, NULL, CFE_ES_NO_MUTEX), CFE_ES_BAD_ARGUMENT); - UtAssert_INT32_EQ(CFE_ES_PoolCreateEx(&PoolID, NULL, sizeof(Pool), 0, NULL, CFE_ES_NO_MUTEX), CFE_ES_BAD_ARGUMENT); - UtAssert_INT32_EQ(CFE_ES_PoolCreateEx(&PoolID, Pool, 0, 0, NULL, CFE_ES_NO_MUTEX), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ( + CFE_ES_PoolCreateEx(&PoolID, CFE_FT_PoolMemBlock, sizeof(CFE_FT_PoolMemBlock), 0, NULL, CFE_ES_NO_MUTEX), + CFE_SUCCESS); + UtAssert_INT32_EQ( + CFE_ES_PoolCreateEx(NULL, CFE_FT_PoolMemBlock, sizeof(CFE_FT_PoolMemBlock), 0, NULL, CFE_ES_NO_MUTEX), + CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_PoolCreateEx(&PoolID, NULL, sizeof(CFE_FT_PoolMemBlock), 0, NULL, CFE_ES_NO_MUTEX), + CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_PoolCreateEx(&PoolID, CFE_FT_PoolMemBlock, 0, 0, NULL, CFE_ES_NO_MUTEX), + CFE_ES_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_ES_PoolDelete(PoolID), CFE_SUCCESS); } +void TestMemPoolCreateMax(void) +{ + CFE_ES_MemHandle_t PoolID[CFE_PLATFORM_ES_MAX_MEMORY_POOLS + 1]; + uint32 NumPools; + + UtPrintf("Testing: CFE_ES_PoolCreate Max Limit"); + + NumPools = 0; + while (NumPools <= CFE_PLATFORM_ES_MAX_MEMORY_POOLS) + { + CFE_Assert_STATUS_STORE(CFE_ES_PoolCreateEx(&PoolID[NumPools], &CFE_FT_PoolMemBlock[NumPools], + sizeof(CFE_FT_PoolMemBlock_t), 0, NULL, CFE_ES_NO_MUTEX)); + if (CFE_Assert_STATUS_MAY_BE(CFE_ES_NO_RESOURCE_IDS_AVAILABLE)) + { + /* limit reached */ + break; + } + CFE_Assert_STATUS_MUST_BE(CFE_SUCCESS); + ++NumPools; + } + + UtAssert_UINT32_LTEQ(NumPools, CFE_PLATFORM_ES_MAX_MEMORY_POOLS); + + /* Clean up */ + while (NumPools > 0) + { + --NumPools; + UtAssert_INT32_EQ(CFE_ES_PoolDelete(PoolID[NumPools]), CFE_SUCCESS); + } +} + void TestMemPoolGetBuf(void) { CFE_ES_MemHandle_t PoolID; int8 Pool[1024]; - size_t Buffer = 512; - size_t BufferBig = 2048; - CFE_ES_MemPoolBuf_t addressp = CFE_ES_MEMPOOLBUF_C(0); + size_t BufferSize = 512; + size_t BufferBig = 2048; + CFE_ES_MemPoolBuf_t addressp = CFE_ES_MEMPOOLBUF_C(0); UtPrintf("Testing: TestMemPoolGetBuf"); UtAssert_INT32_EQ(CFE_ES_PoolCreate(&PoolID, Pool, sizeof(Pool)), CFE_SUCCESS); - UtAssert_INT32_EQ(CFE_ES_GetPoolBuf(&addressp, PoolID, Buffer), Buffer); + UtAssert_INT32_EQ(CFE_ES_GetPoolBuf(&addressp, PoolID, BufferSize), BufferSize); - UtAssert_INT32_EQ(CFE_ES_GetPoolBuf(NULL, PoolID, Buffer), CFE_ES_BAD_ARGUMENT); - UtAssert_INT32_EQ(CFE_ES_GetPoolBuf(&addressp, CFE_ES_MEMHANDLE_UNDEFINED, Buffer), + UtAssert_INT32_EQ(CFE_ES_GetPoolBuf(NULL, PoolID, BufferSize), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_GetPoolBuf(&addressp, CFE_ES_MEMHANDLE_UNDEFINED, BufferSize), CFE_ES_ERR_RESOURCEID_NOT_VALID); - UtAssert_INT32_EQ(CFE_ES_GetPoolBuf(&addressp, PoolID, Buffer), CFE_ES_ERR_MEM_BLOCK_SIZE); - UtAssert_INT32_EQ(CFE_ES_PutPoolBuf(PoolID, addressp), Buffer); + UtAssert_INT32_EQ(CFE_ES_GetPoolBuf(&addressp, PoolID, BufferSize), CFE_ES_ERR_MEM_BLOCK_SIZE); + UtAssert_INT32_EQ(CFE_ES_PutPoolBuf(PoolID, addressp), BufferSize); UtAssert_INT32_EQ(CFE_ES_GetPoolBuf(&addressp, PoolID, BufferBig), CFE_ES_ERR_MEM_BLOCK_SIZE); @@ -104,6 +148,9 @@ void TestMemPoolBufInfo(void) UtAssert_INT32_EQ(CFE_ES_GetPoolBufInfo(CFE_ES_MEMHANDLE_UNDEFINED, addressp), CFE_ES_ERR_RESOURCEID_NOT_VALID); UtAssert_INT32_EQ(CFE_ES_GetPoolBufInfo(PoolID, NULL), CFE_ES_BAD_ARGUMENT); + /* Pass an address from some other memory which is not part of the pool */ + UtAssert_INT32_EQ(CFE_ES_GetPoolBufInfo(PoolID, &Buffer), CFE_ES_BUFFER_NOT_IN_POOL); + UtAssert_INT32_EQ(CFE_ES_PoolDelete(PoolID), CFE_SUCCESS); } @@ -145,13 +192,19 @@ void TestMemPoolDelete(void) UtAssert_UINT32_EQ(Stats.CheckErrCtr, 0); UtAssert_UINT32_EQ(Stats.NumFreeBytes, sizeof(Buffer)); + UtAssert_INT32_EQ(CFE_ES_GetMemPoolStats(NULL, PoolID), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_GetMemPoolStats(&Stats, CFE_ES_MEMHANDLE_UNDEFINED), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_ES_PoolDelete(PoolID), CFE_SUCCESS); UtAssert_INT32_EQ(CFE_ES_GetMemPoolStats(&Stats, PoolID), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_ES_PoolDelete(PoolID), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_ES_PoolDelete(CFE_ES_MEMHANDLE_UNDEFINED), CFE_ES_ERR_RESOURCEID_NOT_VALID); } void ESMemPoolTestSetup(void) { UtTest_Add(TestMemPoolCreate, NULL, NULL, "Test Mem Pool Create"); + UtTest_Add(TestMemPoolCreateMax, NULL, NULL, "Test Mem Pool Create Maximum"); UtTest_Add(TestMemPoolGetBuf, NULL, NULL, "Test Mem Pool Get Buf"); UtTest_Add(TestMemPoolBufInfo, NULL, NULL, "Test Mem Pool Buf Info"); UtTest_Add(TestMemPoolPutBuf, NULL, NULL, "Test Mem Pool Put Buf"); diff --git a/modules/cfe_testcase/src/es_misc_test.c b/modules/cfe_testcase/src/es_misc_test.c index 6545efa29..ec71d5bc6 100644 --- a/modules/cfe_testcase/src/es_misc_test.c +++ b/modules/cfe_testcase/src/es_misc_test.c @@ -58,11 +58,33 @@ void TestCalculateCRC(void) void TestWriteToSysLog(void) { const char *TestString = "Test String for CFE_ES_WriteToSysLog Functional Test"; + uint32 Iterations = CFE_PLATFORM_ES_SYSTEM_LOG_SIZE / 50; UtPrintf("Testing: CFE_ES_WriteToSysLog"); - CFE_ES_WriteToSysLog("MIR (Manual Inspection Required) for CFE_ES_WriteToSysLog"); - CFE_ES_WriteToSysLog(NULL); - CFE_ES_WriteToSysLog("%s", TestString); + + UtAssert_INT32_EQ(CFE_ES_WriteToSysLog(NULL), CFE_ES_BAD_ARGUMENT); + + CFE_Assert_STATUS_STORE(CFE_ES_WriteToSysLog("MIR (Manual Inspection Required) for CFE_ES_WriteToSysLog")); + if (!CFE_Assert_STATUS_MAY_BE(CFE_ES_ERR_SYS_LOG_FULL)) + { + CFE_Assert_STATUS_MUST_BE(CFE_SUCCESS); + } + + /* The test string is a little over 50 chars in length, so writing it repeatedly should fill it up. */ + /* This does depend on whether the system is set to OVERWRITE or DISCARD mode, though - + * in OVERWRITE mode, the system log will never fill, and therefore CFE_ES_ERR_SYS_LOG_FULL cannot be tested */ + Iterations = 1 + (CFE_PLATFORM_ES_SYSTEM_LOG_SIZE / strlen(TestString)); + + while (Iterations > 0) + { + --Iterations; + CFE_Assert_STATUS_STORE(CFE_ES_WriteToSysLog("%s", TestString)); + if (CFE_Assert_STATUS_MAY_BE(CFE_ES_ERR_SYS_LOG_FULL)) + { + break; + } + CFE_Assert_STATUS_MUST_BE(CFE_SUCCESS); + } UtAssert_MIR("MIR (Manual Inspection Required) for CFE_ES_WriteToSysLog"); } diff --git a/modules/cfe_testcase/src/es_task_test.c b/modules/cfe_testcase/src/es_task_test.c index bd9f64bf4..063e67a6c 100644 --- a/modules/cfe_testcase/src/es_task_test.c +++ b/modules/cfe_testcase/src/es_task_test.c @@ -43,6 +43,49 @@ void TaskFunction(void) return; } +/* A task function that verifies the behavior of other APIs when those are called from a child task */ +void TaskFunctionCheckChildTaskContext(void) +{ + CFE_ES_TaskId_t TaskId; + CFE_ES_AppId_t AppId; + CFE_ES_AppInfo_t AppInfo; + + /* extra startup delay before first assert, to make sure parent task has reached its wait loop */ + OS_TaskDelay(100); + + /* If invoked from the context of a child task, this should return an error */ + UtAssert_INT32_EQ(CFE_ES_CreateChildTask(&TaskId, "Test", TaskFunction, OSAL_TASK_STACK_ALLOCATE, 4096, 150, 0), + CFE_ES_ERR_CHILD_TASK_CREATE); + + /* Likewise attempting to delete the main task of the app from a child task should fail */ + UtAssert_INT32_EQ(CFE_ES_GetAppID(&AppId), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_ES_GetAppInfo(&AppInfo, AppId), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_ES_DeleteChildTask(AppInfo.MainTaskId), CFE_ES_ERR_CHILD_TASK_DELETE_MAIN_TASK); + + UtAssert_True(true, "CFE_ES_ExitChildTask() called"); + CFE_ES_ExitChildTask(); +} + +/* A task function that verifies the behavior of other APIs when those are called from a non-CFE app task */ +void TaskFunctionCheckNonAppContext(void) +{ + CFE_ES_TaskId_t TaskId; + CFE_ES_AppId_t AppId; + + /* extra startup delay before first assert, to make sure parent task has reached its wait loop */ + OS_TaskDelay(100); + + UtAssert_INT32_EQ(CFE_ES_GetAppID(&AppId), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_ES_GetTaskID(&TaskId), CFE_ES_ERR_RESOURCEID_NOT_VALID); + + UtAssert_INT32_EQ( + CFE_ES_CreateChildTask(&TaskId, "TaskName", TaskFunction, CFE_ES_TASK_STACK_ALLOCATE, 4096, 200, 0), + CFE_ES_ERR_RESOURCEID_NOT_VALID); + + UtAssert_True(true, "OS_TaskExit() called"); + OS_TaskExit(); +} + void TaskExitFunction(void) { while (CFE_FT_Global.Count < 200) @@ -64,22 +107,76 @@ void TestCreateChild(void) size_t StackSize = CFE_PLATFORM_ES_PERF_CHILD_STACK_SIZE; CFE_ES_TaskPriority_Atom_t Priority = CFE_PLATFORM_ES_PERF_CHILD_PRIORITY; uint32 Flags = 0; - int ExpectedCount = 5; + int32 ExpectedCount = 5; + int32 RetryCount; + char TaskNameBuf[16]; + osal_id_t OtherTaskId; + OS_task_prop_t task_prop; CFE_FT_Global.Count = 0; - UtAssert_INT32_EQ(CFE_ES_CreateChildTask(&TaskId, TaskName, TaskFunction, StackPointer, StackSize, Priority, Flags), CFE_SUCCESS); OS_TaskDelay(500); - UtAssert_True(ExpectedCount >= CFE_FT_Global.Count - 1 && ExpectedCount <= CFE_FT_Global.Count + 1, - "countCopy (%d) == count (%d)", (int)ExpectedCount, (int)CFE_FT_Global.Count); + UtAssert_INT32_GT(CFE_FT_Global.Count, ExpectedCount - 1); + UtAssert_INT32_LT(CFE_FT_Global.Count, ExpectedCount + 1); + /* Create task with same name - note the name conflict is detected by OSAL, not CFE here, and the error code is + * translated */ UtAssert_INT32_EQ( CFE_ES_CreateChildTask(&TaskId2, TaskName, TaskFunction, StackPointer, StackSize, Priority, Flags), CFE_STATUS_EXTERNAL_RESOURCE_FAIL); UtAssert_INT32_EQ(CFE_ES_DeleteChildTask(TaskId), CFE_SUCCESS); + /* Also Confirm behavior of child task create/delete when called from a child task */ + CFE_FT_Global.Count = 0; + UtAssert_INT32_EQ(CFE_ES_CreateChildTask(&TaskId, TaskName, TaskFunctionCheckChildTaskContext, StackPointer, + StackSize, Priority, Flags), + CFE_SUCCESS); + + /* wait for task to exit itself */ + RetryCount = 0; + while (RetryCount < 10) + { + /* + * poll until CFE_ES_GetTaskName() returns an error, then the task has exited + * + * NOTE: this intentionally does not Assert the status here, because the child task is + * also doing asserts at the time this loop is running. Once the child task finishes, + * it is OK to do asserts from this task again + */ + if (CFE_Assert_STATUS_STORE(CFE_ES_GetTaskName(TaskNameBuf, TaskId, sizeof(TaskNameBuf))) != CFE_SUCCESS) + { + break; + } + OS_TaskDelay(100); + ++RetryCount; + } + + /* Retroactively confirm that the previous call to CFE_ES_GetTaskName() returned RESOURCEID_NOT_VALID */ + CFE_Assert_STATUS_MUST_BE(CFE_ES_ERR_RESOURCEID_NOT_VALID); + + /* Now do the same but instead of a CFE child task, make an OSAL task that is not associated with a CFE app */ + UtAssert_INT32_EQ(OS_TaskCreate(&OtherTaskId, "NonCfe", TaskFunctionCheckNonAppContext, OSAL_TASK_STACK_ALLOCATE, + 4096, OSAL_PRIORITY_C(200), 0), + OS_SUCCESS); + + /* wait for task to exit itself */ + RetryCount = 0; + while (RetryCount < 10) + { + /* + * poll until OS_TaskGetInfo() returns an error, then the task has exited + */ + if (OS_TaskGetInfo(OtherTaskId, &task_prop) != OS_SUCCESS) + { + break; + } + + OS_TaskDelay(100); + ++RetryCount; + } + UtAssert_INT32_EQ(CFE_ES_CreateChildTask(NULL, TaskName, TaskFunction, StackPointer, StackSize, Priority, Flags), CFE_ES_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_ES_CreateChildTask(&TaskId, NULL, TaskFunction, StackPointer, StackSize, Priority, Flags), @@ -114,6 +211,7 @@ void TestChildTaskName(void) UtAssert_StrCmp(TaskNameBuf, TaskName, "CFE_ES_GetTaskName() = %s", TaskNameBuf); UtAssert_INT32_EQ(CFE_ES_GetTaskIDByName(NULL, TaskName), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ES_GetTaskIDByName(&TaskIdByName, NULL), CFE_ES_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_ES_GetTaskIDByName(&TaskIdByName, INVALID_TASK_NAME), CFE_ES_ERR_NAME_NOT_FOUND); CFE_UtAssert_RESOURCEID_UNDEFINED(TaskIdByName); @@ -175,6 +273,16 @@ void TestExitChild(void) CFE_SUCCESS); OS_TaskDelay(500); UtAssert_INT32_EQ(ExpectedCount, 1); + + /* + * Invoking CFE_ES_ExitChildTask() from the context of a main task should _not_ actually exit. + * as this is a void function there is no return code to check here. The fact that the test + * continues after this call is evidence that the test passed (i.e. it did not actually end the task). + */ + UtAssert_VOIDCALL(CFE_ES_ExitChildTask()); + + /* If this message is printed, then the test passed. If the test fails this will not be reached. */ + UtAssert_True(true, "CFE_ES_ExitChildTask() called from main task (ignored; main task did not exit)"); } void ESTaskTestSetup(void) diff --git a/modules/cfe_testcase/src/fs_util_test.c b/modules/cfe_testcase/src/fs_util_test.c index dbce2c893..e378fc862 100644 --- a/modules/cfe_testcase/src/fs_util_test.c +++ b/modules/cfe_testcase/src/fs_util_test.c @@ -90,21 +90,35 @@ void TestInputFile(void) CFE_FS_INVALID_PATH); UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutNameBuf, InNameBuf, sizeof(OutNameBuf), 0, NULL, Path, Ext), CFE_FS_INVALID_PATH); + + /* A short output buffer that is too small to fit the result */ + UtAssert_INT32_EQ(CFE_FS_ParseInputFileNameEx(OutNameBuf, InNameBuf, 8, sizeof(InNameBuf), Name, Path, Ext), + CFE_FS_FNAME_TOO_LONG); } void TestFileName(void) { - const char Path[] = "/func/FileName.test"; + char Path[OS_MAX_PATH_LEN + 4]; char Name[OS_MAX_FILE_NAME]; const char ExpectedName[] = "FileName.test"; UtPrintf("Testing: CFE_FS_ExtractFilenameFromPath"); + snprintf(Path, sizeof(Path), "/func/FileName.test"); UtAssert_INT32_EQ(CFE_FS_ExtractFilenameFromPath(Path, Name), CFE_SUCCESS); UtAssert_StrCmp(Name, ExpectedName, "Extract Filename: %s", Name); UtAssert_INT32_EQ(CFE_FS_ExtractFilenameFromPath(NULL, Name), CFE_FS_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_FS_ExtractFilenameFromPath(Path, NULL), CFE_FS_BAD_ARGUMENT); + + memset(Path, 'x', sizeof(Path) - 1); + Path[sizeof(Path) - 1] = 0; + Path[0] = '/'; + UtAssert_INT32_EQ(CFE_FS_ExtractFilenameFromPath(Path, Name), CFE_FS_FNAME_TOO_LONG); + + Path[0] = 'x'; + Path[OS_MAX_PATH_LEN - 1] = 0; + UtAssert_INT32_EQ(CFE_FS_ExtractFilenameFromPath(Path, Name), CFE_FS_INVALID_PATH); } /* FT helper stub compatible with background file write DataGetter */ @@ -119,32 +133,54 @@ bool FS_DataGetter(void *Meta, uint32 RecordNum, void **Buffer, size_t *BufSize) void FS_OnEvent(void *Meta, CFE_FS_FileWriteEvent_t Event, int32 Status, uint32 RecordNum, size_t BlockSize, size_t Position) { + OS_TaskDelay(100); } void TestFileDump(void) { + int32 count; + int32 MaxWait = 20; + memset(&CFE_FT_Global.FuncTestState, 0, sizeof(CFE_FT_Global.FuncTestState)); CFE_FT_Global.FuncTestState.FileSubType = 2; - CFE_FT_Global.FuncTestState.GetData = FS_DataGetter; - CFE_FT_Global.FuncTestState.OnEvent = FS_OnEvent; - strncpy(CFE_FT_Global.FuncTestState.FileName, "/ram/FT.bin", sizeof(CFE_FT_Global.FuncTestState.FileName)); strncpy(CFE_FT_Global.FuncTestState.Description, "FT", sizeof(CFE_FT_Global.FuncTestState.Description)); - int count = 0; - int MaxWait = 20; UtPrintf("Testing: CFE_FS_BackgroundFileDumpRequest, CFE_FS_BackgroundFileDumpIsPending"); UtAssert_INT32_EQ(CFE_FS_BackgroundFileDumpIsPending(&CFE_FT_Global.FuncTestState), false); + + /* With an empty "FileName" field, it should fail path validation */ + CFE_FT_Global.FuncTestState.GetData = FS_DataGetter; + CFE_FT_Global.FuncTestState.OnEvent = FS_OnEvent; + UtAssert_INT32_EQ(CFE_FS_BackgroundFileDumpRequest(&CFE_FT_Global.FuncTestState), CFE_FS_INVALID_PATH); + strncpy(CFE_FT_Global.FuncTestState.FileName, "/ram/FT.bin", sizeof(CFE_FT_Global.FuncTestState.FileName)); + + /* With an empty "GetData" field, it should fail validation */ + CFE_FT_Global.FuncTestState.GetData = NULL; + UtAssert_INT32_EQ(CFE_FS_BackgroundFileDumpRequest(&CFE_FT_Global.FuncTestState), CFE_FS_BAD_ARGUMENT); + CFE_FT_Global.FuncTestState.GetData = FS_DataGetter; + + /* With an empty "OnEvent" field, it should fail validation */ + CFE_FT_Global.FuncTestState.OnEvent = NULL; + UtAssert_INT32_EQ(CFE_FS_BackgroundFileDumpRequest(&CFE_FT_Global.FuncTestState), CFE_FS_BAD_ARGUMENT); + CFE_FT_Global.FuncTestState.OnEvent = FS_OnEvent; + + /* This should work */ UtAssert_INT32_EQ(CFE_FS_BackgroundFileDumpRequest(&CFE_FT_Global.FuncTestState), CFE_SUCCESS); + /* Duplicate request should get rejected */ + UtAssert_INT32_EQ(CFE_FS_BackgroundFileDumpRequest(&CFE_FT_Global.FuncTestState), + CFE_STATUS_REQUEST_ALREADY_PENDING); + /* Wait for background task to complete */ + count = 0; while (CFE_FS_BackgroundFileDumpIsPending(&CFE_FT_Global.FuncTestState) && count < MaxWait) { OS_TaskDelay(100); count++; } - UtAssert_True(count < MaxWait, "count (%i) < MaxWait (%i)", count, MaxWait); + UtAssert_INT32_LT(count, MaxWait); UtAssert_INT32_EQ(CFE_FS_BackgroundFileDumpRequest(NULL), CFE_FS_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_FS_BackgroundFileDumpIsPending(NULL), false); diff --git a/modules/cfe_testcase/src/sb_pipe_mang_test.c b/modules/cfe_testcase/src/sb_pipe_mang_test.c index da161d2dd..08be2171c 100644 --- a/modules/cfe_testcase/src/sb_pipe_mang_test.c +++ b/modules/cfe_testcase/src/sb_pipe_mang_test.c @@ -43,13 +43,63 @@ void TestPipeCreate(void) UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId1, PipeDepth, PipeName), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId1), CFE_SB_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_SB_DeletePipe(CFE_SB_INVALID_PIPE), CFE_SB_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_SB_CreatePipe(NULL, PipeDepth, PipeName), CFE_SB_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId1, OS_QUEUE_MAX_DEPTH + 5, PipeName), CFE_SB_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId1, 0, PipeName), CFE_SB_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId1, PipeDepth, NULL), CFE_SB_PIPE_CR_ERR); +} - UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId1), CFE_SUCCESS); - UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId1), CFE_SB_BAD_ARGUMENT); +void TestPipeCreateMax(void) +{ + CFE_SB_PipeId_t PipeId[CFE_PLATFORM_SB_MAX_PIPES + 1]; + char PipeName[12]; + uint32 NumPipes; + + UtPrintf("Testing: CFE_SB_CreatePipe, maximum pipe limit"); + + /* + * NOTE: because any other running apps (including core apps) will likely have + * created some pipes already, it is not known how many more pipes can be created + * at this point. So this cannot assert directly on the return code of + * CFE_SB_CreatePipe because we do not know which iteration will return error, + * but it will be less than CFE_PLATFORM_SB_MAX_PIPES. + */ + NumPipes = 0; + while (NumPipes <= CFE_PLATFORM_SB_MAX_PIPES) + { + snprintf(PipeName, sizeof(PipeName), "TestPipe%u", (unsigned int)NumPipes); + CFE_Assert_STATUS_STORE(CFE_SB_CreatePipe(&PipeId[NumPipes], 10, PipeName)); + /* + * Normally, this will return CFE_SUCCESS, until the max number of pipes is reached. + * Confirm that the last creation attempt returned CFE_SB_MAX_PIPES_MET + * + * NOTE: this also mimics the same format as UtAssert_INT32_EQ so that any post-procesing + * test log analysis tools will see this call as well. + */ + if (CFE_Assert_STATUS_MAY_BE(CFE_SB_MAX_PIPES_MET)) + { + break; + } + + /* If not CFE_SB_MAX_PIPES_MET, then the only acceptable response is SUCCESS */ + CFE_Assert_STATUS_MUST_BE(CFE_SUCCESS); + + ++NumPipes; + } + + /* should have gotten CFE_SB_MAX_PIPES_MET before CFE_PLATFORM_SB_MAX_PIPES reached */ + UtAssert_UINT32_LT(NumPipes, CFE_PLATFORM_SB_MAX_PIPES); + + /* Cleanup: delete all pipes created above */ + while (NumPipes > 0) + { + --NumPipes; + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId[NumPipes]), CFE_SUCCESS); + } } void TestPipeIndex(void) @@ -119,6 +169,7 @@ void TestPipeName(void) UtAssert_INT32_EQ(CFE_SB_GetPipeName(PipeNameBuf, sizeof(PipeNameBuf), CFE_SB_INVALID_PIPE), CFE_SB_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_SB_GetPipeIdByName(NULL, PipeName), CFE_SB_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_SB_GetPipeIdByName(&PipeIdBuff, NULL), CFE_SB_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_SB_GetPipeIdByName(&PipeIdBuff, InvalidPipeName), CFE_SB_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId), CFE_SUCCESS); @@ -127,6 +178,7 @@ void TestPipeName(void) void SBPipeMangSetup(void) { UtTest_Add(TestPipeCreate, NULL, NULL, "Test Pipe Create"); + UtTest_Add(TestPipeCreateMax, NULL, NULL, "Test Pipe Create Max Limit"); UtTest_Add(TestPipeIndex, NULL, NULL, "Test Pipe Index"); UtTest_Add(TestPipeOptions, NULL, NULL, "Test Pipe Options"); UtTest_Add(TestPipeName, NULL, NULL, "Test Pipe Name"); diff --git a/modules/cfe_testcase/src/sb_sendrecv_test.c b/modules/cfe_testcase/src/sb_sendrecv_test.c index 699a73123..2113c9f2d 100644 --- a/modules/cfe_testcase/src/sb_sendrecv_test.c +++ b/modules/cfe_testcase/src/sb_sendrecv_test.c @@ -34,6 +34,8 @@ #include "cfe_test.h" #include "cfe_msgids.h" +#define CFE_FT_STRINGBUF_SIZE 12 + /* A simple command message */ typedef struct { @@ -49,10 +51,13 @@ typedef struct } CFE_FT_TestTlmMessage_t; /* A message intended to be (overall) larger than the CFE_MISSION_SB_MAX_SB_MSG_SIZE */ -typedef struct +typedef union { - CFE_MSG_Message_t Hdr; - uint8 MaxSize[CFE_MISSION_SB_MAX_SB_MSG_SIZE]; + CFE_MSG_Message_t Hdr; + CFE_MSG_CommandHeader_t CmdHeader; + CFE_MSG_TelemetryHeader_t TlmHeader; + uint8 MaxSize[CFE_MISSION_SB_MAX_SB_MSG_SIZE + 16]; + char StringBuffer[CFE_FT_STRINGBUF_SIZE]; } CFE_FT_TestBigMessage_t; /* @@ -137,8 +142,11 @@ void TestBasicTransmitRecv(void) /* * 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) + * + * Note this also utilizes the CFE_SB_PEND_FOREVER flag - if working correctly, + * there should be a message in the queue, so it should not block. */ - UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, 100), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, CFE_SB_PEND_FOREVER), 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); @@ -146,7 +154,7 @@ void TestBasicTransmitRecv(void) 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_SB_ReceiveBuffer(&MsgBuf, PipeId1, CFE_SB_PEND_FOREVER), 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); @@ -154,7 +162,7 @@ void TestBasicTransmitRecv(void) 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_SB_ReceiveBuffer(&MsgBuf, PipeId1, CFE_SB_PEND_FOREVER), 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); @@ -163,6 +171,7 @@ void TestBasicTransmitRecv(void) UtAssert_UINT32_EQ(Seq1, 11); /* Final should not be in the pipe, should have been rejected due to MsgLim */ + /* Must not use CFE_SB_PEND_FOREVER here, as this will cause the test to block */ UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, 100), CFE_SB_TIME_OUT); /* @@ -200,15 +209,179 @@ void TestBasicTransmitRecv(void) UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId2), CFE_SUCCESS); } +/* + * Test distribution/broadcasting features (MsgLimit/PipeDepth enforcement, etc) + * + * Important to verify that although some receive pipes may have errors/limits, it should not affect + * the transmit side nor should it affect delivery to pipes that do not have limit errors. + */ +void TestMsgBroadcast(void) +{ + CFE_SB_PipeId_t PipeId1; + CFE_SB_PipeId_t PipeId2; + CFE_SB_PipeId_t PipeId3; + CFE_SB_PipeId_t PipeId4; + CFE_FT_TestCmdMessage_t CmdMsg; + CFE_SB_MsgId_t MsgId; + CFE_SB_Buffer_t * MsgBuf1; + CFE_SB_Buffer_t * MsgBuf2; + CFE_SB_Buffer_t * MsgBuf3; + CFE_SB_Buffer_t * MsgBuf4; + const CFE_FT_TestCmdMessage_t *CmdPtr; + + UtPrintf("Testing: MsgLimit enforcement"); + + /* Setup - subscribe same MsgId to multiple different pipes with different limits */ + UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId1, 3, "TestPipe1"), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId2, 3, "TestPipe2"), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId3, 3, "TestPipe3"), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId4, 5, "TestPipe4"), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_SubscribeEx(CFE_FT_CMD_MSGID, PipeId1, CFE_SB_DEFAULT_QOS, 1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_SubscribeEx(CFE_FT_CMD_MSGID, PipeId2, CFE_SB_DEFAULT_QOS, 2), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_SubscribeEx(CFE_FT_CMD_MSGID, PipeId3, CFE_SB_DEFAULT_QOS, 4), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_SubscribeEx(CFE_FT_CMD_MSGID, PipeId4, CFE_SB_DEFAULT_QOS, 6), CFE_SUCCESS); + + /* Initialize the message content */ + UtAssert_INT32_EQ(CFE_MSG_Init(&CmdMsg.CmdHeader.Msg, CFE_FT_CMD_MSGID, sizeof(CmdMsg)), CFE_SUCCESS); + + /* Make unique content in each message. Sending should always be successful. */ + CmdMsg.CmdPayload = 0xbabb1e00; + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&CmdMsg.CmdHeader.Msg, true), CFE_SUCCESS); + CmdMsg.CmdPayload = 0xbabb1e01; + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&CmdMsg.CmdHeader.Msg, true), CFE_SUCCESS); + CmdMsg.CmdPayload = 0xbabb1e02; + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&CmdMsg.CmdHeader.Msg, true), CFE_SUCCESS); + CmdMsg.CmdPayload = 0xbabb1e03; + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&CmdMsg.CmdHeader.Msg, true), CFE_SUCCESS); + + /* Now receive 1st message from Pipes, actual msg should appear on all (no limit violations here) */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf1, PipeId1, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf2, PipeId2, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf3, PipeId3, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf4, PipeId4, CFE_SB_POLL), CFE_SUCCESS); + + /* All pipes should have gotten the same actual buffer */ + UtAssert_ADDRESS_EQ(MsgBuf1, MsgBuf2); + UtAssert_ADDRESS_EQ(MsgBuf1, MsgBuf3); + UtAssert_ADDRESS_EQ(MsgBuf1, MsgBuf4); + + /* Confirm content */ + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf1->Msg, &MsgId), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_CMD_MSGID); + CmdPtr = (const CFE_FT_TestCmdMessage_t *)MsgBuf1; + UtAssert_UINT32_EQ(CmdPtr->CmdPayload, 0xbabb1e00); + + /* Now receive 2nd message from Pipes, should not appear on PipeId 1 due to MsgLimit */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf1, PipeId1, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf2, PipeId2, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf3, PipeId3, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf4, PipeId4, CFE_SB_POLL), CFE_SUCCESS); + + /* All pipes should have gotten the same actual buffer */ + UtAssert_ADDRESS_EQ(MsgBuf2, MsgBuf3); + UtAssert_ADDRESS_EQ(MsgBuf2, MsgBuf4); + + /* Confirm content */ + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf2->Msg, &MsgId), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_CMD_MSGID); + CmdPtr = (const CFE_FT_TestCmdMessage_t *)MsgBuf2; + UtAssert_UINT32_EQ(CmdPtr->CmdPayload, 0xbabb1e01); + + /* Now receive 3rd message from Pipes, should not appear on PipeId 1 or 2 due to MsgLimit */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf1, PipeId1, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf2, PipeId2, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf3, PipeId3, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf4, PipeId4, CFE_SB_POLL), CFE_SUCCESS); + + /* All pipes should have gotten the same actual buffer */ + UtAssert_ADDRESS_EQ(MsgBuf3, MsgBuf4); + + /* Confirm content */ + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf3->Msg, &MsgId), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_CMD_MSGID); + CmdPtr = (const CFE_FT_TestCmdMessage_t *)MsgBuf3; + UtAssert_UINT32_EQ(CmdPtr->CmdPayload, 0xbabb1e02); + + /* Now receive 4th message from Pipes, should only appear on PipeId4 due PipeDepth limit on 3 */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf1, PipeId1, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf2, PipeId2, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf3, PipeId3, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf4, PipeId4, CFE_SB_POLL), CFE_SUCCESS); + + /* Confirm content */ + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf4->Msg, &MsgId), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_CMD_MSGID); + CmdPtr = (const CFE_FT_TestCmdMessage_t *)MsgBuf4; + UtAssert_UINT32_EQ(CmdPtr->CmdPayload, 0xbabb1e03); + + UtPrintf("Testing: Unsubscribe single pipe"); + + /* Now unsubscribe only one of the pipes, and confirm no messages delivered to that pipe */ + UtAssert_INT32_EQ(CFE_SB_Unsubscribe(CFE_FT_CMD_MSGID, PipeId2), CFE_SUCCESS); + + /* Send two more messages */ + CmdMsg.CmdPayload = 0xbabb1e04; + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&CmdMsg.CmdHeader.Msg, true), CFE_SUCCESS); + CmdMsg.CmdPayload = 0xbabb1e05; + UtAssert_INT32_EQ(CFE_SB_TransmitMsg(&CmdMsg.CmdHeader.Msg, true), CFE_SUCCESS); + + /* poll all pipes again, message should appear on all except PipeId2 (Unsubscribed) */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf1, PipeId1, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf2, PipeId2, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf3, PipeId3, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf4, PipeId4, CFE_SB_POLL), CFE_SUCCESS); + + /* All pipes should have gotten the same actual buffer */ + UtAssert_ADDRESS_EQ(MsgBuf1, MsgBuf3); + UtAssert_ADDRESS_EQ(MsgBuf1, MsgBuf4); + + /* Confirm content */ + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf1->Msg, &MsgId), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_CMD_MSGID); + CmdPtr = (const CFE_FT_TestCmdMessage_t *)MsgBuf1; + UtAssert_UINT32_EQ(CmdPtr->CmdPayload, 0xbabb1e04); + + /* poll all pipes again, message should appear on all except PipeId1 (MsgLim) or PipeId2 (Unsubscribed) */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf1, PipeId1, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf2, PipeId2, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf3, PipeId3, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf4, PipeId4, CFE_SB_POLL), CFE_SUCCESS); + + /* All pipes should have gotten the same actual buffer */ + UtAssert_ADDRESS_EQ(MsgBuf3, MsgBuf4); + + /* Confirm content */ + UtAssert_INT32_EQ(CFE_MSG_GetMsgId(&MsgBuf3->Msg, &MsgId), CFE_SUCCESS); + CFE_UtAssert_MSGID_EQ(MsgId, CFE_FT_CMD_MSGID); + CmdPtr = (const CFE_FT_TestCmdMessage_t *)MsgBuf3; + UtAssert_UINT32_EQ(CmdPtr->CmdPayload, 0xbabb1e05); + + /* poll all pipes again, all should be empty now */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf1, PipeId1, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf2, PipeId2, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf3, PipeId3, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf4, PipeId4, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + + /* Cleanup */ + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId1), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId2), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId3), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId4), 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; + 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; + CFE_MSG_SequenceCount_t SeqCmd1; + CFE_MSG_SequenceCount_t SeqTlm1; + CFE_MSG_SequenceCount_t SeqCmd2; + CFE_MSG_SequenceCount_t SeqTlm2; /* Setup, create a pipe and subscribe (one cmd, one tlm) */ UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId1, 5, "TestPipe1"), CFE_SUCCESS); @@ -262,22 +435,165 @@ void TestZeroCopyTransmitRecv(void) 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, PipeId1, CFE_SB_POLL), CFE_SB_NO_MESSAGE); 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); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId2, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + + /* Attempt to send a msg of maximum size */ + UtAssert_NOT_NULL(CmdBuf = CFE_SB_AllocateMessageBuffer(CFE_MISSION_SB_MAX_SB_MSG_SIZE)); + + /* First initialize to indicate its even bigger than the max (should fail to transmit) */ + UtAssert_INT32_EQ(CFE_MSG_Init(&CmdBuf->Msg, CFE_FT_CMD_MSGID, sizeof(CFE_FT_BigMsg)), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitBuffer(CmdBuf, true), CFE_SB_MSG_TOO_BIG); + + /* reducing size should make it work */ + UtAssert_INT32_EQ(CFE_MSG_SetSize(&CmdBuf->Msg, CFE_MISSION_SB_MAX_SB_MSG_SIZE), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitBuffer(CmdBuf, true), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_ADDRESS_EQ(MsgBuf, CmdBuf); /* should be the same actual buffer (not a copy) */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, CFE_SB_POLL), CFE_SB_NO_MESSAGE); + + UtPrintf("Testing: CFE_SB_TransmitBuffer sequence number updates"); + + /* Send a set of messages with and without sequence number update flag */ + UtAssert_NOT_NULL(CmdBuf = CFE_SB_AllocateMessageBuffer(sizeof(CFE_FT_TestCmdMessage_t))); + UtAssert_NOT_NULL(TlmBuf = CFE_SB_AllocateMessageBuffer(sizeof(CFE_FT_TestTlmMessage_t))); + 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_MSG_SetSequenceCount(&CmdBuf->Msg, 1234), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_SetSequenceCount(&TlmBuf->Msg, 5678), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitBuffer(CmdBuf, true), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitBuffer(TlmBuf, true), CFE_SUCCESS); + + /* Receive and get initial sequence count */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetSequenceCount(&MsgBuf->Msg, &SeqCmd1), CFE_SUCCESS); + UtAssert_UINT32_EQ(SeqCmd1, 1234); /* NOTE: commands currently do NOT honor "Increment" flag */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId2, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetSequenceCount(&MsgBuf->Msg, &SeqTlm1), CFE_SUCCESS); + + /* Send a second message also with increment = true and confirm value */ + UtAssert_NOT_NULL(CmdBuf = CFE_SB_AllocateMessageBuffer(sizeof(CFE_FT_TestCmdMessage_t))); + UtAssert_NOT_NULL(TlmBuf = CFE_SB_AllocateMessageBuffer(sizeof(CFE_FT_TestTlmMessage_t))); + 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_MSG_SetSequenceCount(&CmdBuf->Msg, 1234), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_SetSequenceCount(&TlmBuf->Msg, 5678), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitBuffer(CmdBuf, true), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitBuffer(TlmBuf, true), CFE_SUCCESS); + + /* Receive and get current sequence count */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetSequenceCount(&MsgBuf->Msg, &SeqCmd2), CFE_SUCCESS); + UtAssert_UINT32_EQ(SeqCmd2, 1234); /* NOTE: commands currently do NOT honor "Increment" flag */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId2, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetSequenceCount(&MsgBuf->Msg, &SeqTlm2), CFE_SUCCESS); + UtAssert_UINT32_EQ(SeqTlm2, CFE_MSG_GetNextSequenceCount(SeqTlm1)); /* should be +1 from the previous */ + + /* Send a third message also with increment = false and confirm value */ + UtAssert_NOT_NULL(CmdBuf = CFE_SB_AllocateMessageBuffer(sizeof(CFE_FT_TestCmdMessage_t))); + UtAssert_NOT_NULL(TlmBuf = CFE_SB_AllocateMessageBuffer(sizeof(CFE_FT_TestTlmMessage_t))); + 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_MSG_SetSequenceCount(&CmdBuf->Msg, 1234), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_SetSequenceCount(&TlmBuf->Msg, 5678), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitBuffer(CmdBuf, false), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_SB_TransmitBuffer(TlmBuf, false), CFE_SUCCESS); + + /* Receive and get sequence count, should NOT be incremented from previous */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId1, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetSequenceCount(&MsgBuf->Msg, &SeqCmd1), CFE_SUCCESS); + UtAssert_UINT32_EQ(SeqCmd1, 1234); /* should match initialized value */ + UtAssert_INT32_EQ(CFE_SB_ReceiveBuffer(&MsgBuf, PipeId2, CFE_SB_POLL), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_MSG_GetSequenceCount(&MsgBuf->Msg, &SeqTlm1), CFE_SUCCESS); + UtAssert_UINT32_EQ(SeqTlm1, 5678); /* should match initialized value */ /* Cleanup */ UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId1), CFE_SUCCESS); UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId2), CFE_SUCCESS); } +void TestMiscMessageUtils(void) +{ + char TestString[CFE_FT_STRINGBUF_SIZE + 4]; + const char RefString1[] = "abc"; + const char RefString2[] = "defg"; + + memset(&CFE_FT_BigMsg, 'x', sizeof(CFE_FT_BigMsg)); + memset(TestString, 'y', sizeof(TestString)); + + /* nominal CFE_SB_MessageStringGet */ + UtAssert_INT32_EQ(CFE_SB_MessageStringGet(TestString, CFE_FT_BigMsg.StringBuffer, RefString1, sizeof(TestString), + sizeof(CFE_FT_BigMsg.StringBuffer)), + CFE_FT_STRINGBUF_SIZE); + + /* The result should be null terminated, even if the input was not */ + UtAssert_ZERO(TestString[CFE_FT_STRINGBUF_SIZE]); + UtAssert_STRINGBUF_EQ(TestString, sizeof(TestString), CFE_FT_BigMsg.StringBuffer, + sizeof(CFE_FT_BigMsg.StringBuffer)); + + /* No default */ + memset(&CFE_FT_BigMsg, 'w', sizeof(CFE_FT_BigMsg)); + UtAssert_INT32_EQ(CFE_SB_MessageStringGet(TestString, CFE_FT_BigMsg.StringBuffer, NULL, sizeof(TestString), + sizeof(CFE_FT_BigMsg.StringBuffer)), + CFE_FT_STRINGBUF_SIZE); + UtAssert_STRINGBUF_EQ(TestString, sizeof(TestString), CFE_FT_BigMsg.StringBuffer, + sizeof(CFE_FT_BigMsg.StringBuffer)); + UtAssert_ZERO(TestString[CFE_FT_STRINGBUF_SIZE]); + UtAssert_STRINGBUF_EQ(TestString, sizeof(TestString), CFE_FT_BigMsg.StringBuffer, + sizeof(CFE_FT_BigMsg.StringBuffer)); + + /* Check if the input is empty */ + memset(&CFE_FT_BigMsg, 0, sizeof(CFE_FT_BigMsg)); + UtAssert_INT32_EQ(CFE_SB_MessageStringGet(TestString, CFE_FT_BigMsg.StringBuffer, RefString1, sizeof(TestString), + sizeof(CFE_FT_BigMsg.StringBuffer)), + sizeof(RefString1) - 1); + UtAssert_STRINGBUF_EQ(TestString, sizeof(TestString), RefString1, sizeof(RefString1)); + UtAssert_INT32_EQ(CFE_SB_MessageStringGet(TestString, NULL, RefString2, sizeof(TestString), 0), + sizeof(RefString2) - 1); + UtAssert_STRINGBUF_EQ(TestString, sizeof(TestString), RefString2, sizeof(RefString2)); + + /* Neither source nor default */ + UtAssert_INT32_EQ(CFE_SB_MessageStringGet(TestString, NULL, NULL, sizeof(TestString), 0), CFE_SUCCESS); + UtAssert_STRINGBUF_EQ(TestString, sizeof(TestString), "", 1); + + /* bad inputs */ + UtAssert_INT32_EQ(CFE_SB_MessageStringGet(NULL, CFE_FT_BigMsg.StringBuffer, RefString1, sizeof(TestString), + sizeof(CFE_FT_BigMsg.StringBuffer)), + CFE_SB_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_SB_MessageStringGet(TestString, CFE_FT_BigMsg.StringBuffer, RefString1, 0, + sizeof(CFE_FT_BigMsg.StringBuffer)), + CFE_SB_BAD_ARGUMENT); + + /* nominal CFE_SB_MessageStringSet */ + memset(TestString, 'z', sizeof(TestString)); + UtAssert_INT32_EQ(CFE_SB_MessageStringSet(CFE_FT_BigMsg.StringBuffer, TestString, + sizeof(CFE_FT_BigMsg.StringBuffer), sizeof(TestString)), + CFE_FT_STRINGBUF_SIZE); + UtAssert_STRINGBUF_EQ(TestString, CFE_FT_STRINGBUF_SIZE, CFE_FT_BigMsg.StringBuffer, CFE_FT_STRINGBUF_SIZE); + + /* The result should NOT be null terminated (fixed size msg string does not need it) */ + UtAssert_INT32_EQ(CFE_FT_BigMsg.StringBuffer[sizeof(CFE_FT_BigMsg.StringBuffer) - 1], 'z'); + /* Should not have overwritten anything beyond the fixed buffer */ + UtAssert_ZERO(CFE_FT_BigMsg.MaxSize[sizeof(CFE_FT_BigMsg.StringBuffer)]); + + /* bad inputs */ + UtAssert_INT32_EQ(CFE_SB_MessageStringSet(NULL, TestString, sizeof(CFE_FT_BigMsg.StringBuffer), sizeof(TestString)), + CFE_SB_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_SB_MessageStringSet(CFE_FT_BigMsg.StringBuffer, NULL, sizeof(CFE_FT_BigMsg.StringBuffer), + sizeof(TestString)), + CFE_SB_BAD_ARGUMENT); +} + void SBSendRecvTestSetup(void) { UtTest_Add(TestBasicTransmitRecv, NULL, NULL, "Test Basic Transmit/Receive"); UtTest_Add(TestZeroCopyTransmitRecv, NULL, NULL, "Test Zero Copy Transmit/Receive"); + UtTest_Add(TestMsgBroadcast, NULL, NULL, "Test Msg Broadcast"); + UtTest_Add(TestMiscMessageUtils, NULL, NULL, "Test Miscellaneous Message Utility APIs"); } diff --git a/modules/cfe_testcase/src/sb_subscription_test.c b/modules/cfe_testcase/src/sb_subscription_test.c index 7fe51de5d..8e1745272 100644 --- a/modules/cfe_testcase/src/sb_subscription_test.c +++ b/modules/cfe_testcase/src/sb_subscription_test.c @@ -238,11 +238,56 @@ void TestSBMaxSubscriptions(void) UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId), CFE_SUCCESS); } +/* This is a different flavor of the subscription limit - a single msgid can only + * have up to CFE_PLATFORM_SB_MAX_DEST_PER_PKT destinations */ +void TestSBMaxDestinations(void) +{ + CFE_SB_PipeId_t PipeId[CFE_PLATFORM_SB_MAX_DEST_PER_PKT + 1]; + char PipeName[CFE_MISSION_MAX_API_LEN]; + uint32 NumDests; + + UtPrintf("Testing: CFE_SB_Subscribe, max destination limit"); + + NumDests = 0; + while (NumDests <= CFE_PLATFORM_SB_MAX_DEST_PER_PKT) + { + snprintf(PipeName, sizeof(PipeName), "TestPipe%u", (unsigned int)NumDests); + if (!UtAssert_INT32_EQ(CFE_SB_CreatePipe(&PipeId[NumDests], 2, PipeName), CFE_SUCCESS)) + { + break; + } + + if (NumDests == CFE_PLATFORM_SB_MAX_DEST_PER_PKT) + { + /* All 3 variations of subscribe can be checked here, they should all fail identically */ + UtAssert_INT32_EQ(CFE_SB_Subscribe(CFE_FT_CMD_MSGID, PipeId[NumDests]), CFE_SB_MAX_DESTS_MET); + UtAssert_INT32_EQ(CFE_SB_SubscribeEx(CFE_FT_CMD_MSGID, PipeId[NumDests], CFE_SB_DEFAULT_QOS, 2), + CFE_SB_MAX_DESTS_MET); + UtAssert_INT32_EQ(CFE_SB_SubscribeLocal(CFE_FT_CMD_MSGID, PipeId[NumDests], 2), CFE_SB_MAX_DESTS_MET); + } + else + { + UtAssert_INT32_EQ(CFE_SB_Subscribe(CFE_FT_CMD_MSGID, PipeId[NumDests]), CFE_SUCCESS); + } + + ++NumDests; + } + + while (NumDests > 0) + { + --NumDests; + + /* Note this should also remove any subscriptions from the above loop */ + UtAssert_INT32_EQ(CFE_SB_DeletePipe(PipeId[NumDests]), 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"); + UtTest_Add(TestSBMaxDestinations, NULL, NULL, "Test SB Max Destinations"); /* * NOTE: The TestSBMaxSubscriptions() is not included/added by default, as it will fill the diff --git a/modules/cfe_testcase/src/tbl_content_access_test.c b/modules/cfe_testcase/src/tbl_content_access_test.c index 08c60e868..8e215ab63 100644 --- a/modules/cfe_testcase/src/tbl_content_access_test.c +++ b/modules/cfe_testcase/src/tbl_content_access_test.c @@ -51,7 +51,7 @@ void TestGetAddress(void) /* Never loaded */ UtAssert_INT32_EQ(CFE_TBL_GetAddress(&TblPtr, CFE_FT_Global.TblHandle), CFE_TBL_ERR_NEVER_LOADED); UtAssert_INT32_EQ(CFE_TBL_GetAddress(&TblPtr, CFE_TBL_BAD_TABLE_HANDLE), CFE_TBL_ERR_INVALID_HANDLE); - UtAssert_INT32_EQ(CFE_TBL_GetAddress(NULL, CFE_TBL_BAD_TABLE_HANDLE), CFE_TBL_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_TBL_GetAddress(NULL, CFE_FT_Global.TblHandle), CFE_TBL_BAD_ARGUMENT); /* Returns CFE_TBL_INFO_UPDATED since it was just loaded */ LoadTable(&TestTable, CFE_SUCCESS); diff --git a/modules/cfe_testcase/src/tbl_content_mang_test.c b/modules/cfe_testcase/src/tbl_content_mang_test.c index dd525c431..c0a133aea 100644 --- a/modules/cfe_testcase/src/tbl_content_mang_test.c +++ b/modules/cfe_testcase/src/tbl_content_mang_test.c @@ -34,51 +34,174 @@ #include "cfe_test.h" #include "cfe_test_table.h" -/* Does not test partial loads */ +static const char TESTTBL_OTHER_NAME[] = "OtherTbl"; + +/* A set of additional (generated) table images to test permutations of CFE_TBL_Load() */ +static const char TESTTBL_NOMINAL_FILE[] = + "/cf/cfe_test_tbl.tbl"; /**< nominal image file, from table tool (elf2cfetbl or similar) */ +static const char TESTTBL_NOTEXIST_FILE[] = + "/ram/notexist.tbl"; /**< a valid filename, but file does not actually exist */ +static const char TESTTBL_BAD_STDHDR_FILE[] = "/ram/testtbl_shdr.tbl"; /**< bad image without a complete FS header */ +static const char TESTTBL_BAD_TBLHDR_FILE[] = "/ram/testtbl_thdr.tbl"; /**< bad image without a complete TBL header */ +static const char TESTTBL_BAD_CONTENT_FILE[] = "/ram/testtbl_cid.tbl"; /**< image with incorrect "content ID" field */ +static const char TESTTBL_BAD_SUBTYPE_FILE[] = "/ram/testtbl_st.tbl"; /**< image with incorrect "subtype" field */ +static const char TESTTBL_ALTERNATE_FILE[] = "/ram/testtbl_alt.tbl"; /**< good/complete image with different content */ +static const char TESTTBL_OTHERTBL_FILE[] = + "/ram/testtbl_other.tbl"; /**< good/complete image with different content for a different table */ +static const char TESTTBL_TRUNCATED_FILE[] = + "/ram/testtbl_trunc.tbl"; /**< truncated version (header info has more bytes than file) */ +static const char TESTTBL_LONG_FILE[] = + "/ram/testtbl_long.tbl"; /**< long version (file has more bytes than header info) */ +static const char TESTTBL_SHORT_FILE[] = + "/ram/testtbl_short.tbl"; /**< short version (header info matches file but smaller than tbl) */ +static const char TESTTBL_PARTIAL_FILE[] = + "/ram/testtbl_part.tbl"; /**< partial (offset nonzero, remainder of data from short file) */ + void TestLoad(void) { + CFE_TBL_Handle_t BadTblHandle; + const char * BadTblName = "BadTableName"; + CFE_TBL_Handle_t DumpTblHandle; + const char * DumpTblName = "DumpOnlyTable"; + CFE_TBL_Handle_t SharedTblHandle; + const char * SharedTblName = CFE_FT_Global.RegisteredTblName; + TBL_TEST_Table_t TestTable = {0xd00d, 0xdad}; + TBL_TEST_Table_t *TablePtr; + CFE_TBL_Handle_t OtherHandle; + UtPrintf("Testing: CFE_TBL_Load"); - CFE_TBL_Handle_t BadTblHandle; - const char * BadTblName = "BadTableName"; + UtAssert_INT32_EQ( CFE_TBL_Register(&BadTblHandle, BadTblName, sizeof(TBL_TEST_Table_t), CFE_TBL_OPT_DBL_BUFFER, NULL), CFE_SUCCESS); - /* Load from file */ - UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, "/cf/cfe_test_tbl.tbl"), CFE_SUCCESS); - /* Load again */ - UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, "/cf/cfe_test_tbl.tbl"), CFE_SUCCESS); + /* Create a second table handle, to keep things interesting */ + UtAssert_INT32_EQ(CFE_TBL_Register(&OtherHandle, TESTTBL_OTHER_NAME, sizeof(TBL_TEST_Table_t), 0, NULL), + CFE_SUCCESS); + + /* Some basic failure checks */ + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_BAD_STDHDR_FILE), + CFE_TBL_ERR_NO_STD_HEADER); + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_BAD_TBLHDR_FILE), + CFE_TBL_ERR_NO_TBL_HEADER); + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_BAD_CONTENT_FILE), + CFE_TBL_ERR_BAD_CONTENT_ID); + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_BAD_SUBTYPE_FILE), + CFE_TBL_ERR_BAD_SUBTYPE_ID); + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, ~CFE_TBL_SRC_FILE, TESTTBL_NOMINAL_FILE), + CFE_TBL_ERR_ILLEGAL_SRC_TYPE); + + /* Load from partial file (offset nonzero, before any successful load) - + * This should be restricted and return an error */ + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_PARTIAL_FILE), + CFE_TBL_ERR_PARTIAL_LOAD); + + /* Load from short file (offset 0, but incomplete, also before any successful load) */ + /* In the current TBL implementation, this actually returns SUCCESS here (which is misleading) */ + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_SHORT_FILE), CFE_SUCCESS); + + /* NOTE: _NOT_ checking content after above; although it returned a success code, it is not well defined + * as to what the content will be because the data was never fully loaded yet */ + + /* Load from file (nominal) - first full data load */ + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_NOMINAL_FILE), CFE_SUCCESS); + + /* confirm content (football) */ + UtAssert_INT32_EQ(CFE_TBL_GetAddress((void **)&TablePtr, CFE_FT_Global.TblHandle), CFE_TBL_INFO_UPDATED); + UtAssert_UINT32_EQ(TablePtr->Int1, 0xf007); + UtAssert_UINT32_EQ(TablePtr->Int2, 0xba11); + UtAssert_INT32_EQ(CFE_TBL_ReleaseAddress(CFE_FT_Global.TblHandle), CFE_SUCCESS); + + /* Load from file too big */ + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_LONG_FILE), + CFE_TBL_ERR_FILE_TOO_LARGE); + + /* confirm content again (note content should not have been updated) */ + UtAssert_INT32_EQ(CFE_TBL_GetAddress((void **)&TablePtr, CFE_FT_Global.TblHandle), CFE_SUCCESS); + UtAssert_UINT32_EQ(TablePtr->Int1, 0xf007); + UtAssert_UINT32_EQ(TablePtr->Int2, 0xba11); + UtAssert_INT32_EQ(CFE_TBL_ReleaseAddress(CFE_FT_Global.TblHandle), CFE_SUCCESS); + + /* Load again with alternate content */ + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_ALTERNATE_FILE), CFE_SUCCESS); + + /* confirm content again (changed to alternate data) */ + UtAssert_INT32_EQ(CFE_TBL_GetAddress((void **)&TablePtr, CFE_FT_Global.TblHandle), CFE_TBL_INFO_UPDATED); + UtAssert_UINT32_EQ(TablePtr->Int1, 0xdead); + UtAssert_UINT32_EQ(TablePtr->Int2, 0xbeef); + UtAssert_INT32_EQ(CFE_TBL_ReleaseAddress(CFE_FT_Global.TblHandle), CFE_SUCCESS); + + /* Load from file truncated */ + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_TRUNCATED_FILE), + CFE_TBL_ERR_LOAD_INCOMPLETE); + + /* confirm content again (should not be changed) */ + UtAssert_INT32_EQ(CFE_TBL_GetAddress((void **)&TablePtr, CFE_FT_Global.TblHandle), CFE_SUCCESS); + UtAssert_UINT32_EQ(TablePtr->Int1, 0xdead); + UtAssert_UINT32_EQ(TablePtr->Int2, 0xbeef); + UtAssert_INT32_EQ(CFE_TBL_ReleaseAddress(CFE_FT_Global.TblHandle), CFE_SUCCESS); + + /* Load the other table (nominal data) */ + UtAssert_INT32_EQ(CFE_TBL_Load(OtherHandle, CFE_TBL_SRC_FILE, TESTTBL_OTHERTBL_FILE), CFE_SUCCESS); + + /* confirm content of first table again (should not be changed) */ + UtAssert_INT32_EQ(CFE_TBL_GetAddress((void **)&TablePtr, CFE_FT_Global.TblHandle), CFE_SUCCESS); + UtAssert_UINT32_EQ(TablePtr->Int1, 0xdead); + UtAssert_UINT32_EQ(TablePtr->Int2, 0xbeef); + UtAssert_INT32_EQ(CFE_TBL_ReleaseAddress(CFE_FT_Global.TblHandle), CFE_SUCCESS); + + /* confirm content of other table (boatload) */ + UtAssert_INT32_EQ(CFE_TBL_GetAddress((void **)&TablePtr, OtherHandle), CFE_TBL_INFO_UPDATED); + UtAssert_UINT32_EQ(TablePtr->Int1, 0xb0a7); + UtAssert_UINT32_EQ(TablePtr->Int2, 0x10ad); + UtAssert_INT32_EQ(CFE_TBL_ReleaseAddress(OtherHandle), CFE_SUCCESS); + + /* Load from short file again (different response after successful load) */ + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_SHORT_FILE), CFE_SUCCESS); + + /* confirm content again (reported as updated from partial load) */ + /* Should have updated the first word only */ + UtAssert_INT32_EQ(CFE_TBL_GetAddress((void **)&TablePtr, CFE_FT_Global.TblHandle), CFE_TBL_INFO_UPDATED); + UtAssert_UINT32_EQ(TablePtr->Int1, 0x5555); + UtAssert_UINT32_EQ(TablePtr->Int2, 0xbeef); + UtAssert_INT32_EQ(CFE_TBL_ReleaseAddress(CFE_FT_Global.TblHandle), CFE_SUCCESS); + + /* Load from short file again (different response after successful load) */ + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_PARTIAL_FILE), CFE_SUCCESS); + + /* confirm content again (reported as updated from partial load) */ + /* Should have updated the second word only */ + UtAssert_INT32_EQ(CFE_TBL_GetAddress((void **)&TablePtr, CFE_FT_Global.TblHandle), CFE_TBL_INFO_UPDATED); + UtAssert_UINT32_EQ(TablePtr->Int1, 0x5555); + UtAssert_UINT32_EQ(TablePtr->Int2, 0x6666); + UtAssert_INT32_EQ(CFE_TBL_ReleaseAddress(CFE_FT_Global.TblHandle), CFE_SUCCESS); + /* Table name mismatches */ - UtAssert_INT32_EQ(CFE_TBL_Load(BadTblHandle, CFE_TBL_SRC_FILE, "/cf/cfe_test_tbl.tbl"), + UtAssert_INT32_EQ(CFE_TBL_Load(BadTblHandle, CFE_TBL_SRC_FILE, TESTTBL_NOMINAL_FILE), CFE_TBL_ERR_FILE_FOR_WRONG_TABLE); - UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, "/cf/sample_app_tbl.tbl"), + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_OTHERTBL_FILE), CFE_TBL_ERR_FILE_FOR_WRONG_TABLE); - UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, "/cf/not_cfe_test_tbl.tbl"), + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, TESTTBL_NOTEXIST_FILE), CFE_TBL_ERR_ACCESS); - UtAssert_INT32_EQ(CFE_TBL_Load(CFE_TBL_BAD_TABLE_HANDLE, CFE_TBL_SRC_FILE, "/cf/cfe_test_tbl.tbl"), + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_TBL_BAD_TABLE_HANDLE, CFE_TBL_SRC_FILE, TESTTBL_NOMINAL_FILE), CFE_TBL_ERR_INVALID_HANDLE); /* Load from memory */ - TBL_TEST_Table_t TestTable = {1, 2}; UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_ADDRESS, &TestTable), CFE_SUCCESS); UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_ADDRESS, NULL), CFE_TBL_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_TBL_Load(CFE_TBL_BAD_TABLE_HANDLE, CFE_TBL_SRC_ADDRESS, &TestTable), CFE_TBL_ERR_INVALID_HANDLE); /* Attempt to load a dump only table */ - CFE_TBL_Handle_t DumpTblHandle; - const char * DumpTblName = "DumpOnlyTable"; UtAssert_INT32_EQ( CFE_TBL_Register(&DumpTblHandle, DumpTblName, sizeof(TBL_TEST_Table_t), CFE_TBL_OPT_DUMP_ONLY, NULL), CFE_SUCCESS); - UtAssert_INT32_EQ(CFE_TBL_Load(DumpTblHandle, CFE_TBL_SRC_FILE, "/cf/cfe_test_tbl.tbl"), CFE_TBL_ERR_DUMP_ONLY); + UtAssert_INT32_EQ(CFE_TBL_Load(DumpTblHandle, CFE_TBL_SRC_FILE, TESTTBL_NOMINAL_FILE), CFE_TBL_ERR_DUMP_ONLY); /* Load a shared table */ - CFE_TBL_Handle_t SharedTblHandle; - const char * SharedTblName = "SAMPLE_APP.SampleAppTable"; UtAssert_INT32_EQ(CFE_TBL_Share(&SharedTblHandle, SharedTblName), CFE_SUCCESS); - UtAssert_INT32_EQ(CFE_TBL_Load(SharedTblHandle, CFE_TBL_SRC_FILE, "/cf/sample_app_tbl.tbl"), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_TBL_Load(SharedTblHandle, CFE_TBL_SRC_FILE, TESTTBL_NOMINAL_FILE), CFE_SUCCESS); } void TestUpdate(void) @@ -120,8 +243,239 @@ void TestModified(void) UtAssert_INT32_EQ(CFE_TBL_Modified(CFE_TBL_BAD_TABLE_HANDLE), CFE_TBL_ERR_INVALID_HANDLE); } +/* Helper function to set a CFE_ES_MemOffset_t value (must be big-endian) */ +void TblTest_UpdateOffset(CFE_ES_MemOffset_t *TgtVal, CFE_ES_MemOffset_t SetVal) +{ + union + { + CFE_ES_MemOffset_t offset; + uint8 bytes[sizeof(CFE_ES_MemOffset_t)]; + } offsetbuf; + + offsetbuf.bytes[3] = SetVal & 0xFF; + SetVal >>= 8; + offsetbuf.bytes[2] = SetVal & 0xFF; + SetVal >>= 8; + offsetbuf.bytes[1] = SetVal & 0xFF; + SetVal >>= 8; + offsetbuf.bytes[0] = SetVal & 0xFF; + + *TgtVal = offsetbuf.offset; +} + +/* + * A helper function that intentionally creates flawed table image files - + * This takes the good image file produced during the build, and creates + * variants with certain header fields modified and data truncated, to + * validate the error detection logic in CFE_TBL_Load(). + */ +void TblTest_GenerateTblFiles(void) +{ + osal_id_t fh1; + osal_id_t fh2; + uint32 PartialOffset; + uint32 PartialSize; + union + { + uint8 u8; + uint16 u16; + uint32 u32; + CFE_FS_Header_t FsHdr; + CFE_TBL_File_Hdr_t TblHdr; + TBL_TEST_Table_t Content; + } buf; + + /* Open the original (correct) table image file for reference */ + UtAssert_INT32_EQ(OS_OpenCreate(&fh1, TESTTBL_NOMINAL_FILE, 0, OS_READ_ONLY), OS_SUCCESS); + + /* create a file which does not have a valid FS header */ + UtAssert_INT32_EQ( + OS_OpenCreate(&fh2, TESTTBL_BAD_STDHDR_FILE, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY), + OS_SUCCESS); + buf.u32 = 0x12345678; + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.u32)), sizeof(buf.u32)); + UtAssert_INT32_EQ(OS_close(fh2), OS_SUCCESS); + + /* create a file which has an FS header but not a valid TBL header */ + OS_lseek(fh1, 0, OS_SEEK_SET); + UtAssert_INT32_EQ( + OS_OpenCreate(&fh2, TESTTBL_BAD_TBLHDR_FILE, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY), + OS_SUCCESS); + + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + buf.u32 = 0x12345678; + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.u32)), sizeof(buf.u32)); + UtAssert_INT32_EQ(OS_close(fh2), OS_SUCCESS); + + /* Create a tbl image that has the wrong content ID field */ + OS_lseek(fh1, 0, OS_SEEK_SET); + UtAssert_INT32_EQ( + OS_OpenCreate(&fh2, TESTTBL_BAD_CONTENT_FILE, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY), + OS_SUCCESS); + + /* copy headers and modify */ + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + buf.FsHdr.ContentType = 0x09abcdef; + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + + /* Identifiable content, different from original */ + buf.Content.Int1 = 0x7777; + buf.Content.Int2 = 0x8888; + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.Content)), sizeof(buf.Content)); + + UtAssert_INT32_EQ(OS_close(fh2), OS_SUCCESS); + + /* Create a tbl image that has the wrong content ID field */ + OS_lseek(fh1, 0, OS_SEEK_SET); + UtAssert_INT32_EQ( + OS_OpenCreate(&fh2, TESTTBL_BAD_SUBTYPE_FILE, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY), + OS_SUCCESS); + + /* copy headers as-is */ + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + buf.FsHdr.SubType = 0x09abcdef; + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + + /* Identifiable content, different from original */ + buf.Content.Int1 = 0x9999; + buf.Content.Int2 = 0xaaaa; + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.Content)), sizeof(buf.Content)); + + UtAssert_INT32_EQ(OS_close(fh2), OS_SUCCESS); + + /* Create a tbl image that is complete but with different content */ + OS_lseek(fh1, 0, OS_SEEK_SET); + UtAssert_INT32_EQ( + OS_OpenCreate(&fh2, TESTTBL_ALTERNATE_FILE, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY), + OS_SUCCESS); + + /* copy headers as-is */ + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + + /* Identifiable content, different from original */ + buf.Content.Int1 = 0xdead; + buf.Content.Int2 = 0xbeef; + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.Content)), sizeof(buf.Content)); + + UtAssert_INT32_EQ(OS_close(fh2), OS_SUCCESS); + + /* Create a tbl image that is complete but for the OTHER table (also different content) */ + OS_lseek(fh1, 0, OS_SEEK_SET); + UtAssert_INT32_EQ( + OS_OpenCreate(&fh2, TESTTBL_OTHERTBL_FILE, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY), + OS_SUCCESS); + + /* copy headers as-is */ + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + snprintf(buf.TblHdr.TableName, sizeof(buf.TblHdr.TableName), "%s.%s", "CFE_TEST_APP", TESTTBL_OTHER_NAME); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + + /* Identifiable content, different from original */ + buf.Content.Int1 = 0xb0a7; + buf.Content.Int2 = 0x10ad; + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.Content)), sizeof(buf.Content)); + + UtAssert_INT32_EQ(OS_close(fh2), OS_SUCCESS); + /* Create a tbl image that is too big */ + OS_lseek(fh1, 0, OS_SEEK_SET); + UtAssert_INT32_EQ( + OS_OpenCreate(&fh2, TESTTBL_LONG_FILE, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY), OS_SUCCESS); + + /* copy headers as-is */ + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + + /* write content, but make it identifiable/unique */ + buf.Content.Int1 = 0x1111; + buf.Content.Int1 = 0x2222; + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.Content)), sizeof(buf.Content)); + + /* Write extra byte at the end */ + buf.u8 = 0x33; + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.u8)), sizeof(buf.u8)); + UtAssert_INT32_EQ(OS_close(fh2), OS_SUCCESS); + + /* Create a tbl image that is truncated; header byte count is larger than file */ + OS_lseek(fh1, 0, OS_SEEK_SET); + UtAssert_INT32_EQ( + OS_OpenCreate(&fh2, TESTTBL_TRUNCATED_FILE, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY), + OS_SUCCESS); + + /* copy headers as-is */ + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + + /* But write only one byte of data into the content part (so will be too small) */ + buf.u8 = 0x44; + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.u8)), sizeof(buf.u8)); + + UtAssert_INT32_EQ(OS_close(fh2), OS_SUCCESS); + + /* Make a file that is "short" (byte count is correct, just not enough bytes to fill table) */ + OS_lseek(fh1, 0, OS_SEEK_SET); + UtAssert_INT32_EQ( + OS_OpenCreate(&fh2, TESTTBL_SHORT_FILE, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY), + OS_SUCCESS); + + /* copy headers, but modify TBL header */ + /* NOTE: headers must be in big-endian/network byte order! */ + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + PartialOffset = 0; + PartialSize = offsetof(TBL_TEST_Table_t, Int2); + TblTest_UpdateOffset(&buf.TblHdr.Offset, PartialOffset); + TblTest_UpdateOffset(&buf.TblHdr.NumBytes, PartialSize); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + + /* write partial content */ + buf.Content.Int1 = 0x5555; + UtAssert_INT32_EQ(OS_write(fh2, &buf, PartialSize), PartialSize); + UtAssert_INT32_EQ(OS_close(fh2), OS_SUCCESS); + + /* Make a file that is "partial" (contains remainder of bytes from above) */ + OS_lseek(fh1, 0, OS_SEEK_SET); + UtAssert_INT32_EQ( + OS_OpenCreate(&fh2, TESTTBL_PARTIAL_FILE, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY), + OS_SUCCESS); + + /* copy headers, but modify TBL header */ + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.FsHdr)), sizeof(buf.FsHdr)); + UtAssert_INT32_EQ(OS_read(fh1, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + PartialOffset = offsetof(TBL_TEST_Table_t, Int2); + PartialSize = sizeof(buf.Content) - offsetof(TBL_TEST_Table_t, Int2); + TblTest_UpdateOffset(&buf.TblHdr.Offset, PartialOffset); + TblTest_UpdateOffset(&buf.TblHdr.NumBytes, PartialSize); + UtAssert_INT32_EQ(OS_write(fh2, &buf, sizeof(buf.TblHdr)), sizeof(buf.TblHdr)); + + /* Copy partial content */ + buf.Content.Int2 = 0x6666; + UtAssert_INT32_EQ(OS_write(fh2, &buf.Content.Int2, PartialSize), PartialSize); + UtAssert_INT32_EQ(OS_close(fh2), OS_SUCCESS); + + /* Close the source file */ + UtAssert_INT32_EQ(OS_close(fh1), OS_SUCCESS); +} + void TBLContentMangTestSetup(void) { + TblTest_GenerateTblFiles(); + UtTest_Add(TestLoad, RegisterTestTable, UnregisterTestTable, "Test Table Load"); UtTest_Add(TestUpdate, RegisterTestTable, UnregisterTestTable, "Test Table Update"); UtTest_Add(TestValidate, RegisterTestTable, UnregisterTestTable, "Test Table Validate"); diff --git a/modules/cfe_testcase/src/tbl_information_test.c b/modules/cfe_testcase/src/tbl_information_test.c index 6adcbd541..813aa4ef0 100644 --- a/modules/cfe_testcase/src/tbl_information_test.c +++ b/modules/cfe_testcase/src/tbl_information_test.c @@ -33,6 +33,7 @@ #include "cfe_test.h" #include "cfe_test_table.h" +#include "cfe_msgids.h" void TestGetStatus(void) { @@ -53,6 +54,7 @@ void TestGetInfo(void) UtAssert_INT32_EQ(CFE_TBL_GetInfo(&TblInfo, CFE_FT_Global.RegisteredTblName), CFE_SUCCESS); UtAssert_INT32_EQ(CFE_TBL_GetInfo(NULL, CFE_FT_Global.TblName), CFE_TBL_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_TBL_GetInfo(&TblInfo, BadTblName), CFE_TBL_ERR_INVALID_NAME); + UtAssert_INT32_EQ(CFE_TBL_GetInfo(&TblInfo, NULL), CFE_TBL_BAD_ARGUMENT); /* This is only checking some parts of the TblInfo struct */ size_t expectedSize = sizeof(TBL_TEST_Table_t); @@ -76,9 +78,13 @@ void TestNotifyByMessage(void) UtPrintf("Testing: CFE_TBL_NotifyByMessage"); CFE_TBL_Handle_t SharedTblHandle; const char * SharedTblName = "SAMPLE_APP.SampleAppTable"; - CFE_SB_MsgId_t TestMsgId = 0x9999; - CFE_MSG_FcnCode_t TestCmdCode = 0x9999; + CFE_SB_MsgId_t TestMsgId = CFE_TEST_CMD_MID; + CFE_MSG_FcnCode_t TestCmdCode = 0; uint32 TestParameter = 0; + + UtAssert_INT32_EQ(CFE_TBL_NotifyByMessage(CFE_TBL_BAD_TABLE_HANDLE, TestMsgId, TestCmdCode, TestParameter), + CFE_TBL_ERR_INVALID_HANDLE); + UtAssert_INT32_EQ(CFE_TBL_NotifyByMessage(CFE_FT_Global.TblHandle, TestMsgId, TestCmdCode, TestParameter), CFE_SUCCESS); diff --git a/modules/cfe_testcase/src/tbl_registration_test.c b/modules/cfe_testcase/src/tbl_registration_test.c index abe7160f6..ed300ece3 100644 --- a/modules/cfe_testcase/src/tbl_registration_test.c +++ b/modules/cfe_testcase/src/tbl_registration_test.c @@ -33,6 +33,7 @@ #include "cfe_test.h" #include "cfe_test_table.h" +#include "cfe_msgids.h" int32 CallbackFunc(void *TblPtr) { @@ -41,22 +42,38 @@ int32 CallbackFunc(void *TblPtr) void TestTableRegistration(void) { + char BadTblName[CFE_TBL_MAX_FULL_NAME_LEN + 2]; + CFE_TBL_Handle_t OtherHandle; + UtPrintf("Testing: CFE_TBL_Register, CFE_TBL_Unregister"); - char BadTblName[CFE_TBL_MAX_FULL_NAME_LEN + 2]; + BadTblName[CFE_TBL_MAX_FULL_NAME_LEN + 1] = '\0'; memset(BadTblName, 'a', sizeof(BadTblName) - 1); + /* invalid table handle arg */ + UtAssert_INT32_EQ( + CFE_TBL_Register(NULL, CFE_FT_Global.TblName, sizeof(TBL_TEST_Table_t), CFE_TBL_OPT_DEFAULT, &CallbackFunc), + CFE_TBL_BAD_ARGUMENT); + /* Successfully create table */ UtAssert_INT32_EQ(CFE_TBL_Register(&CFE_FT_Global.TblHandle, CFE_FT_Global.TblName, sizeof(TBL_TEST_Table_t), CFE_TBL_OPT_DEFAULT, &CallbackFunc), CFE_SUCCESS); - /* Duplicate table */ - UtAssert_INT32_EQ(CFE_TBL_Register(&CFE_FT_Global.TblHandle, CFE_FT_Global.TblName, sizeof(TBL_TEST_Table_t), + /* Duplicate table (should return the same handle) */ + UtAssert_INT32_EQ(CFE_TBL_Register(&OtherHandle, CFE_FT_Global.TblName, sizeof(TBL_TEST_Table_t), CFE_TBL_OPT_DEFAULT, &CallbackFunc), CFE_TBL_WARN_DUPLICATE); + UtAssert_INT32_EQ(OtherHandle, CFE_FT_Global.TblHandle); + + /* Duplicate table with different size */ + UtAssert_INT32_EQ(CFE_TBL_Register(&OtherHandle, CFE_FT_Global.TblName, sizeof(TBL_TEST_Table_t) / 2, + CFE_TBL_OPT_DEFAULT, &CallbackFunc), + CFE_TBL_ERR_DUPLICATE_DIFF_SIZE); + /* Unregister the table */ + UtAssert_INT32_EQ(CFE_TBL_Unregister(CFE_TBL_BAD_TABLE_HANDLE), CFE_TBL_ERR_INVALID_HANDLE); UtAssert_INT32_EQ(CFE_TBL_Unregister(CFE_FT_Global.TblHandle), CFE_SUCCESS); UtAssert_INT32_EQ(CFE_TBL_Unregister(CFE_FT_Global.TblHandle), CFE_TBL_ERR_INVALID_HANDLE); @@ -88,6 +105,13 @@ void TestTableRegistration(void) UtAssert_INT32_EQ(CFE_TBL_Register(&CFE_FT_Global.TblHandle, CFE_FT_Global.TblName, sizeof(TBL_TEST_Table_t), CFE_TBL_OPT_CRITICAL | CFE_TBL_OPT_USR_DEF_ADDR, NULL), CFE_TBL_ERR_INVALID_OPTIONS); +} + +void TestTableMaxLimits(void) +{ + CFE_TBL_Handle_t Handles[CFE_PLATFORM_TBL_MAX_NUM_HANDLES + 1]; + char TblName[CFE_TBL_MAX_FULL_NAME_LEN]; + uint32 numTblsCreated = 0; /* Track num created to unregister them all */ /* * Create the maximum number of tables @@ -95,28 +119,73 @@ void TestTableRegistration(void) * stop succeeding before it reaches the end of the loop * Check that after the loop no more tables can be created */ - CFE_TBL_Handle_t TblHandles[CFE_PLATFORM_TBL_MAX_NUM_TABLES]; - char TblName2[10]; - int numTblsCreated = 0; /* Track num created to unregister them all */ - for (int i = 0; i < CFE_PLATFORM_TBL_MAX_NUM_TABLES; i++) + while (numTblsCreated <= CFE_PLATFORM_TBL_MAX_NUM_HANDLES) { - sprintf(TblName2, "%d", i); - if (CFE_TBL_Register(&TblHandles[i], TblName2, sizeof(TBL_TEST_Table_t), CFE_TBL_OPT_DEFAULT, NULL) == - CFE_SUCCESS) + snprintf(TblName, sizeof(TblName), "Tbl%u", (unsigned int)numTblsCreated); + CFE_Assert_STATUS_STORE( + CFE_TBL_Register(&Handles[numTblsCreated], TblName, sizeof(TBL_TEST_Table_t), CFE_TBL_OPT_DEFAULT, NULL)); + if (CFE_Assert_STATUS_MAY_BE(CFE_TBL_ERR_REGISTRY_FULL)) { - numTblsCreated++; + break; } + if (!CFE_Assert_STATUS_MUST_BE(CFE_SUCCESS)) + { + break; + } + ++numTblsCreated; } - UtAssert_INT32_EQ(CFE_TBL_Register(&TblHandles[numTblsCreated], CFE_FT_Global.TblName, sizeof(TBL_TEST_Table_t), - CFE_TBL_OPT_DEFAULT, &CallbackFunc), - CFE_TBL_ERR_REGISTRY_FULL); - /* Unregister the tables */ - for (int i = 0; i < numTblsCreated; i++) + + if (!UtAssert_NONZERO(numTblsCreated)) { - if (CFE_TBL_Unregister(TblHandles[i]) != CFE_SUCCESS) + UtAssert_WARN("Table test cannot create any tables"); + return; + } + + UtAssert_UINT32_LT(numTblsCreated, CFE_PLATFORM_TBL_MAX_NUM_TABLES); + UtAssert_UINT32_LT(numTblsCreated, CFE_PLATFORM_TBL_MAX_NUM_HANDLES); + + /* Delete one table so the registry isn't full anymore */ + --numTblsCreated; + UtAssert_INT32_EQ(CFE_TBL_Unregister(Handles[numTblsCreated]), CFE_SUCCESS); + + if (!UtAssert_NONZERO(numTblsCreated)) + { + UtAssert_WARN("Table test cannot run CFE_TBL_Share max without at least one table"); + return; + } + + /* + * A shared table has a unique handle but not a unique entry in the registry. + * By calling CFE_TBL_Share it should consume handles but not registry entries + */ + snprintf(TblName, sizeof(TblName), "CFE_TEST_APP.Tbl%u", (unsigned int)0); + while (numTblsCreated <= CFE_PLATFORM_TBL_MAX_NUM_HANDLES) + { + CFE_Assert_STATUS_STORE(CFE_TBL_Share(&Handles[numTblsCreated], TblName)); + if (CFE_Assert_STATUS_MAY_BE(CFE_TBL_ERR_HANDLES_FULL)) { - UtAssert_Failed("Failed to unregister table number %d", i); + break; } + if (!CFE_Assert_STATUS_MUST_BE(CFE_SUCCESS)) + { + break; + } + ++numTblsCreated; + } + + UtAssert_UINT32_LT(numTblsCreated, CFE_PLATFORM_TBL_MAX_NUM_HANDLES); + + /* also confirm not able to register a new table, either */ + snprintf(TblName, sizeof(TblName), "Tbl%u", (unsigned int)numTblsCreated); + UtAssert_INT32_EQ( + CFE_TBL_Register(&Handles[numTblsCreated], TblName, sizeof(TBL_TEST_Table_t), CFE_TBL_OPT_DEFAULT, NULL), + CFE_TBL_ERR_HANDLES_FULL); + + /* Unregister all table handles */ + while (numTblsCreated > 0) + { + --numTblsCreated; + UtAssert_INT32_EQ(CFE_TBL_Unregister(Handles[numTblsCreated]), CFE_SUCCESS); } } @@ -126,13 +195,82 @@ void TestTableShare(void) CFE_TBL_Handle_t SharedTblHandle; const char * SharedTblName = "SAMPLE_APP.SampleAppTable"; const char * BadTblName = "SampleAppTable"; + + UtAssert_INT32_EQ(CFE_TBL_Share(NULL, SharedTblName), CFE_TBL_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_TBL_Share(&SharedTblHandle, SharedTblName), CFE_SUCCESS); UtAssert_INT32_EQ(CFE_TBL_Share(&SharedTblHandle, NULL), CFE_TBL_BAD_ARGUMENT); UtAssert_INT32_EQ(CFE_TBL_Share(&SharedTblHandle, BadTblName), CFE_TBL_ERR_INVALID_NAME); } +void TestTblNonAppContext(void) +{ + CFE_TBL_Handle_t Handle; + void * TblPtr; + + /* Attempt to register another table */ + UtAssert_INT32_EQ( + CFE_TBL_Register(&Handle, "OtherTable", sizeof(TBL_TEST_Table_t), CFE_TBL_OPT_DEFAULT, &CallbackFunc), + CFE_ES_ERR_RESOURCEID_NOT_VALID); + + /* Calling any other API (with a valid handle) should be rejected from this context */ + UtAssert_INT32_EQ(CFE_TBL_DumpToBuffer(CFE_FT_Global.TblHandle), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_TBL_GetAddress(&TblPtr, CFE_FT_Global.TblHandle), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_TBL_GetStatus(CFE_FT_Global.TblHandle), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_TBL_Load(CFE_FT_Global.TblHandle, CFE_TBL_SRC_FILE, "/cf/cfe_test_tbl.tbl"), + CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_TBL_Manage(CFE_FT_Global.TblHandle), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_TBL_Modified(CFE_FT_Global.TblHandle), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_TBL_NotifyByMessage(CFE_FT_Global.TblHandle, CFE_TEST_CMD_MID, 0, 0), + CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_TBL_ReleaseAddress(CFE_FT_Global.TblHandle), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_TBL_Share(&Handle, CFE_FT_Global.TblName), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_TBL_Update(CFE_FT_Global.TblHandle), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_TBL_Validate(CFE_FT_Global.TblHandle), CFE_ES_ERR_RESOURCEID_NOT_VALID); + + /* Attempt to unregister a table */ + UtAssert_INT32_EQ(CFE_TBL_Unregister(CFE_FT_Global.TblHandle), CFE_ES_ERR_RESOURCEID_NOT_VALID); +} + +void TestTableBadContext(void) +{ + uint32 RetryCount; + osal_id_t OtherTaskId; + OS_task_prop_t TaskProp; + + /* Create one (good) handle first from this task */ + UtAssert_INT32_EQ(CFE_TBL_Register(&CFE_FT_Global.TblHandle, CFE_FT_Global.TblName, sizeof(TBL_TEST_Table_t), + CFE_TBL_OPT_DEFAULT, &CallbackFunc), + CFE_SUCCESS); + + /* Create a separate task to run the tests, to confirm TBL context checks */ + UtAssert_INT32_EQ(OS_TaskCreate(&OtherTaskId, "NonCfe", TestTblNonAppContext, OSAL_TASK_STACK_ALLOCATE, 16384, + OSAL_PRIORITY_C(200), 0), + OS_SUCCESS); + + /* wait for task to exit itself */ + RetryCount = 0; + while (RetryCount < 20) + { + /* + * poll until OS_TaskGetInfo() returns an error, then the task has exited + */ + if (OS_TaskGetInfo(OtherTaskId, &TaskProp) != OS_SUCCESS) + { + break; + } + + OS_TaskDelay(100); + ++RetryCount; + } + + UtAssert_UINT32_LT(RetryCount, 20); + UtAssert_INT32_EQ(CFE_TBL_Unregister(CFE_FT_Global.TblHandle), CFE_SUCCESS); +} + void TBLRegistrationTestSetup(void) { UtTest_Add(TestTableRegistration, NULL, NULL, "Test Table Registration"); + UtTest_Add(TestTableMaxLimits, NULL, NULL, "Table Max Limits"); UtTest_Add(TestTableShare, NULL, NULL, "Test Table Sharing"); + UtTest_Add(TestTableBadContext, NULL, NULL, "Test Table Bad Context"); } diff --git a/modules/cfe_testcase/src/time_current_test.c b/modules/cfe_testcase/src/time_current_test.c index 901e6ca7c..71e297d14 100644 --- a/modules/cfe_testcase/src/time_current_test.c +++ b/modules/cfe_testcase/src/time_current_test.c @@ -32,6 +32,7 @@ */ #include "cfe_test.h" +#include "cfe_time_msg.h" bool TimeInRange(CFE_TIME_SysTime_t Time, CFE_TIME_SysTime_t Target, OS_time_t difference) { @@ -120,7 +121,38 @@ void TestGetTime(void) UtAssert_True(TimeInRange(MET, Buf, difference), "MET (%s) = METSubSeconds (%s)", timeBuf1, timeBuf2); } +void TestClock(void) +{ + UtPrintf("Testing: CFE_TIME_GetClockState, CFE_TIME_GetClockInfo"); + + CFE_TIME_ClockState_Enum_t state = CFE_TIME_GetClockState(); + + if (state >= 0) + { + UtAssert_BITMASK_SET(CFE_TIME_GetClockInfo(), CFE_TIME_FLAG_CLKSET); + + if (state == 0) + { + UtAssert_BITMASK_UNSET(CFE_TIME_GetClockInfo(), CFE_TIME_FLAG_FLYING); + } + else + { + UtAssert_BITMASK_SET(CFE_TIME_GetClockInfo(), CFE_TIME_FLAG_FLYING); + } + } + else + { + UtAssert_BITMASK_UNSET(CFE_TIME_GetClockInfo(), CFE_TIME_FLAG_CLKSET); + } + + UtAssert_BITMASK_SET(CFE_TIME_GetClockInfo(), CFE_TIME_FLAG_SRCINT); + UtAssert_BITMASK_SET(CFE_TIME_GetClockInfo(), CFE_TIME_FLAG_SIGPRI); + UtAssert_BITMASK_UNSET(CFE_TIME_GetClockInfo(), CFE_TIME_FLAG_REFERR); + UtAssert_BITMASK_UNSET(CFE_TIME_GetClockInfo(), CFE_TIME_FLAG_UNUSED); +} + void TimeCurrentTestSetup(void) { UtTest_Add(TestGetTime, NULL, NULL, "Test Current Time"); + UtTest_Add(TestClock, NULL, NULL, "Test Clock"); } diff --git a/modules/cfe_testcase/tables/cfe_test_tbl.c b/modules/cfe_testcase/tables/cfe_test_tbl.c index 81116b796..65fae385e 100644 --- a/modules/cfe_testcase/tables/cfe_test_tbl.c +++ b/modules/cfe_testcase/tables/cfe_test_tbl.c @@ -32,5 +32,11 @@ #include "cfe_tbl_filedef.h" #include "cfe_test_tbl.h" -TBL_TEST_Table_t TestTable = {1, 2}; +/* + * The test table data should contain some identifiable numeric values, + * so any issues with paritial loading/byteswapping are morely likely + * to be detected. + */ +TBL_TEST_Table_t TestTable = {0xf007, 0xba11}; + CFE_TBL_FILEDEF(TestTable, CFE_TEST_APP.TestTable, Table Test Table, cfe_test_tbl.tbl) \ No newline at end of file diff --git a/modules/core_api/fsw/inc/cfe_es.h b/modules/core_api/fsw/inc/cfe_es.h index 44e6e79c3..7e34b8308 100644 --- a/modules/core_api/fsw/inc/cfe_es.h +++ b/modules/core_api/fsw/inc/cfe_es.h @@ -420,7 +420,7 @@ bool CFE_ES_RunLoop(uint32 *RunStatus); ** ** \return Execution status, see \ref CFEReturnCodes ** \retval #CFE_SUCCESS State successfully achieved -** \retval #CFE_ES_OPERATION_TIMED_OUT Timeout was reached +** \retval #CFE_ES_OPERATION_TIMED_OUT \covtest Timeout was reached ** ** \sa #CFE_ES_RunLoop ** @@ -651,7 +651,7 @@ CFE_Status_t CFE_ES_GetAppName(char *AppName, CFE_ES_AppId_t AppId, size_t Buffe ** ** \param[in] LibId Library ID of Library whose name is being requested. ** -** \param[in] BufferLength The maximum number of characters, including the null terminator, that can be put +** \param[in] BufferLength The maximum number of characters @nonzero, including the null terminator, that can be put ** into the \c LibName buffer. This routine will truncate the name to this length, ** if necessary. ** @@ -903,8 +903,7 @@ CFE_Status_t CFE_ES_GetTaskName(char *TaskName, CFE_ES_TaskId_t TaskId, size_t B ** ** \return Execution status, see \ref CFEReturnCodes ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS -** \retval #CFE_ES_NOT_IMPLEMENTED \copybrief CFE_ES_NOT_IMPLEMENTED -** \retval #CFE_ES_ERR_CHILD_TASK_DELETE \copybrief CFE_ES_ERR_CHILD_TASK_DELETE +** \retval #CFE_ES_ERR_CHILD_TASK_DELETE \covtest \copybrief CFE_ES_ERR_CHILD_TASK_DELETE ** \retval #CFE_ES_ERR_CHILD_TASK_DELETE_MAIN_TASK \copybrief CFE_ES_ERR_CHILD_TASK_DELETE_MAIN_TASK ** \retval #CFE_ES_ERR_RESOURCEID_NOT_VALID \copybrief CFE_ES_ERR_RESOURCEID_NOT_VALID ** @@ -1072,7 +1071,7 @@ void CFE_ES_ProcessAsyncEvent(void); ** \retval #CFE_ES_CDS_INVALID_SIZE \copybrief CFE_ES_CDS_INVALID_SIZE ** \retval #CFE_ES_CDS_INVALID_NAME \copybrief CFE_ES_CDS_INVALID_NAME ** \retval #CFE_ES_BAD_ARGUMENT \copybrief CFE_ES_BAD_ARGUMENT -** \retval #CFE_ES_CDS_INVALID \copybrief CFE_ES_CDS_INVALID +** \retval #CFE_ES_CDS_INVALID \covtest \copybrief CFE_ES_CDS_INVALID ** ** \sa #CFE_ES_CopyToCDS, #CFE_ES_RestoreFromCDS ** @@ -1185,7 +1184,7 @@ CFE_Status_t CFE_ES_CopyToCDS(CFE_ES_CDSHandle_t Handle, const void *DataToCopy) ** \return Execution status, see \ref CFEReturnCodes ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS ** \retval #CFE_ES_ERR_RESOURCEID_NOT_VALID \copybrief CFE_ES_ERR_RESOURCEID_NOT_VALID -** \retval #CFE_ES_CDS_BLOCK_CRC_ERR \copybrief CFE_ES_CDS_BLOCK_CRC_ERR +** \retval #CFE_ES_CDS_BLOCK_CRC_ERR \covtest \copybrief CFE_ES_CDS_BLOCK_CRC_ERR ** \retval #CFE_ES_BAD_ARGUMENT \copybrief CFE_ES_BAD_ARGUMENT ** ** \sa #CFE_ES_RegisterCDS, #CFE_ES_CopyToCDS @@ -1309,7 +1308,7 @@ CFE_Status_t CFE_ES_PoolCreate(CFE_ES_MemHandle_t *PoolID, void *MemPtr, size_t ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS ** \retval #CFE_ES_BAD_ARGUMENT \copybrief CFE_ES_BAD_ARGUMENT ** \retval #CFE_ES_NO_RESOURCE_IDS_AVAILABLE \copybrief CFE_ES_NO_RESOURCE_IDS_AVAILABLE -** \retval #CFE_STATUS_EXTERNAL_RESOURCE_FAIL \copybrief CFE_STATUS_EXTERNAL_RESOURCE_FAIL +** \retval #CFE_STATUS_EXTERNAL_RESOURCE_FAIL \covtest \copybrief CFE_STATUS_EXTERNAL_RESOURCE_FAIL ** ** \sa #CFE_ES_PoolCreate, #CFE_ES_PoolCreateNoSem, #CFE_ES_GetPoolBuf, #CFE_ES_PutPoolBuf, #CFE_ES_GetMemPoolStats ** @@ -1356,7 +1355,7 @@ int32 CFE_ES_PoolDelete(CFE_ES_MemHandle_t PoolID); ** ** \param[in] Handle The handle to the memory pool as returned by #CFE_ES_PoolCreate or #CFE_ES_PoolCreateNoSem. ** -** \param[in] Size The size of the buffer requested @nonzero. NOTE: The size allocated may be larger. +** \param[in] Size The size of the buffer requested. NOTE: The size allocated may be larger. ** ** \return Bytes Allocated, or error code \ref CFEReturnCodes ** \retval #CFE_ES_ERR_RESOURCEID_NOT_VALID \copybrief CFE_ES_ERR_RESOURCEID_NOT_VALID diff --git a/modules/core_api/fsw/inc/cfe_fs.h b/modules/core_api/fsw/inc/cfe_fs.h index c23b5dafe..f3fa4b916 100644 --- a/modules/core_api/fsw/inc/cfe_fs.h +++ b/modules/core_api/fsw/inc/cfe_fs.h @@ -168,7 +168,7 @@ CFE_Status_t CFE_FS_WriteHeader(osal_id_t FileDes, CFE_FS_Header_t *Hdr); ** to be put into the file's Standard cFE File Header. ** ** \return Execution status, see \ref CFEReturnCodes, or OSAL status -** \retval #CFE_STATUS_EXTERNAL_RESOURCE_FAIL \copybrief CFE_STATUS_EXTERNAL_RESOURCE_FAIL +** \retval #CFE_STATUS_EXTERNAL_RESOURCE_FAIL \covtest \copybrief CFE_STATUS_EXTERNAL_RESOURCE_FAIL ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS ** ** \note This function invokes OSAL API routines and the current implementation may return diff --git a/modules/core_api/fsw/inc/cfe_sb.h b/modules/core_api/fsw/inc/cfe_sb.h index 6f11d8029..53c80348b 100644 --- a/modules/core_api/fsw/inc/cfe_sb.h +++ b/modules/core_api/fsw/inc/cfe_sb.h @@ -259,10 +259,10 @@ CFE_Status_t CFE_SB_GetPipeIdByName(CFE_SB_PipeId_t *PipeIdPtr, const char *Pipe ** ** \return Execution status, see \ref CFEReturnCodes ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS -** \retval #CFE_SB_MAX_MSGS_MET \copybrief CFE_SB_MAX_MSGS_MET +** \retval #CFE_SB_MAX_MSGS_MET \covtest \copybrief CFE_SB_MAX_MSGS_MET ** \retval #CFE_SB_MAX_DESTS_MET \copybrief CFE_SB_MAX_DESTS_MET ** \retval #CFE_SB_BAD_ARGUMENT \copybrief CFE_SB_BAD_ARGUMENT -** \retval #CFE_SB_BUF_ALOC_ERR \copybrief CFE_SB_BUF_ALOC_ERR +** \retval #CFE_SB_BUF_ALOC_ERR \covtest \copybrief CFE_SB_BUF_ALOC_ERR ** ** \sa #CFE_SB_Subscribe, #CFE_SB_SubscribeLocal, #CFE_SB_Unsubscribe, #CFE_SB_UnsubscribeLocal **/ @@ -294,10 +294,10 @@ CFE_Status_t CFE_SB_SubscribeEx(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeId, CF ** ** \return Execution status, see \ref CFEReturnCodes ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS -** \retval #CFE_SB_MAX_MSGS_MET \copybrief CFE_SB_MAX_MSGS_MET +** \retval #CFE_SB_MAX_MSGS_MET \covtest \copybrief CFE_SB_MAX_MSGS_MET ** \retval #CFE_SB_MAX_DESTS_MET \copybrief CFE_SB_MAX_DESTS_MET ** \retval #CFE_SB_BAD_ARGUMENT \copybrief CFE_SB_BAD_ARGUMENT -** \retval #CFE_SB_BUF_ALOC_ERR \copybrief CFE_SB_BUF_ALOC_ERR +** \retval #CFE_SB_BUF_ALOC_ERR \covtest \copybrief CFE_SB_BUF_ALOC_ERR ** ** \sa #CFE_SB_SubscribeEx, #CFE_SB_SubscribeLocal, #CFE_SB_Unsubscribe, #CFE_SB_UnsubscribeLocal **/ @@ -329,10 +329,10 @@ CFE_Status_t CFE_SB_Subscribe(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeId); ** ** \return Execution status, see \ref CFEReturnCodes ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS -** \retval #CFE_SB_MAX_MSGS_MET \copybrief CFE_SB_MAX_MSGS_MET +** \retval #CFE_SB_MAX_MSGS_MET \covtest \copybrief CFE_SB_MAX_MSGS_MET ** \retval #CFE_SB_MAX_DESTS_MET \copybrief CFE_SB_MAX_DESTS_MET ** \retval #CFE_SB_BAD_ARGUMENT \copybrief CFE_SB_BAD_ARGUMENT -** \retval #CFE_SB_BUF_ALOC_ERR \copybrief CFE_SB_BUF_ALOC_ERR +** \retval #CFE_SB_BUF_ALOC_ERR \covtest \copybrief CFE_SB_BUF_ALOC_ERR ** ** \sa #CFE_SB_Subscribe, #CFE_SB_SubscribeEx, #CFE_SB_Unsubscribe, #CFE_SB_UnsubscribeLocal **/ @@ -357,7 +357,7 @@ CFE_Status_t CFE_SB_SubscribeLocal(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeId, ** ** \return Execution status, see \ref CFEReturnCodes ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS -** \retval #CFE_SB_INTERNAL_ERR \copybrief CFE_SB_INTERNAL_ERR +** \retval #CFE_SB_BAD_ARGUMENT \copybrief CFE_SB_BAD_ARGUMENT ** ** \sa #CFE_SB_Subscribe, #CFE_SB_SubscribeEx, #CFE_SB_SubscribeLocal, #CFE_SB_UnsubscribeLocal **/ @@ -383,7 +383,7 @@ CFE_Status_t CFE_SB_Unsubscribe(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeId); ** ** \return Execution status, see \ref CFEReturnCodes ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS -** \retval #CFE_SB_INTERNAL_ERR \copybrief CFE_SB_INTERNAL_ERR +** \retval #CFE_SB_BAD_ARGUMENT \copybrief CFE_SB_BAD_ARGUMENT ** ** \sa #CFE_SB_Subscribe, #CFE_SB_SubscribeEx, #CFE_SB_SubscribeLocal, #CFE_SB_Unsubscribe **/ @@ -421,7 +421,7 @@ CFE_Status_t CFE_SB_UnsubscribeLocal(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeI ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS ** \retval #CFE_SB_BAD_ARGUMENT \copybrief CFE_SB_BAD_ARGUMENT ** \retval #CFE_SB_MSG_TOO_BIG \copybrief CFE_SB_MSG_TOO_BIG -** \retval #CFE_SB_BUF_ALOC_ERR \copybrief CFE_SB_BUF_ALOC_ERR +** \retval #CFE_SB_BUF_ALOC_ERR \covtest \copybrief CFE_SB_BUF_ALOC_ERR **/ CFE_Status_t CFE_SB_TransmitMsg(const CFE_MSG_Message_t *MsgPtr, bool IncrementSequenceCount); @@ -461,7 +461,7 @@ CFE_Status_t CFE_SB_TransmitMsg(const CFE_MSG_Message_t *MsgPtr, bool IncrementS ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS ** \retval #CFE_SB_BAD_ARGUMENT \copybrief CFE_SB_BAD_ARGUMENT ** \retval #CFE_SB_TIME_OUT \copybrief CFE_SB_TIME_OUT -** \retval #CFE_SB_PIPE_RD_ERR \copybrief CFE_SB_PIPE_RD_ERR +** \retval #CFE_SB_PIPE_RD_ERR \covtest \copybrief CFE_SB_PIPE_RD_ERR ** \retval #CFE_SB_NO_MESSAGE \copybrief CFE_SB_NO_MESSAGE **/ CFE_Status_t CFE_SB_ReceiveBuffer(CFE_SB_Buffer_t **BufPtr, CFE_SB_PipeId_t PipeId, int32 TimeOut); @@ -717,9 +717,9 @@ size_t CFE_SB_GetUserDataLength(const CFE_MSG_Message_t *MsgPtr); ** truncated, but it will still be null terminated. ** ** \param[out] DestStringPtr Pointer to destination buffer @nonnull -** \param[in] SourceStringPtr Pointer to source buffer (component of SB message definition) @nonnull +** \param[in] SourceStringPtr Pointer to source buffer (component of SB message definition) ** \param[in] DefaultString Default string to use if source is empty -** \param[in] DestMaxSize Size of destination storage buffer (must be at least 2) +** \param[in] DestMaxSize Size of destination storage buffer @nonzero ** \param[in] SourceMaxSize Size of source buffer as defined by the message definition ** ** \return Number of characters copied or error code, see \ref CFEReturnCodes diff --git a/modules/core_api/fsw/inc/cfe_tbl.h b/modules/core_api/fsw/inc/cfe_tbl.h index 277c62984..0026e1bf5 100644 --- a/modules/core_api/fsw/inc/cfe_tbl.h +++ b/modules/core_api/fsw/inc/cfe_tbl.h @@ -303,21 +303,22 @@ CFE_Status_t CFE_TBL_Unregister(CFE_TBL_Handle_t TblHandle); ** ** \return Execution status, see \ref CFEReturnCodes ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS -** \retval #CFE_TBL_WARN_SHORT_FILE \copybrief CFE_TBL_WARN_SHORT_FILE -** \retval #CFE_TBL_WARN_PARTIAL_LOAD \copybrief CFE_TBL_WARN_PARTIAL_LOAD ** \retval #CFE_ES_ERR_RESOURCEID_NOT_VALID \copybrief CFE_ES_ERR_RESOURCEID_NOT_VALID ** \retval #CFE_TBL_ERR_NO_ACCESS \copybrief CFE_TBL_ERR_NO_ACCESS ** \retval #CFE_TBL_ERR_INVALID_HANDLE \copybrief CFE_TBL_ERR_INVALID_HANDLE ** \retval #CFE_TBL_ERR_DUMP_ONLY \copybrief CFE_TBL_ERR_DUMP_ONLY ** \retval #CFE_TBL_ERR_ILLEGAL_SRC_TYPE \copybrief CFE_TBL_ERR_ILLEGAL_SRC_TYPE ** \retval #CFE_TBL_ERR_LOAD_IN_PROGRESS \copybrief CFE_TBL_ERR_LOAD_IN_PROGRESS +** \retval #CFE_TBL_ERR_LOAD_INCOMPLETE \copybrief CFE_TBL_ERR_LOAD_INCOMPLETE ** \retval #CFE_TBL_ERR_NO_BUFFER_AVAIL \copybrief CFE_TBL_ERR_NO_BUFFER_AVAIL ** \retval #CFE_TBL_ERR_ACCESS \copybrief CFE_TBL_ERR_ACCESS ** \retval #CFE_TBL_ERR_FILE_TOO_LARGE \copybrief CFE_TBL_ERR_FILE_TOO_LARGE ** \retval #CFE_TBL_ERR_BAD_CONTENT_ID \copybrief CFE_TBL_ERR_BAD_CONTENT_ID +** \retval #CFE_TBL_ERR_BAD_SUBTYPE_ID \copybrief CFE_TBL_ERR_BAD_SUBTYPE_ID +** \retval #CFE_TBL_ERR_NO_STD_HEADER \copybrief CFE_TBL_ERR_NO_STD_HEADER +** \retval #CFE_TBL_ERR_NO_TBL_HEADER \copybrief CFE_TBL_ERR_NO_TBL_HEADER ** \retval #CFE_TBL_ERR_PARTIAL_LOAD \copybrief CFE_TBL_ERR_PARTIAL_LOAD ** \retval #CFE_TBL_BAD_ARGUMENT \copybrief CFE_TBL_BAD_ARGUMENT -** \retval #CFE_TBL_WARN_PARTIAL_LOAD \copybrief CFE_TBL_WARN_PARTIAL_LOAD ** ** \sa #CFE_TBL_Update, #CFE_TBL_Validate, #CFE_TBL_Manage ** diff --git a/modules/core_api/fsw/inc/cfe_version.h b/modules/core_api/fsw/inc/cfe_version.h index cb02cfc46..6e6100cad 100644 --- a/modules/core_api/fsw/inc/cfe_version.h +++ b/modules/core_api/fsw/inc/cfe_version.h @@ -28,7 +28,7 @@ #define CFE_VERSION_H /* Development Build Macro Definitions */ -#define CFE_BUILD_NUMBER 933 /**< @brief Development: Number of development commits since baseline */ +#define CFE_BUILD_NUMBER 980 /**< @brief Development: Number of development commits since baseline */ #define CFE_BUILD_BASELINE "v6.8.0-rc1" /**< @brief Development: Reference git tag for build number */ /* Version Macro Definitions updated for official releases only */ diff --git a/modules/evs/ut-coverage/evs_UT.c b/modules/evs/ut-coverage/evs_UT.c index d3a476d5d..380c493c7 100644 --- a/modules/evs/ut-coverage/evs_UT.c +++ b/modules/evs/ut-coverage/evs_UT.c @@ -234,6 +234,11 @@ void Test_Init(void) CFE_EVS_EarlyInit(); CFE_UtAssert_SYSLOG(EVS_SYSLOG_MSGS[4]); + /* Task main with init failure */ + UT_InitData(); + UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetAppID), 1, -1); + UtAssert_VOIDCALL(CFE_EVS_TaskMain()); + /* Test TaskMain with a command pipe read failure due to an * invalid command packet */ @@ -365,6 +370,7 @@ void Test_Init(void) void Test_IllegalAppID(void) { CFE_TIME_SysTime_t time = {0, 0}; + CFE_ES_AppId_t AppID; UtPrintf("Begin Test Illegal App ID"); @@ -375,6 +381,11 @@ void Test_IllegalAppID(void) /* Test registering an event using an illegal application ID */ UtAssert_INT32_EQ(CFE_EVS_Register(NULL, 0, 0), CFE_EVS_APP_ILLEGAL_APP_ID); + /* Test sending events with a NULL spec */ + UtAssert_INT32_EQ(CFE_EVS_SendEvent(0, 0, NULL), CFE_EVS_INVALID_PARAMETER); + UtAssert_INT32_EQ(CFE_EVS_SendEventWithAppID(0, 0, CFE_ES_APPID_UNDEFINED, NULL), CFE_EVS_INVALID_PARAMETER); + UtAssert_INT32_EQ(CFE_EVS_SendTimedEvent(time, 0, 0, NULL), CFE_EVS_INVALID_PARAMETER); + /* Test sending an event using an illegal application ID */ UT_InitData(); UT_SetDefaultReturnValue(UT_KEY(CFE_ES_AppID_ToIndex), CFE_ES_ERR_RESOURCEID_NOT_VALID); @@ -409,6 +420,11 @@ void Test_IllegalAppID(void) UT_InitData(); UT_SetDefaultReturnValue(UT_KEY(CFE_ES_AppID_ToIndex), CFE_ES_ERR_RESOURCEID_NOT_VALID); UtAssert_INT32_EQ(CFE_EVS_CleanUpApp(CFE_ES_APPID_UNDEFINED), CFE_EVS_APP_ILLEGAL_APP_ID); + + /* Test with out of range AppID */ + UT_InitData(); + AppID = CFE_ES_APPID_C(CFE_ResourceId_FromInteger(CFE_PLATFORM_ES_MAX_APPLICATIONS)); + UtAssert_INT32_EQ(CFE_EVS_SendEventWithAppID(0, 0, AppID, "NULL"), CFE_EVS_APP_ILLEGAL_APP_ID); } /* @@ -515,27 +531,42 @@ void Test_FilterRegistration(void) CFE_UtAssert_SUCCESS(CFE_EVS_Register(filter, CFE_PLATFORM_EVS_MAX_EVENT_FILTERS + 1, CFE_EVS_EventFilter_BINARY)); + CFE_EVS_Global.EVS_TlmPkt.Payload.MessageSendCounter = 0; + /* Send 1st information message, should get through */ UT_InitData(); CFE_UtAssert_SUCCESS(CFE_EVS_SendEvent(0, CFE_EVS_EventType_INFORMATION, "OK")); + UtAssert_UINT32_EQ(CFE_EVS_Global.EVS_TlmPkt.Payload.MessageSendCounter, 1); + UtAssert_INT32_EQ(UT_GetStubCount(UT_KEY(CFE_SB_TransmitMsg)), 1); /* Send 2nd information message, should be filtered */ UT_InitData(); CFE_UtAssert_SUCCESS(CFE_EVS_SendEvent(0, CFE_EVS_EventType_INFORMATION, "FAILED")); + UtAssert_UINT32_EQ(CFE_EVS_Global.EVS_TlmPkt.Payload.MessageSendCounter, 1); + UtAssert_INT32_EQ(UT_GetStubCount(UT_KEY(CFE_SB_TransmitMsg)), 0); /* Send last information message, which should cause filtering to lock */ UT_InitData(); FilterPtr = EVS_FindEventID(0, (EVS_BinFilter_t *)AppDataPtr->BinFilters); FilterPtr->Count = CFE_EVS_MAX_FILTER_COUNT - 1; CFE_UtAssert_SUCCESS(CFE_EVS_SendEvent(0, CFE_EVS_EventType_INFORMATION, "OK")); + UtAssert_UINT32_EQ(CFE_EVS_Global.EVS_TlmPkt.Payload.MessageSendCounter, 3); + UtAssert_INT32_EQ(UT_GetStubCount(UT_KEY(CFE_SB_TransmitMsg)), 2); + UtAssert_UINT32_EQ(FilterPtr->Count, CFE_EVS_MAX_FILTER_COUNT); /* Test that filter lock is applied */ UT_InitData(); CFE_UtAssert_SUCCESS(CFE_EVS_SendEvent(0, CFE_EVS_EventType_INFORMATION, "FAILED")); + UtAssert_UINT32_EQ(CFE_EVS_Global.EVS_TlmPkt.Payload.MessageSendCounter, 3); + UtAssert_INT32_EQ(UT_GetStubCount(UT_KEY(CFE_SB_TransmitMsg)), 0); + UtAssert_UINT32_EQ(FilterPtr->Count, CFE_EVS_MAX_FILTER_COUNT); /* Test that filter lock is (still) applied */ UT_InitData(); CFE_UtAssert_SUCCESS(CFE_EVS_SendEvent(0, CFE_EVS_EventType_INFORMATION, "FAILED")); + UtAssert_UINT32_EQ(CFE_EVS_Global.EVS_TlmPkt.Payload.MessageSendCounter, 3); + UtAssert_INT32_EQ(UT_GetStubCount(UT_KEY(CFE_SB_TransmitMsg)), 0); + UtAssert_UINT32_EQ(FilterPtr->Count, CFE_EVS_MAX_FILTER_COUNT); /* Return application to original state: re-register application */ UT_InitData(); @@ -717,6 +748,10 @@ void Test_Format(void) * the maximum allowed */ CFE_UtAssert_SUCCESS(CFE_EVS_SendTimedEvent(time, 0, CFE_EVS_EventType_INFORMATION, "%s", long_msg)); + + /* Force an invalid format and send for code coverage */ + CFE_EVS_Global.EVS_TlmPkt.Payload.MessageFormatMode = CFE_EVS_MsgFormat_LONG + 1; + CFE_UtAssert_SUCCESS(CFE_EVS_SendEvent(0, CFE_EVS_EventType_INFORMATION, "%s", long_msg)); } /* @@ -813,7 +848,8 @@ void Test_Ports(void) void Test_Logging(void) { int i; - uint32 resetAreaSize = 0; + uint32 resetAreaSize = 0; + uint16 LogOverflowCounterExpected = 1; char tmpString[100]; union { @@ -857,6 +893,7 @@ void Test_Logging(void) /* Test overfilling the log in discard mode */ UT_InitData(); + UtAssert_VOIDCALL(EVS_ClearLog()); /* Ensure log is filled, then add one more, implicitly testing * EVS_AddLog @@ -870,15 +907,18 @@ void Test_Logging(void) CFE_EVS_SendEvent(0, CFE_EVS_EventType_INFORMATION, "Log overfill event discard"); UtAssert_BOOL_TRUE(CFE_EVS_Global.EVS_LogPtr->LogFullFlag); UtAssert_UINT32_EQ(CFE_EVS_Global.EVS_LogPtr->LogMode, CFE_EVS_LogMode_DISCARD); + UtAssert_UINT32_EQ(CFE_EVS_Global.EVS_LogPtr->LogOverflowCounter, LogOverflowCounterExpected); /* Test setting the logging mode to overwrite */ UT_InitData(); CmdBuf.modecmd.Payload.LogMode = CFE_EVS_LogMode_OVERWRITE; UT_EVS_DoDispatchCheckEvents(&CmdBuf.modecmd, sizeof(CmdBuf.modecmd), UT_TPID_CFE_EVS_CMD_SET_LOG_MODE_CC, &UT_EVS_EventBuf); + LogOverflowCounterExpected = CFE_EVS_Global.EVS_LogPtr->LogOverflowCounter + 1; CFE_EVS_SendEvent(0, CFE_EVS_EventType_INFORMATION, "Log overfill event overwrite"); UtAssert_BOOL_TRUE(CFE_EVS_Global.EVS_LogPtr->LogFullFlag); UtAssert_UINT32_EQ(CFE_EVS_Global.EVS_LogPtr->LogMode, CFE_EVS_LogMode_OVERWRITE); + UtAssert_UINT32_EQ(CFE_EVS_Global.EVS_LogPtr->LogOverflowCounter, LogOverflowCounterExpected); /* Test sending a no op command */ UT_InitData(); @@ -891,6 +931,7 @@ void Test_Logging(void) CFE_EVS_Global.EVS_TlmPkt.Payload.LogEnabled = true; UT_EVS_DoDispatchCheckEvents(&CmdBuf.cmd, sizeof(CmdBuf.cmd), UT_TPID_CFE_EVS_CMD_CLEAR_LOG_CC, &UT_EVS_EventBuf); UtAssert_BOOL_FALSE(CFE_EVS_Global.EVS_LogPtr->LogFullFlag); + UtAssert_UINT32_EQ(CFE_EVS_Global.EVS_LogPtr->LogOverflowCounter, 0); /* Test setting the logging mode to overwrite */ UT_InitData(); @@ -1786,7 +1827,9 @@ void Test_Misc(void) char msg[CFE_MISSION_EVS_MAX_MESSAGE_LENGTH + 2]; UT_SoftwareBusSnapshot_Entry_t HK_SnapshotData = {.MsgId = CFE_SB_MSGID_WRAP_VALUE(CFE_EVS_HK_TLM_MID)}; - EVS_GetCurrentContext(&AppDataPtr, &AppID); + /* Cover null cases for EVS_GetCurrentContext */ + EVS_GetCurrentContext(NULL, &AppID); + EVS_GetCurrentContext(&AppDataPtr, NULL); UtPrintf("Begin Test Miscellaneous"); @@ -1877,4 +1920,13 @@ void Test_Misc(void) AppDataPtr->EventTypesActiveFlag |= CFE_EVS_INFORMATION_BIT; EVS_SendEvent(0, CFE_EVS_EventType_INFORMATION, msg); UtAssert_UINT32_EQ(CFE_EVS_Global.EVS_TlmPkt.Payload.MessageTruncCounter, 1); + + /* Use all AppData and report housekeeping to get branch coverage */ + UT_InitData(); + for (i = 0; i < sizeof(CFE_EVS_Global.AppData) / sizeof(CFE_EVS_Global.AppData[0]); i++) + { + /* Doesn't matter here that AppID is all the same... */ + EVS_AppDataSetUsed(&CFE_EVS_Global.AppData[i], AppID); + } + UtAssert_UINT32_EQ(CFE_EVS_ReportHousekeepingCmd(NULL), CFE_STATUS_NO_COUNTER_INCREMENT); } diff --git a/modules/fs/ut-coverage/fs_UT.c b/modules/fs/ut-coverage/fs_UT.c index b670d1bcc..a0508955f 100644 --- a/modules/fs/ut-coverage/fs_UT.c +++ b/modules/fs/ut-coverage/fs_UT.c @@ -20,7 +20,7 @@ /* ** File: -** fss_UT.c +** fs_UT.c ** ** Purpose: ** File Services unit test @@ -119,12 +119,15 @@ void Test_CFE_FS_ReadHeader(void) UT_SetDefaultReturnValue(UT_KEY(OS_lseek), OS_ERROR); UtAssert_INT32_EQ(CFE_FS_ReadHeader(&Hdr, FileDes), CFE_STATUS_EXTERNAL_RESOURCE_FAIL); - /* Test successfully reading the header */ + /* Test reading header with OS_read failure */ UT_InitData(); - UT_SetDeferredRetcode(UT_KEY(OS_lseek), 1, OS_SUCCESS); UT_SetDefaultReturnValue(UT_KEY(OS_read), OS_ERROR); UtAssert_INT32_EQ(CFE_FS_ReadHeader(&Hdr, FileDes), CFE_STATUS_EXTERNAL_RESOURCE_FAIL); + /* Test successfully reading the header */ + UT_InitData(); + UtAssert_INT32_EQ(CFE_FS_ReadHeader(&Hdr, FileDes), sizeof(Hdr)); + /* Test calling with NULL pointer argument */ UtAssert_INT32_EQ(CFE_FS_ReadHeader(NULL, FileDes), CFE_FS_BAD_ARGUMENT); } diff --git a/modules/msg/ut-coverage/test_cfe_msg_msgid_shared.c b/modules/msg/ut-coverage/test_cfe_msg_msgid_shared.c index c6ae6fede..759409a3c 100644 --- a/modules/msg/ut-coverage/test_cfe_msg_msgid_shared.c +++ b/modules/msg/ut-coverage/test_cfe_msg_msgid_shared.c @@ -45,6 +45,9 @@ void Test_MSG_GetTypeFromMsgId(void) UtAssert_INT32_EQ(CFE_MSG_GetTypeFromMsgId(msgid, NULL), CFE_MSG_BAD_ARGUMENT); UtAssert_INT32_EQ(Test_MSG_NotZero(&msg), 0); + UtPrintf("Bad parameter tests, Invalid message ID"); + UtAssert_INT32_EQ(CFE_MSG_GetTypeFromMsgId(CFE_SB_INVALID_MSG_ID, &actual), CFE_MSG_BAD_ARGUMENT); + UtPrintf("Set to all F's, test cmd and tlm"); memset(&msg, 0xFF, sizeof(msg)); CFE_UtAssert_SUCCESS(CFE_MSG_SetMsgId(&msg, CFE_SB_ValueToMsgId(CFE_PLATFORM_SB_HIGHEST_VALID_MSGID))); diff --git a/modules/resourceid/ut-coverage/test_cfe_resourceid.c b/modules/resourceid/ut-coverage/test_cfe_resourceid.c index ec77dd709..0da99bd23 100644 --- a/modules/resourceid/ut-coverage/test_cfe_resourceid.c +++ b/modules/resourceid/ut-coverage/test_cfe_resourceid.c @@ -163,6 +163,11 @@ void TestResourceID(void) UtAssert_True(TestIndex == RefIndex, "ID index after search: id=%lx, expected=%lu, got=%lu", CFE_ResourceId_ToInteger(Id), (unsigned long)RefIndex, (unsigned long)TestIndex); + /* For valid Id check other invalid inputs */ + UtAssert_INT32_EQ(CFE_ResourceId_ToIndex(Id, RefBase, 1, NULL), CFE_ES_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_ResourceId_ToIndex(Id, RefBase, 0, &TestIndex), CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_ResourceId_ToIndex(Id, ~RefBase, 1, &TestIndex), CFE_ES_ERR_RESOURCEID_NOT_VALID); + /* Validate off-nominal inputs */ Id = CFE_ResourceId_FindNext(CFE_RESOURCEID_UNDEFINED, 0, UT_ResourceId_CheckIdSlotUsed); UtAssert_True(CFE_ResourceId_Equal(Id, CFE_RESOURCEID_UNDEFINED), "CFE_ResourceId_FindNext() bad input: id=%lx", @@ -171,10 +176,6 @@ void TestResourceID(void) Id = CFE_ResourceId_FindNext(LastId, 0, NULL); UtAssert_True(CFE_ResourceId_Equal(Id, CFE_RESOURCEID_UNDEFINED), "CFE_ResourceId_FindNext() bad input: id=%lx", CFE_ResourceId_ToInteger(Id)); - - UtAssert_INT32_EQ(CFE_ResourceId_ToIndex(Id, RefBase, 1, NULL), CFE_ES_BAD_ARGUMENT); - UtAssert_INT32_EQ(CFE_ResourceId_ToIndex(Id, RefBase, 0, &TestIndex), CFE_ES_ERR_RESOURCEID_NOT_VALID); - UtAssert_INT32_EQ(CFE_ResourceId_ToIndex(Id, ~RefBase, 1, &TestIndex), CFE_ES_ERR_RESOURCEID_NOT_VALID); } void UtTest_Setup(void) diff --git a/modules/sbr/ut-coverage/test_cfe_sbr_route_unsorted.c b/modules/sbr/ut-coverage/test_cfe_sbr_route_unsorted.c index c16ddecb4..45a7286f5 100644 --- a/modules/sbr/ut-coverage/test_cfe_sbr_route_unsorted.c +++ b/modules/sbr/ut-coverage/test_cfe_sbr_route_unsorted.c @@ -131,6 +131,8 @@ void Test_SBR_Route_Unsort_GetSet(void) UtAssert_BOOL_TRUE(CFE_SB_MsgId_Equal(CFE_SBR_GetMsgId(routeid[i]), CFE_SB_INVALID_MSG_ID)); UtAssert_ADDRESS_EQ(CFE_SBR_GetDestListHeadPtr(routeid[i]), NULL); UtAssert_INT32_EQ(CFE_SBR_GetSequenceCounter(routeid[i]), 0); + UtAssert_VOIDCALL(CFE_SBR_SetDestListHeadPtr(routeid[i], NULL)); + UtAssert_VOIDCALL(CFE_SBR_IncrementSequenceCounter(routeid[i])); } /* diff --git a/modules/tbl/ut-coverage/tbl_UT.c b/modules/tbl/ut-coverage/tbl_UT.c index f59974be1..0f3bc1f7c 100644 --- a/modules/tbl/ut-coverage/tbl_UT.c +++ b/modules/tbl/ut-coverage/tbl_UT.c @@ -74,6 +74,7 @@ void * Tbl1Ptr = NULL; void * Tbl2Ptr = NULL; void **ArrayOfPtrsToTblPtrs[2]; +static const UT_TaskPipeDispatchId_t UT_TPID_CFE_TBL_MSG_HK = {.MsgId = CFE_SB_MSGID_WRAP_VALUE(CFE_TBL_SEND_HK_MID)}; static const UT_TaskPipeDispatchId_t UT_TPID_CFE_TBL_CMD_NOOP_CC = {.MsgId = CFE_SB_MSGID_WRAP_VALUE(CFE_TBL_CMD_MID), .CommandCode = CFE_TBL_NOOP_CC}; static const UT_TaskPipeDispatchId_t UT_TPID_CFE_TBL_CMD_RESET_COUNTERS_CC = { @@ -244,10 +245,20 @@ void Test_CFE_TBL_TaskInit(void) UT_SetDataBuffer(UT_KEY(CFE_ES_ExitApp), &ExitCode, sizeof(ExitCode), false); UT_SetDataBuffer(UT_KEY(CFE_MSG_GetMsgId), &MsgId, sizeof(MsgId), false); UT_SetDataBuffer(UT_KEY(CFE_MSG_GetFcnCode), &FcnCode, sizeof(FcnCode), false); - CFE_TBL_TaskMain(); + UtAssert_VOIDCALL(CFE_TBL_TaskMain()); UtAssert_INT32_EQ(ExitCode, CFE_ES_RunStatus_CORE_APP_RUNTIME_ERROR); UtAssert_STUB_COUNT(CFE_ES_ExitApp, 1); + /* Main task initialization failure */ + UT_InitData(); + ExitCode = 0; + UT_SetDataBuffer(UT_KEY(CFE_ES_ExitApp), &ExitCode, sizeof(ExitCode), false); + UT_SetDeferredRetcode(UT_KEY(CFE_EVS_Register), 1, -1); + UtAssert_VOIDCALL(CFE_TBL_TaskMain()); + UtAssert_INT32_EQ(ExitCode, CFE_ES_RunStatus_CORE_APP_INIT_ERROR); + /* Since stub doesn't actually cause an exit, will get called twice */ + UtAssert_STUB_COUNT(CFE_ES_ExitApp, 2); + /* Test successful table services core application initialization */ UT_InitData(); CFE_UtAssert_SUCCESS(CFE_TBL_TaskInit()); @@ -307,7 +318,6 @@ void Test_CFE_TBL_TaskInit(void) CFE_UtAssert_EVENTSENT(CFE_TBL_CC1_ERR_EID); /* Test command pipe messages handler response to other errors */ - /* Test command pipe messages handler response to "message type" message */ UT_InitData(); CFE_TBL_Global.CommandCounter = 0; CFE_TBL_Global.CommandErrorCounter = 0; @@ -316,6 +326,14 @@ void Test_CFE_TBL_TaskInit(void) UtAssert_ZERO(CFE_TBL_Global.CommandCounter); UtAssert_ZERO(CFE_TBL_Global.CommandErrorCounter); + /* Test command pipe messages handler response to "message type" message */ + UT_InitData(); + CFE_TBL_Global.CommandCounter = 0; + CFE_TBL_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TBL_TaskPipe, &CmdBuf.Msg, sizeof(CmdBuf.NoArgsCmd), UT_TPID_CFE_TBL_MSG_HK); + UtAssert_ZERO(CFE_TBL_Global.CommandCounter); + UtAssert_ZERO(CFE_TBL_Global.CommandErrorCounter); + /* Test command pipe messages handler response to "command type" message */ UT_InitData(); UT_CallTaskPipe(CFE_TBL_TaskPipe, &CmdBuf.Msg, sizeof(CmdBuf.NoArgsCmd), UT_TPID_CFE_TBL_CMD_RESET_COUNTERS_CC); @@ -945,8 +963,23 @@ void Test_CFE_TBL_DumpRegCmd(void) UtAssert_NOT_NULL(LocalBuf); UtAssert_NONZERO(LocalSize); + /* Same but not double buffered */ + UT_InitData(); + CFE_TBL_Global.Registry[0].OwnerAppId = AppID; + CFE_TBL_Global.Registry[0].HeadOfAccessList = CFE_TBL_END_OF_LIST; + CFE_TBL_Global.Registry[1].OwnerAppId = CFE_TBL_NOT_OWNED; + CFE_TBL_Global.Registry[0].LoadInProgress = CFE_TBL_NO_LOAD_IN_PROGRESS + 1; + CFE_TBL_Global.Registry[0].DoubleBuffered = false; + LocalBuf = NULL; + LocalSize = 0; + UtAssert_BOOL_FALSE(CFE_TBL_DumpRegistryGetter(&CFE_TBL_Global.RegDumpState, 0, &LocalBuf, &LocalSize)); + UtAssert_NOT_NULL(LocalBuf); + UtAssert_NONZERO(LocalSize); + + /* Hit last entry, no load in progress */ CFE_TBL_Global.Registry[CFE_PLATFORM_TBL_MAX_NUM_TABLES - 1].OwnerAppId = CFE_TBL_NOT_OWNED; CFE_TBL_Global.Registry[CFE_PLATFORM_TBL_MAX_NUM_TABLES - 1].HeadOfAccessList = 2; + CFE_TBL_Global.Registry[CFE_PLATFORM_TBL_MAX_NUM_TABLES - 1].LoadInProgress = CFE_TBL_NO_LOAD_IN_PROGRESS; CFE_TBL_Global.Handles[2].NextLink = CFE_TBL_END_OF_LIST; LocalBuf = NULL; LocalSize = 0; @@ -960,6 +993,15 @@ void Test_CFE_TBL_DumpRegCmd(void) &LocalBuf, &LocalSize)); UtAssert_NULL(LocalBuf); UtAssert_ZERO(LocalSize); + + /* Test empty registry */ + CFE_TBL_Global.Registry[0].OwnerAppId = CFE_TBL_NOT_OWNED; + CFE_TBL_Global.Registry[0].HeadOfAccessList = CFE_TBL_END_OF_LIST; + LocalBuf = NULL; + LocalSize = 0; + UtAssert_BOOL_FALSE(CFE_TBL_DumpRegistryGetter(&CFE_TBL_Global.RegDumpState, 0, &LocalBuf, &LocalSize)); + UtAssert_NULL(LocalBuf); + UtAssert_ZERO(LocalSize); } /* @@ -1098,10 +1140,10 @@ void Test_CFE_TBL_DumpCmd(void) */ void Test_CFE_TBL_LoadCmd(void) { - int i, j; + int i; CFE_TBL_File_Hdr_t TblFileHeader; CFE_FS_Header_t StdFileHeader; - CFE_TBL_LoadBuff_t BufferPtr = CFE_TBL_Global.LoadBuffs[0]; + uint8 LoadBuffer[sizeof(UT_Table1_t)]; CFE_TBL_LoadCmd_t LoadCmd; CFE_ES_AppId_t AppID; @@ -1109,51 +1151,50 @@ void Test_CFE_TBL_LoadCmd(void) UtPrintf("Begin Test Load Command"); - StdFileHeader.SpacecraftID = CFE_PLATFORM_TBL_VALID_SCID_1; - StdFileHeader.ProcessorID = CFE_PLATFORM_TBL_VALID_PRID_1; + /* Clear all local structures */ + memset(&TblFileHeader, 0, sizeof(TblFileHeader)); + memset(&StdFileHeader, 0, sizeof(StdFileHeader)); + memset(&LoadCmd, 0, sizeof(LoadCmd)); + + /* Start with a cleared global (no tables registered) */ + memset(&CFE_TBL_Global, 0, sizeof(CFE_TBL_Global)); + + /* Set up the headers */ + strncpy(StdFileHeader.Description, "FS header description", sizeof(StdFileHeader.Description) - 1); + StdFileHeader.Description[sizeof(StdFileHeader.Description) - 1] = '\0'; + StdFileHeader.ContentType = CFE_FS_FILE_CONTENT_ID; + StdFileHeader.SubType = CFE_FS_SubType_TBL_IMG; + StdFileHeader.SpacecraftID = CFE_PLATFORM_TBL_VALID_SCID_1; + StdFileHeader.ProcessorID = CFE_PLATFORM_TBL_VALID_PRID_1; /* Test response to inability to open file */ UT_InitData(); - strncpy(LoadCmd.Payload.LoadFilename, "LoadFileName", sizeof(LoadCmd.Payload.LoadFilename) - 1); - LoadCmd.Payload.LoadFilename[sizeof(LoadCmd.Payload.LoadFilename) - 1] = '\0'; UT_SetDefaultReturnValue(UT_KEY(OS_OpenCreate), OS_ERROR); UtAssert_INT32_EQ(CFE_TBL_LoadCmd(&LoadCmd), CFE_TBL_INC_ERR_CTR); /* Test response to inability to find the table in the registry */ UT_InitData(); - - for (i = 0; i < CFE_PLATFORM_TBL_MAX_NUM_TABLES; i++) - { - CFE_TBL_Global.Registry[i].OwnerAppId = CFE_TBL_NOT_OWNED; - CFE_TBL_Global.Registry[i].LoadPending = false; - } - strncpy(TblFileHeader.TableName, CFE_TBL_Global.Registry[0].Name, sizeof(TblFileHeader.TableName) - 1); TblFileHeader.TableName[sizeof(TblFileHeader.TableName) - 1] = '\0'; - strncpy(StdFileHeader.Description, "FS header description", sizeof(StdFileHeader.Description) - 1); - StdFileHeader.Description[sizeof(StdFileHeader.Description) - 1] = '\0'; - StdFileHeader.ContentType = CFE_FS_FILE_CONTENT_ID; - StdFileHeader.SubType = CFE_FS_SubType_TBL_IMG; UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); UT_SetReadHeader(&StdFileHeader, sizeof(StdFileHeader)); UtAssert_INT32_EQ(CFE_TBL_LoadCmd(&LoadCmd), CFE_TBL_INC_ERR_CTR); + /* The rest of the tests will use registry 0, note empty name matches */ + CFE_TBL_Global.Registry[0].OwnerAppId = AppID; + /* Test attempt to load a dump only table */ UT_InitData(); - CFE_TBL_Global.Registry[0].OwnerAppId = AppID; UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); UT_SetReadHeader(&StdFileHeader, sizeof(StdFileHeader)); - CFE_TBL_Global.Registry[0].Size = sizeof(CFE_TBL_File_Hdr_t) + 1; CFE_TBL_Global.Registry[0].DumpOnly = true; UtAssert_INT32_EQ(CFE_TBL_LoadCmd(&LoadCmd), CFE_TBL_INC_ERR_CTR); + CFE_TBL_Global.Registry[0].DumpOnly = false; /* Test attempt to load a table with a load already pending */ UT_InitData(); - CFE_TBL_Global.Registry[0].OwnerAppId = AppID; UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); UT_SetReadHeader(&StdFileHeader, sizeof(StdFileHeader)); - CFE_TBL_Global.Registry[0].Size = sizeof(CFE_TBL_File_Hdr_t) + 1; - CFE_TBL_Global.Registry[0].DumpOnly = false; CFE_TBL_Global.Registry[0].LoadPending = true; UtAssert_INT32_EQ(CFE_TBL_LoadCmd(&LoadCmd), CFE_TBL_INC_ERR_CTR); CFE_TBL_Global.Registry[0].LoadPending = false; @@ -1161,59 +1202,56 @@ void Test_CFE_TBL_LoadCmd(void) /* Test where the file isn't dump only and passes table checks, get a * working buffer, and there is an extra byte (more data than header * indicates) + * Works because OS_read stub assumes success (returns dummy extra byte even though it isn't in the buffer) */ UT_InitData(); - UT_TBL_SetupHeader(&TblFileHeader, 0, sizeof(CFE_TBL_File_Hdr_t)); - CFE_TBL_Global.Registry[0].TableLoadedOnce = true; - - CFE_TBL_Global.Registry[0].Size = sizeof(CFE_TBL_File_Hdr_t); + UT_TBL_SetupHeader(&TblFileHeader, 0, sizeof(UT_Table1_t)); + CFE_TBL_Global.Registry[0].TableLoadedOnce = true; + CFE_TBL_Global.Registry[0].Size = sizeof(UT_Table1_t); CFE_TBL_Global.Registry[0].LoadInProgress = CFE_TBL_NO_LOAD_IN_PROGRESS + 1; - CFE_TBL_Global.Registry[0].DoubleBuffered = false; - CFE_TBL_Global.LoadBuffs[CFE_TBL_Global.Registry[0].LoadInProgress].BufferPtr = (uint8 *)&BufferPtr; + CFE_TBL_Global.LoadBuffs[CFE_TBL_Global.Registry[0].LoadInProgress].BufferPtr = &LoadBuffer; UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); UT_SetReadHeader(&StdFileHeader, sizeof(StdFileHeader)); - CFE_TBL_Global.Registry[0].DumpOnly = false; UtAssert_INT32_EQ(CFE_TBL_LoadCmd(&LoadCmd), CFE_TBL_INC_ERR_CTR); /* Test with no extra byte => successful load */ UT_InitData(); - UT_TBL_SetupHeader(&TblFileHeader, 0, sizeof(CFE_TBL_File_Hdr_t)); - + UT_TBL_SetupHeader(&TblFileHeader, 0, sizeof(UT_Table1_t)); UT_SetDeferredRetcode(UT_KEY(OS_read), 3, 0); - strncpy(TblFileHeader.TableName, CFE_TBL_Global.Registry[0].Name, sizeof(TblFileHeader.TableName) - 1); - TblFileHeader.TableName[sizeof(TblFileHeader.TableName) - 1] = '\0'; UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); UT_SetReadHeader(&StdFileHeader, sizeof(StdFileHeader)); UtAssert_INT32_EQ(CFE_TBL_LoadCmd(&LoadCmd), CFE_TBL_INC_CMD_CTR); /* Test with differing amount of data from header's claim */ UT_InitData(); - TblFileHeader.NumBytes = CFE_ES_MEMOFFSET_C(sizeof(CFE_TBL_File_Hdr_t)); + UT_TBL_SetupHeader(&TblFileHeader, 0, sizeof(UT_Table1_t)); + UT_SetDeferredRetcode(UT_KEY(OS_read), 2, 0); + UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); + UT_SetReadHeader(&StdFileHeader, sizeof(StdFileHeader)); + UtAssert_INT32_EQ(CFE_TBL_LoadCmd(&LoadCmd), CFE_TBL_INC_ERR_CTR); + + /* Test with no working buffers available */ + UT_InitData(); + CFE_TBL_Global.Registry[0].LoadInProgress = CFE_TBL_NO_LOAD_IN_PROGRESS; + CFE_TBL_Global.Registry[0].TableLoadedOnce = true; + CFE_TBL_Global.Registry[0].DoubleBuffered = false; - if (UT_Endianess == UT_LITTLE_ENDIAN) + for (i = 0; i < CFE_PLATFORM_TBL_MAX_SIMULTANEOUS_LOADS; i++) { - CFE_TBL_ByteSwapUint32(&TblFileHeader.NumBytes); + CFE_TBL_Global.LoadBuffs[i].Taken = true; } - strncpy(TblFileHeader.TableName, CFE_TBL_Global.Registry[0].Name, sizeof(TblFileHeader.TableName) - 1); - TblFileHeader.TableName[sizeof(TblFileHeader.TableName) - 1] = '\0'; - UT_SetDeferredRetcode(UT_KEY(OS_read), 2, 0); UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); UT_SetReadHeader(&StdFileHeader, sizeof(StdFileHeader)); UtAssert_INT32_EQ(CFE_TBL_LoadCmd(&LoadCmd), CFE_TBL_INC_ERR_CTR); - /* Test with no working buffers available */ + /* Test with interal CFE_TBL_GetWorkingBuffer error (memcpy with matching address */ UT_InitData(); CFE_TBL_Global.Registry[0].LoadInProgress = CFE_TBL_NO_LOAD_IN_PROGRESS; CFE_TBL_Global.Registry[0].TableLoadedOnce = true; CFE_TBL_Global.Registry[0].DoubleBuffered = false; - CFE_TBL_Global.Registry[0].Buffers[CFE_TBL_Global.Registry[0].ActiveBufferIndex] = BufferPtr; - - for (j = 0; j < CFE_PLATFORM_TBL_MAX_SIMULTANEOUS_LOADS; j++) - { - CFE_TBL_Global.LoadBuffs[j].Taken = true; - } - + CFE_TBL_Global.Registry[0].Buffers[CFE_TBL_Global.Registry[0].ActiveBufferIndex] = CFE_TBL_Global.LoadBuffs[0]; + CFE_TBL_Global.LoadBuffs[0].Taken = false; strncpy(TblFileHeader.TableName, CFE_TBL_Global.Registry[0].Name, sizeof(TblFileHeader.TableName) - 1); TblFileHeader.TableName[sizeof(TblFileHeader.TableName) - 1] = '\0'; UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); @@ -1222,11 +1260,8 @@ void Test_CFE_TBL_LoadCmd(void) /* Test with table header indicating data beyond size of the table */ UT_InitData(); - UT_TBL_SetupHeader(&TblFileHeader, 0, sizeof(CFE_TBL_File_Hdr_t)); - - CFE_TBL_Global.Registry[0].Size = sizeof(CFE_TBL_File_Hdr_t) - 1; - strncpy(TblFileHeader.TableName, CFE_TBL_Global.Registry[0].Name, sizeof(TblFileHeader.TableName) - 1); - TblFileHeader.TableName[sizeof(TblFileHeader.TableName) - 1] = '\0'; + UT_TBL_SetupHeader(&TblFileHeader, 0, sizeof(UT_Table1_t)); + CFE_TBL_Global.Registry[0].Size = sizeof(UT_Table1_t) - 1; UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); UT_SetReadHeader(&StdFileHeader, sizeof(StdFileHeader)); UtAssert_INT32_EQ(CFE_TBL_LoadCmd(&LoadCmd), CFE_TBL_INC_ERR_CTR); @@ -1234,9 +1269,6 @@ void Test_CFE_TBL_LoadCmd(void) /* Test with table header indicating no data in the file */ UT_InitData(); UT_TBL_SetupHeader(&TblFileHeader, 0, 0); - - strncpy(TblFileHeader.TableName, CFE_TBL_Global.Registry[0].Name, sizeof(TblFileHeader.TableName) - 1); - TblFileHeader.TableName[sizeof(TblFileHeader.TableName) - 1] = '\0'; UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); UT_SetReadHeader(&StdFileHeader, sizeof(StdFileHeader)); UtAssert_INT32_EQ(CFE_TBL_LoadCmd(&LoadCmd), CFE_TBL_INC_ERR_CTR); @@ -1246,12 +1278,8 @@ void Test_CFE_TBL_LoadCmd(void) */ UT_InitData(); UT_TBL_SetupHeader(&TblFileHeader, 1, 1); - CFE_TBL_Global.Registry[0].TableLoadedOnce = false; - - CFE_TBL_Global.Registry[0].Size = sizeof(CFE_TBL_File_Hdr_t); - strncpy(TblFileHeader.TableName, CFE_TBL_Global.Registry[0].Name, sizeof(TblFileHeader.TableName) - 1); - TblFileHeader.TableName[sizeof(TblFileHeader.TableName) - 1] = '\0'; + CFE_TBL_Global.Registry[0].Size = sizeof(UT_Table1_t); UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); UT_SetReadHeader(&StdFileHeader, sizeof(StdFileHeader)); UtAssert_INT32_EQ(CFE_TBL_LoadCmd(&LoadCmd), CFE_TBL_INC_ERR_CTR); @@ -1261,20 +1289,14 @@ void Test_CFE_TBL_LoadCmd(void) */ UT_InitData(); UT_TBL_SetupHeader(&TblFileHeader, 0, 1); - CFE_TBL_Global.Registry[0].TableLoadedOnce = false; - - CFE_TBL_Global.Registry[0].Size = sizeof(CFE_TBL_File_Hdr_t); - strncpy(TblFileHeader.TableName, CFE_TBL_Global.Registry[0].Name, sizeof(TblFileHeader.TableName) - 1); - TblFileHeader.TableName[sizeof(TblFileHeader.TableName) - 1] = '\0'; + CFE_TBL_Global.Registry[0].Size = sizeof(UT_Table1_t); UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); UT_SetReadHeader(&StdFileHeader, sizeof(StdFileHeader)); UtAssert_INT32_EQ(CFE_TBL_LoadCmd(&LoadCmd), CFE_TBL_INC_ERR_CTR); /* Test response to inability to read the file header */ UT_InitData(); - strncpy(LoadCmd.Payload.LoadFilename, "LoadFileName", sizeof(LoadCmd.Payload.LoadFilename) - 1); - LoadCmd.Payload.LoadFilename[sizeof(LoadCmd.Payload.LoadFilename) - 1] = '\0'; UT_SetDeferredRetcode(UT_KEY(CFE_FS_ReadHeader), 1, sizeof(CFE_FS_Header_t) - 1); UtAssert_INT32_EQ(CFE_TBL_LoadCmd(&LoadCmd), CFE_TBL_INC_ERR_CTR); } @@ -1353,6 +1375,12 @@ void Test_CFE_TBL_HousekeepingCmd(void) CFE_TBL_Global.DumpControlBlocks[0].State = CFE_TBL_DUMP_PERFORMED; UT_SetDeferredRetcode(UT_KEY(CFE_FS_SetTimestamp), 1, OS_SUCCESS - 1); UtAssert_INT32_EQ(CFE_TBL_HousekeepingCmd(NULL), CFE_TBL_DONT_INC_CTR); + + /* Test response to OS_OpenCreate failure */ + UT_InitData(); + CFE_TBL_Global.DumpControlBlocks[0].State = CFE_TBL_DUMP_PERFORMED; + UT_SetDeferredRetcode(UT_KEY(OS_OpenCreate), 3, -1); + UtAssert_INT32_EQ(CFE_TBL_HousekeepingCmd(NULL), CFE_TBL_DONT_INC_CTR); } /* @@ -1439,6 +1467,14 @@ void Test_CFE_TBL_Register(void) CFE_UtAssert_EVENTSENT(CFE_TBL_REGISTER_ERR_EID); CFE_UtAssert_EVENTCOUNT(1); + /* Test response at single size limit */ + UT_ClearEventHistory(); + CFE_UtAssert_SUCCESS( + CFE_TBL_Register(&TblHandle1, "UT_Table1", CFE_PLATFORM_TBL_MAX_SNGL_TABLE_SIZE, CFE_TBL_OPT_DEFAULT, NULL)); + CFE_UtAssert_EVENTNOTSENT(CFE_TBL_REGISTER_ERR_EID); + CFE_UtAssert_SUCCESS(CFE_TBL_Unregister(TblHandle1)); + CFE_UtAssert_EVENTCOUNT(0); + /* Test response to a double-buffered table size larger than the * maximum allowed */ @@ -1449,6 +1485,14 @@ void Test_CFE_TBL_Register(void) CFE_UtAssert_EVENTSENT(CFE_TBL_REGISTER_ERR_EID); CFE_UtAssert_EVENTCOUNT(1); + /* Test response at double size limit */ + UT_ClearEventHistory(); + CFE_UtAssert_SUCCESS( + CFE_TBL_Register(&TblHandle1, "UT_Table1", CFE_PLATFORM_TBL_MAX_DBL_TABLE_SIZE, CFE_TBL_OPT_DBL_BUFFER, NULL)); + CFE_UtAssert_EVENTNOTSENT(CFE_TBL_REGISTER_ERR_EID); + CFE_UtAssert_SUCCESS(CFE_TBL_Unregister(TblHandle1)); + CFE_UtAssert_EVENTCOUNT(0); + /* Test response to an invalid table option combination * (CFE_TBL_OPT_USR_DEF_ADDR | CFE_TBL_OPT_DBL_BUFFER) */ @@ -2916,8 +2960,11 @@ void Test_CFE_TBL_Update(void) UtAssert_INT32_EQ(CFE_TBL_Update(App1TblHandle1), CFE_TBL_ERR_NO_ACCESS); CFE_UtAssert_EVENTCOUNT(1); - /* Successfully process an update */ + /* Test with resource not valid */ UT_InitData(); + UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetAppID), 1, CFE_ES_ERR_RESOURCEID_NOT_VALID); + UtAssert_INT32_EQ(CFE_TBL_Update(App1TblHandle1), CFE_ES_ERR_RESOURCEID_NOT_VALID); + CFE_UtAssert_EVENTCOUNT(1); } /* @@ -2984,6 +3031,7 @@ void Test_CFE_TBL_TblMod(void) CFE_TBL_RegistryRec_t * RegRecPtr; CFE_TBL_Handle_t AccessIterator; uint8 CDS_Data[sizeof(UT_Table1_t)]; + uint32 ExpectedCrc; UtPrintf("Begin Test Table Modified"); @@ -3104,10 +3152,19 @@ void Test_CFE_TBL_TblMod(void) CFE_UtAssert_EVENTSENT(CFE_TBL_LOAD_SUCCESS_INF_EID); CFE_UtAssert_EVENTCOUNT(1); - /* Notify Table Services that the table has been modified */ + /* + * Notify Table Services that the table has been modified. Verify CRC has been + * calculated and table has been flagged as Updated + */ + ExpectedCrc = 0x0000F00D; + UT_SetDeferredRetcode(UT_KEY(CFE_ES_CalculateCRC), 1, ExpectedCrc); + CFE_TBL_Global.Handles[AccessIterator].Updated = false; CFE_UtAssert_SUCCESS(CFE_TBL_Modified(App1TblHandle1)); + UtAssert_BOOL_TRUE(CFE_TBL_Global.Handles[AccessIterator].Updated); CFE_UtAssert_SUCCESS(CFE_TBL_GetInfo(&TblInfo1, "ut_cfe_tbl.UT_Table2")); UtAssert_INT32_EQ(TblInfo1.TimeOfLastUpdate.Seconds, TblInfo1.TimeOfLastUpdate.Subseconds); + UtAssert_UINT32_EQ(TblInfo1.Crc, ExpectedCrc); + UtAssert_INT32_EQ(CFE_TBL_GetAddress((void **)&TblDataPtr, App1TblHandle1), CFE_TBL_INFO_UPDATED); /* * LastFileLoaded (limited by mission) can be bigger than MyFilename (limited by osal), @@ -3243,6 +3300,35 @@ void Test_CFE_TBL_Internal(void) CFE_UtAssert_EVENTSENT(CFE_TBL_FILE_INCOMPLETE_ERR_EID); CFE_UtAssert_EVENTCOUNT(1); + /* Test CFE_TBL_LoadFromFile with failure of data OS_read */ + UT_InitData(); + StdFileHeader.ContentType = CFE_FS_FILE_CONTENT_ID; + StdFileHeader.SubType = CFE_FS_SubType_TBL_IMG; + strncpy(TblFileHeader.TableName, "ut_cfe_tbl.UT_Table2", sizeof(TblFileHeader.TableName) - 1); + TblFileHeader.TableName[sizeof(TblFileHeader.TableName) - 1] = '\0'; + UT_TBL_SetupHeader(&TblFileHeader, 0, sizeof(UT_Table1_t)); + + UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); + UT_SetReadHeader(&StdFileHeader, sizeof(StdFileHeader)); + UT_SetDeferredRetcode(UT_KEY(OS_read), 2, -1); + UtAssert_INT32_EQ(CFE_TBL_LoadFromFile("UT", WorkingBufferPtr, RegRecPtr, Filename), CFE_TBL_ERR_LOAD_INCOMPLETE); + CFE_UtAssert_EVENTSENT(CFE_TBL_FILE_INCOMPLETE_ERR_EID); + CFE_UtAssert_EVENTCOUNT(1); + + /* Test CFE_TBL_LoadFromFile with failure of extra byte OS_read */ + UT_InitData(); + StdFileHeader.ContentType = CFE_FS_FILE_CONTENT_ID; + StdFileHeader.SubType = CFE_FS_SubType_TBL_IMG; + strncpy(TblFileHeader.TableName, "ut_cfe_tbl.UT_Table2", sizeof(TblFileHeader.TableName) - 1); + TblFileHeader.TableName[sizeof(TblFileHeader.TableName) - 1] = '\0'; + UT_TBL_SetupHeader(&TblFileHeader, 0, sizeof(UT_Table1_t)); + + UT_SetReadBuffer(&TblFileHeader, sizeof(TblFileHeader)); + UT_SetReadHeader(&StdFileHeader, sizeof(StdFileHeader)); + UT_SetDeferredRetcode(UT_KEY(OS_read), 3, -1); + CFE_UtAssert_SUCCESS(CFE_TBL_LoadFromFile("UT", WorkingBufferPtr, RegRecPtr, Filename)); + CFE_UtAssert_EVENTCOUNT(0); + /* Test CFE_TBL_LoadFromFile response to the file being for the * wrong table */ @@ -3641,7 +3727,7 @@ void Test_CFE_TBL_Internal(void) CFE_TBL_Global.DumpControlBlocks[3].RegRecPtr = RegRecPtr; RegRecPtr->LoadInProgress = 1; CFE_TBL_Global.LoadBuffs[1].Taken = true; - CFE_TBL_CleanUpApp(UT_TBL_APPID_1); + CFE_UtAssert_SUCCESS(CFE_TBL_CleanUpApp(UT_TBL_APPID_1)); UtAssert_INT32_EQ(CFE_TBL_Global.DumpControlBlocks[3].State, CFE_TBL_DUMP_FREE); CFE_UtAssert_RESOURCEID_EQ(RegRecPtr->OwnerAppId, CFE_TBL_NOT_OWNED); UtAssert_BOOL_FALSE(CFE_TBL_Global.LoadBuffs[RegRecPtr->LoadInProgress].Taken); @@ -3748,21 +3834,34 @@ void Test_CFE_TBL_Internal(void) CFE_UtAssert_SUCCESS(CFE_TBL_UpdateInternal(App1TblHandle2, RegRecPtr, AccessDescPtr)); CFE_UtAssert_EVENTCOUNT(0); - /* Test application cleanup where there are no dumped tables to delete and - * the application doesn't own the table + /* Test CFE_TBL_UpdateInternal with overlapping memcopy (bug) */ + UT_InitData(); + AccessDescPtr = &CFE_TBL_Global.Handles[App1TblHandle2]; + RegRecPtr = &CFE_TBL_Global.Registry[AccessDescPtr->RegIndex]; + RegRecPtr->LoadPending = true; + RegRecPtr->LoadInProgress = CFE_TBL_NO_LOAD_IN_PROGRESS + 1; + RegRecPtr->DoubleBuffered = false; + RegRecPtr->Buffers[0].BufferPtr = CFE_TBL_Global.LoadBuffs[RegRecPtr->LoadInProgress].BufferPtr; + CFE_UtAssert_SUCCESS(CFE_TBL_UpdateInternal(App1TblHandle2, RegRecPtr, AccessDescPtr)); + CFE_UtAssert_EVENTCOUNT(0); + + /* Test application cleanup where there are no dumped tables to delete, + * one unused handle and one used but not owned table */ UT_InitData(); UT_SetAppID(UT_TBL_APPID_1); UT_SetDefaultReturnValue(UT_KEY(CFE_ES_PutPoolBuf), -1); CFE_TBL_Global.Handles[0].AppId = UT_TBL_APPID_1; - AccessDescPtr = &CFE_TBL_Global.Handles[App1TblHandle2]; - RegRecPtr = &CFE_TBL_Global.Registry[AccessDescPtr->RegIndex]; - RegRecPtr->OwnerAppId = CFE_TBL_NOT_OWNED; + CFE_TBL_Global.Handles[0].UsedFlag = true; + CFE_TBL_Global.Handles[0].RegIndex = 0; + CFE_TBL_Global.Registry[0].OwnerAppId = UT_TBL_APPID_2; CFE_TBL_Global.DumpControlBlocks[3].State = CFE_TBL_DUMP_PENDING; - CFE_TBL_Global.DumpControlBlocks[3].RegRecPtr = RegRecPtr; - CFE_TBL_CleanUpApp(UT_TBL_APPID_1); + CFE_TBL_Global.DumpControlBlocks[3].RegRecPtr = &CFE_TBL_Global.Registry[0]; + CFE_TBL_Global.Handles[1].AppId = UT_TBL_APPID_1; + CFE_TBL_Global.Handles[1].UsedFlag = false; + CFE_UtAssert_SUCCESS(CFE_TBL_CleanUpApp(UT_TBL_APPID_1)); UtAssert_INT32_EQ(CFE_TBL_Global.DumpControlBlocks[3].State, CFE_TBL_DUMP_PENDING); - CFE_UtAssert_RESOURCEID_EQ(RegRecPtr->OwnerAppId, CFE_TBL_NOT_OWNED); + CFE_UtAssert_RESOURCEID_EQ(RegRecPtr->OwnerAppId, UT_TBL_APPID_2); #if (CFE_PLATFORM_TBL_VALID_SCID_COUNT > 0) /* Test CFE_TBL_ReadHeaders response to an invalid spacecraft ID */ diff --git a/modules/time/ut-coverage/time_UT.c b/modules/time/ut-coverage/time_UT.c index e578caec0..35b41e36b 100644 --- a/modules/time/ut-coverage/time_UT.c +++ b/modules/time/ut-coverage/time_UT.c @@ -943,21 +943,21 @@ void Test_RegisterSyncCallbackTrue(void) UT_InitData(); UtAssert_INT32_EQ(CFE_TIME_RegisterSynchCallback(NULL), CFE_TIME_BAD_ARGUMENT); - /* - * One callback per application is allowed; the first should succeed, - * the second should fail. - */ - + /* CFE_ES_GetAppID failure */ UT_InitData(); UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetAppID), 1, -1); - CFE_TIME_Global.SynchCallback[0].Ptr = NULL; - UtAssert_INT32_EQ(CFE_TIME_RegisterSynchCallback(&ut_time_MyCallbackFunc), -1); + /* CFE_ES_AppID_ToIndex failure */ + UT_InitData(); + UT_SetDeferredRetcode(UT_KEY(CFE_ES_AppID_ToIndex), 1, -2); + UtAssert_INT32_EQ(CFE_TIME_RegisterSynchCallback(&ut_time_MyCallbackFunc), -2); + /* Test registering the callback function the maximum number of times, * then attempt registering one more time */ UT_InitData(); + CFE_TIME_Global.SynchCallback[0].Ptr = NULL; /* * One callback per application is allowed; the first should succeed, @@ -1347,10 +1347,9 @@ void Test_PipeCmds(void) UtPrintf("Begin Test Pipe Commands"); - memset(&CmdBuf, 0, sizeof(CmdBuf)); - /* Test sending the housekeeping telemetry request command */ UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); UT_SetHookFunction(UT_KEY(CFE_SB_TransmitMsg), UT_SoftwareBusSnapshotHook, &LocalSnapshotData); UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, sizeof(CmdBuf.cmd), UT_TPID_CFE_TIME_SEND_HK); UtAssert_INT32_EQ(LocalSnapshotData.Count, 1); @@ -1402,11 +1401,32 @@ void Test_PipeCmds(void) UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, sizeof(CmdBuf.cmd), UT_TPID_CFE_TIME_CMD_NOOP_CC); CFE_UtAssert_EVENTSENT(CFE_TIME_NOOP_EID); + /* Noop with bad size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_NOOP_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending the reset counters command */ UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, sizeof(CmdBuf.cmd), UT_TPID_CFE_TIME_CMD_RESET_COUNTERS_CC); CFE_UtAssert_EVENTSENT(CFE_TIME_RESET_EID); + /* Reset counters with bad size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_RESET_COUNTERS_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending the request diagnostics command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1414,6 +1434,16 @@ void Test_PipeCmds(void) UT_TPID_CFE_TIME_CMD_SEND_DIAGNOSTIC_TLM_CC); CFE_UtAssert_EVENTSENT(CFE_TIME_DIAG_EID); + /* Request diagnostics with bad size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_SEND_DIAGNOSTIC_TLM_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending a clock state = invalid command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1444,6 +1474,16 @@ void Test_PipeCmds(void) UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, sizeof(CmdBuf.statecmd), UT_TPID_CFE_TIME_CMD_SET_STATE_CC); CFE_UtAssert_EVENTSENT(CFE_TIME_STATE_ERR_EID); + /* Set state with invalid size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_SET_STATE_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending the set time source = internal command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1477,6 +1517,16 @@ void Test_PipeCmds(void) UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, sizeof(CmdBuf.sourcecmd), UT_TPID_CFE_TIME_CMD_SET_SOURCE_CC); CFE_UtAssert_EVENTSENT(CFE_TIME_SOURCE_ERR_EID); + /* Set time source with invalid size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_SET_SOURCE_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending a set tone signal source = primary command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1524,6 +1574,16 @@ void Test_PipeCmds(void) CFE_UtAssert_EVENTSENT(CFE_TIME_SIGNAL_ERR_EID); UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Set tone signal source with invalid size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_SET_SIGNAL_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending a time tone add delay command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1543,6 +1603,16 @@ void Test_PipeCmds(void) UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); #endif + /* Time tone add delay with invalid size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_ADD_DELAY_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending a time tone subtract delay command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1560,6 +1630,16 @@ void Test_PipeCmds(void) UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); #endif + /* Time tone subtract delay with invalid size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_SUB_DELAY_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending a set time command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1577,6 +1657,16 @@ void Test_PipeCmds(void) UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); #endif + /* Set time with invalid size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_SET_TIME_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending a set MET command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1594,6 +1684,16 @@ void Test_PipeCmds(void) UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); #endif + /* Set MET with invalid size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_SET_MET_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending a set STCF command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1611,6 +1711,16 @@ void Test_PipeCmds(void) UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); #endif + /* Set STCF with invalid size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_SET_STCF_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending an adjust STCF positive command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1628,6 +1738,16 @@ void Test_PipeCmds(void) UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); #endif + /* Adjust STCF positive with invalid size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_ADD_ADJUST_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending an adjust STCF negative command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1645,6 +1765,16 @@ void Test_PipeCmds(void) UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); #endif + /* Adjust STCF negative with invalid size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_SUB_ADJUST_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending an adjust STCF 1 Hz positive command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1663,6 +1793,16 @@ void Test_PipeCmds(void) UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); #endif + /* Adjust STCF 1Hz positive with invalid size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_ADD_1HZ_ADJUSTMENT_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test sending an adjust STCF 1 Hz negative command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1681,6 +1821,16 @@ void Test_PipeCmds(void) UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); #endif + /* Adjust STCF 1 Hz negative with invalid size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_SUB_1HZ_ADJUSTMENT_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test response to sending a tone delay command using an invalid time */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1735,6 +1885,16 @@ void Test_PipeCmds(void) UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); #endif + /* Set leap seconds with invalid size */ + UT_InitData(); + memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_TIME_Global.CommandCounter = 0; + CFE_TIME_Global.CommandErrorCounter = 0; + UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_SET_LEAP_SECONDS_CC); + CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandCounter, 0); + UtAssert_UINT32_EQ(CFE_TIME_Global.CommandErrorCounter, 1); + /* Test response to sending an invalid command */ UT_InitData(); memset(&CmdBuf, 0, sizeof(CmdBuf)); @@ -1747,11 +1907,6 @@ void Test_PipeCmds(void) UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, sizeof(CmdBuf.cmd), UT_TPID_CFE_TIME_INVALID_MID); CFE_UtAssert_EVENTSENT(CFE_TIME_ID_ERR_EID); - /* Test response to sending a command with a bad length */ - UT_InitData(); - UT_CallTaskPipe(CFE_TIME_TaskPipe, &CmdBuf.message, 0, UT_TPID_CFE_TIME_CMD_SET_LEAP_SECONDS_CC); - CFE_UtAssert_EVENTSENT(CFE_TIME_LEN_ERR_EID); - /* Call the Task Pipe with the 1Hz command. */ /* In the 1Hz state machine it should call PSP GetTime as part, of latching the clock. This is tested only to see that the latch executed. */ @@ -2002,6 +2157,7 @@ void Test_Tone(void) { CFE_TIME_SysTime_t time1; CFE_TIME_SysTime_t time2; + CFE_TIME_Reference_t Reference; volatile CFE_TIME_ReferenceState_t *RefState; uint32 VersionSave; @@ -2193,6 +2349,16 @@ void Test_Tone(void) CFE_TIME_Global.ClockSource = CFE_TIME_SourceSelect_INTERNAL; + /* Cover path for internal source and not flying */ + CFE_TIME_GetReference(&Reference); + Reference.CurrentMET.Seconds = 10; + RefState = CFE_TIME_StartReferenceUpdate(); + RefState->ClockFlyState = CFE_TIME_FlywheelState_NO_FLY; + CFE_TIME_FinishReferenceUpdate(RefState); + CFE_TIME_Global.VirtualMET = 5; + UtAssert_VOIDCALL(CFE_TIME_ToneUpdate()); + UtAssert_UINT32_EQ(CFE_TIME_Global.VirtualMET, 5); + #if (CFE_PLATFORM_TIME_CFG_CLIENT == true) /* Test tone update using an invalid pending state */ UT_InitData(); @@ -2211,8 +2377,8 @@ void Test_Tone(void) UtAssert_INT32_EQ(CFE_TIME_Global.ServerFlyState, CFE_TIME_FlywheelState_IS_FLY); #else - UtAssert_NA("*Not tested* Invalid pending state"); - UtAssert_NA("*Not tested* Pending state is FLYWHEEL"); + UtAssert_NA("*Not tested* CFE_TIME_ToneUpdate() Invalid pending state, requires client configuration"); + UtAssert_NA("*Not tested* CFE_TIME_ToneUpdate() Pending state is FLYWHEEL, requires client configuration"); #endif } @@ -2499,6 +2665,16 @@ void Test_UnregisterSynchCallback(void) UT_SetDeferredRetcode(UT_KEY(CFE_ES_GetAppID), 1, -1); UtAssert_INT32_EQ(CFE_TIME_UnregisterSynchCallback(&ut_time_MyCallbackFunc), -1); + /* CFE_ES_AppID_ToIndex failure */ + UT_InitData(); + UT_SetDeferredRetcode(UT_KEY(CFE_ES_AppID_ToIndex), 1, -2); + UtAssert_INT32_EQ(CFE_TIME_UnregisterSynchCallback(&ut_time_MyCallbackFunc), -2); + + /* App Index outside bounds of SynchCallback array */ + AppIndex = (sizeof(CFE_TIME_Global.SynchCallback) / sizeof(CFE_TIME_Global.SynchCallback[0])); + UT_SetDataBuffer(UT_KEY(CFE_ES_AppID_ToIndex), &AppIndex, sizeof(AppIndex), false); + UtAssert_INT32_EQ(CFE_TIME_UnregisterSynchCallback(&ut_time_MyCallbackFunc), CFE_TIME_CALLBACK_NOT_REGISTERED); + /* Test tone notification with an invalid time synch application */ UT_InitData(); CFE_TIME_Global.IsToneGood = true; @@ -2580,4 +2756,9 @@ void Test_CleanUpApp(void) AppIndex = 99999; UT_SetDataBuffer(UT_KEY(CFE_ES_AppID_ToIndex), &AppIndex, sizeof(AppIndex), false); UtAssert_INT32_EQ(CFE_TIME_CleanUpApp(CFE_ES_APPID_UNDEFINED), CFE_TIME_CALLBACK_NOT_REGISTERED); + + /* CFE_ES_AppID_ToIndex failure */ + UT_InitData(); + UT_SetDeferredRetcode(UT_KEY(CFE_ES_AppID_ToIndex), 1, -2); + UtAssert_INT32_EQ(CFE_TIME_CleanUpApp(CFE_ES_APPID_UNDEFINED), -2); }