diff --git a/cmake/mission_defaults.cmake b/cmake/mission_defaults.cmake index 8f49d54d5..43818473a 100644 --- a/cmake/mission_defaults.cmake +++ b/cmake/mission_defaults.cmake @@ -45,3 +45,10 @@ set(MISSION_MODULE_SEARCH_PATH set(cfe-core_SEARCH_PATH "cfe/fsw") set(osal_SEARCH_PATH ".") set(psp_SEARCH_PATH ".") + +# If ENABLE_UNIT_TEST is enabled, then include the cfe_assert library in +# all targets. This can still be overridden in targets.cmake. +if (ENABLE_UNIT_TESTS) + list(APPEND MISSION_GLOBAL_APPLIST cfe_assert cfe_testrunner cfe_testcase) +endif (ENABLE_UNIT_TESTS) + diff --git a/docs/README_functionaltest.md b/docs/README_functionaltest.md new file mode 100644 index 000000000..027e9f757 --- /dev/null +++ b/docs/README_functionaltest.md @@ -0,0 +1,40 @@ +# Mini-HOWTO guide for running CFE functional tests + +This version of CFE includes additional modular libraries and an application +to execute functional tests within an unmodified CFE environment. These are +distinct from the unit tests, which are executed separately from CFE in a +confined (non-CFE, test-specific) environment. + +## Building the modules + +These modules are built automatically when `ENABLE_UNIT_TESTS` is enabled +in the build. However, they can be added to any CFE build by adding the +following to the `APPLIST` of any target in `targets.cmake`: + +- `cfe_assert`: a CFE-compatible library wrapping the basic UT assert library. This +is the same library that all other unit tests use, but configured to be +dynamically loaded into the CFE environment, and using CFE syslog for its output. +This must be the first library loaded for any functional test. + +- `cfe_testcase`: a CFE-compatible library implementing test cases for CFE core apps. +This must be loaded after `cfe_assert`. + +- `cfe_testrunner`: a CFE application that actually executes the tests. This is a very +simple app that waits for CFE startup to complete, then executes all registered test +cases. It also must be loaded after `cfe_assert`. + + +## Example startup script entries + +To execute tests at startup, the following lines can be added to `cfe_es_startup.scr` on the +designated test target: + + CFE_LIB, /cf/cfe_assert.so, CFE_Assert_LibInit, ASSERT_LIB, 0, 0, 0x0, 0; + CFE_APP, /cf/cfe_testrunner.so, CFE_TestRunner_AppMain, TESTRUN_APP, 100, 16384, 0x0, 0; + CFE_LIB, /cf/cfe_testcase.so, CFE_Test_Init, CFETEST_LIB, 0, 0, 0x0, 0; + CFE_LIB, /cf/psp_test.so, PSP_Test_Init, PSPTEST_LIB, 0, 0, 0x0, 0; + +It is important that `cfe_assert` is loaded first, as all other test libraries depend on +symbols provided in this library. The order of loading other test cases should not +matter with respect to symbol resolution, but note that test cases will be executed in +the same order that they are registered. diff --git a/modules/cfe_assert/CMakeLists.txt b/modules/cfe_assert/CMakeLists.txt new file mode 100644 index 000000000..c80330ab8 --- /dev/null +++ b/modules/cfe_assert/CMakeLists.txt @@ -0,0 +1,12 @@ +project(CFE_ASSERT C) + +include_directories("${CFE_ASSERT_SOURCE_DIR}/inc") +include_directories("${UT_ASSERT_SOURCE_DIR}/inc") + +# Create the app module +add_cfe_app(cfe_assert + src/cfe_assert_io.c + src/cfe_assert_init.c + $ +) + diff --git a/modules/cfe_assert/inc/cfe_assert.h b/modules/cfe_assert/inc/cfe_assert.h new file mode 100644 index 000000000..8dde70a4f --- /dev/null +++ b/modules/cfe_assert/inc/cfe_assert.h @@ -0,0 +1,63 @@ +/************************************************************************* +** +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** File: cfe_assert.h +** +** Purpose: +** Specification for the CFE assert (UT assert wrapper) functions. +** +*************************************************************************/ +#ifndef cfe_assert_h_ +#define cfe_assert_h_ + +/************************************************************************ +** Includes +*************************************************************************/ +#include + +/************************************************************************ +** Type Definitions +*************************************************************************/ + +/************************************************************************* +** Exported Functions +*************************************************************************/ + +/************************************************************************/ +/** \brief Application Entry Point Function +** +** \par Description +** This function should be specified in the cfe_es_startup.scr file +** as part of starting this application. +** +** \par Assumptions, External Events, and Notes: +** None +** +** \return Execution status, see \ref CFEReturnCodes +** +** +*************************************************************************/ +void CFE_Assert_AppMain(void); + +#endif /* cfe_assert_h_ */ + +/************************/ +/* End of File Comment */ +/************************/ diff --git a/modules/cfe_assert/src/cfe_assert_init.c b/modules/cfe_assert/src/cfe_assert_init.c new file mode 100644 index 000000000..d1923785a --- /dev/null +++ b/modules/cfe_assert/src/cfe_assert_init.c @@ -0,0 +1,56 @@ +/************************************************************************* +** +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** File: cfe_assert_main.c +** +** Purpose: +** Implementation of the CFE assert (UT assert wrapper) functions. +** +*************************************************************************/ + +/* + * Includes + */ + +#include + +#include "cfe_assert.h" + +#include "uttest.h" +#include "utbsp.h" + +/* + * Initialization Function for this library + */ +int32 CFE_Assert_LibInit(uint32 LibId) +{ + UtTest_EarlyInit(); + UT_BSP_Setup(); + + /* + * Start a test case for all startup logic. + * + * Test libs may use assert statements within their init function and these + * will be reported as a "startup" test case. + */ + UtAssert_BeginTest("CFE-STARTUP"); + + return CFE_SUCCESS; +} diff --git a/modules/cfe_assert/src/cfe_assert_io.c b/modules/cfe_assert/src/cfe_assert_io.c new file mode 100644 index 000000000..5c01213c3 --- /dev/null +++ b/modules/cfe_assert/src/cfe_assert_io.c @@ -0,0 +1,137 @@ +/************************************************************************* +** +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** File: cfe_assert_io.c +** +** Purpose: +** Implementation of the CFE assert (UT assert wrapper) functions. +** +*************************************************************************/ + +#include +#include +#include +#include + +#include + +#include "utbsp.h" +#include "uttest.h" + +/* +** Local Variables +*/ +typedef struct +{ + uint32 CurrVerbosity; +} BSP_UT_GlobalData_t; + +BSP_UT_GlobalData_t BSP_UT_Global; + +void UT_BSP_Setup(void) +{ + BSP_UT_Global.CurrVerbosity = (2 << UTASSERT_CASETYPE_PASS) - 1; + UT_BSP_DoText(UTASSERT_CASETYPE_BEGIN, "CFE FUNCTIONAL TEST"); +} + +void UT_BSP_StartTestSegment(uint32 SegmentNumber, const char *SegmentName) +{ + char ReportBuffer[128]; + + snprintf(ReportBuffer, sizeof(ReportBuffer), "%02u %s", (unsigned int)SegmentNumber, SegmentName); + UT_BSP_DoText(UTASSERT_CASETYPE_BEGIN, ReportBuffer); +} + +void UT_BSP_DoText(uint8 MessageType, const char *OutputMessage) +{ + const char *Prefix; + uint32 MsgEnabled = BSP_UT_Global.CurrVerbosity >> MessageType; + + if (MsgEnabled & 1) + { + switch (MessageType) + { + case UTASSERT_CASETYPE_ABORT: + Prefix = "ABORT"; + break; + case UTASSERT_CASETYPE_FAILURE: + Prefix = "FAIL"; + break; + case UTASSERT_CASETYPE_MIR: + Prefix = "MIR"; + break; + case UTASSERT_CASETYPE_TSF: + Prefix = "TSF"; + break; + case UTASSERT_CASETYPE_TTF: + Prefix = "TTF"; + break; + case UTASSERT_CASETYPE_NA: + Prefix = "N/A"; + break; + case UTASSERT_CASETYPE_BEGIN: + Prefix = "BEGIN"; + break; + case UTASSERT_CASETYPE_END: + Prefix = "END"; + break; + case UTASSERT_CASETYPE_PASS: + Prefix = "PASS"; + break; + case UTASSERT_CASETYPE_INFO: + Prefix = "INFO"; + break; + case UTASSERT_CASETYPE_DEBUG: + Prefix = "DEBUG"; + break; + default: + Prefix = "OTHER"; + break; + } + + CFE_ES_WriteToSysLog("[%5s] %s\n", Prefix, OutputMessage); + } + + /* + * If any ABORT (major failure) message is thrown, + * then call a BSP-provided routine to stop the test and possibly dump a core + */ + if (MessageType == UTASSERT_CASETYPE_ABORT) + { + OS_TaskExit(); + } +} + +void UT_BSP_EndTest(const UtAssert_TestCounter_t *TestCounters) +{ + /* + * Only output a "summary" if there is more than one test Segment. + * Otherwise it is a duplicate of the report already given. + */ + if (TestCounters->TestSegmentCount > 1) + { + UtAssert_DoTestSegmentReport("SUMMARY", TestCounters); + } + + CFE_ES_WriteToSysLog("TEST COMPLETE: %u tests Segment(s) executed\n\n", + (unsigned int)TestCounters->TestSegmentCount); + + OS_TaskExit(); +} diff --git a/modules/cfe_testcase/CMakeLists.txt b/modules/cfe_testcase/CMakeLists.txt new file mode 100644 index 000000000..a2a48bde9 --- /dev/null +++ b/modules/cfe_testcase/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories("${CFE_ASSERT_SOURCE_DIR}/inc") +include_directories("${UT_ASSERT_SOURCE_DIR}/inc") + +# Create the app module +add_cfe_app(cfe_testcase + src/cfe_test.c + src/es_test.c +) diff --git a/modules/cfe_testcase/src/cfe_test.c b/modules/cfe_testcase/src/cfe_test.c new file mode 100644 index 000000000..d9606b9eb --- /dev/null +++ b/modules/cfe_testcase/src/cfe_test.c @@ -0,0 +1,43 @@ +/************************************************************************* +** +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** File: cfe_test.c +** +** Purpose: +** Initialization routine for CFE functional test +** Demonstration of how to register and use the UT assert functions. +** +*************************************************************************/ + +/* + * Includes + */ + +#include "cfe_test.h" + +/* + * Initialization function + * Register this test routine with CFE Assert + */ +int32 CFE_Test_Init(int32 LibId) +{ + UtTest_Add(ES_Test_AppId, NULL, NULL, "ES AppID"); + return CFE_SUCCESS; +} diff --git a/modules/cfe_testcase/src/cfe_test.h b/modules/cfe_testcase/src/cfe_test.h new file mode 100644 index 000000000..45f98e890 --- /dev/null +++ b/modules/cfe_testcase/src/cfe_test.h @@ -0,0 +1,44 @@ +/************************************************************************* +** +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** File: cfe_test.c +** +** Purpose: +** Initialization routine for CFE functional test +** Demonstration of how to register and use the UT assert functions. +** +*************************************************************************/ + +#ifndef CFE_TEST_H +#define CFE_TEST_H + +/* + * Includes + */ + +#include + +#include "uttest.h" +#include "utassert.h" + +void ES_Test_AppId(void); +int32 CFE_Test_Init(int32 LibId); + +#endif /* CFE_TEST_H */ diff --git a/modules/cfe_testcase/src/es_test.c b/modules/cfe_testcase/src/es_test.c new file mode 100644 index 000000000..afe13e74e --- /dev/null +++ b/modules/cfe_testcase/src/es_test.c @@ -0,0 +1,44 @@ +/************************************************************************* +** +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** File: es_test.c +** +** Purpose: +** Functional test of basic ES APIs +** +** Demonstration of how to register and use the UT assert functions. +** +*************************************************************************/ + +/* + * Includes + */ + +#include "cfe_test.h" + +void ES_Test_AppId(void) +{ + uint32 AppId; + char AppNameBuf[OS_MAX_API_NAME + 4]; + + UtAssert_INT32_EQ(CFE_ES_GetAppID(&AppId), CFE_SUCCESS); + UtAssert_INT32_EQ(CFE_ES_GetAppName(AppNameBuf, AppId, sizeof(AppNameBuf)), CFE_SUCCESS); + UtAssert_StrCmp(AppNameBuf, "TESTRUN_APP", "CFE_ES_GetAppName() returned TESTRUN_APP"); +} diff --git a/modules/cfe_testrunner/CMakeLists.txt b/modules/cfe_testrunner/CMakeLists.txt new file mode 100644 index 000000000..24d153262 --- /dev/null +++ b/modules/cfe_testrunner/CMakeLists.txt @@ -0,0 +1,10 @@ +project(CFE_TESTRUNNER C) + +include_directories("inc") +include_directories("${UT_ASSERT_SOURCE_DIR}/inc") + +# Create the app module +add_cfe_app(cfe_testrunner + src/cfe_testrunner_main.c +) + diff --git a/modules/cfe_testrunner/inc/cfe_testrunner.h b/modules/cfe_testrunner/inc/cfe_testrunner.h new file mode 100644 index 000000000..8502714af --- /dev/null +++ b/modules/cfe_testrunner/inc/cfe_testrunner.h @@ -0,0 +1,63 @@ +/************************************************************************* +** +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** File: cfe_testrunner.h +** +** Purpose: +** Specification for the CFE testrunner (UT testrunner wrapper) functions. +** +*************************************************************************/ +#ifndef cfe_testrunner_h_ +#define cfe_testrunner_h_ + +/************************************************************************ +** Includes +*************************************************************************/ +#include + +/************************************************************************ +** Type Definitions +*************************************************************************/ + +/************************************************************************* +** Exported Functions +*************************************************************************/ + +/************************************************************************/ +/** \brief Application Entry Point Function +** +** \par Description +** This function should be specified in the cfe_es_startup.scr file +** as part of starting this application. +** +** \par Assumptions, External Events, and Notes: +** None +** +** \return Execution status, see \ref CFEReturnCodes +** +** +*************************************************************************/ +void CFE_TestRunner_AppMain(void); + +#endif /* cfe_testrunner_h_ */ + +/************************/ +/* End of File Comment */ +/************************/ diff --git a/modules/cfe_testrunner/src/cfe_testrunner_main.c b/modules/cfe_testrunner/src/cfe_testrunner_main.c new file mode 100644 index 000000000..c12153a23 --- /dev/null +++ b/modules/cfe_testrunner/src/cfe_testrunner_main.c @@ -0,0 +1,120 @@ +/************************************************************************* +** +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +** +** File: cfe_testrunner_main.c +** +** Purpose: +** Implementation of the CFE testrunner (UT testrunner wrapper) functions. +** +*************************************************************************/ + +/* + * Includes + */ + +#include + +#include "cfe_testrunner.h" + +#include "uttest.h" +#include "utbsp.h" + +/* + * The maximum amount of time that the application will delay to + * wait for other apps to complete startup before running the tests. + * + * The value is in milliseconds. Normally this shouldn't be more than + * a second or two for apps to all reach their respective main loop(s). + */ +#define CFE_TESTRUNNER_MAX_STARTUP_WAIT 30000 + +/* + * Small Extra delay before starting tests. + * + * This is not strictly necessary, but it does give a bit of time for other apps + * to settle their final syslog writes/events such that they will not be intermixed + * with test messages in the syslog. + * + * The value is in milliseconds. + */ +#define CFE_TESTRUNNER_START_DELAY 4000 + +/* + * Entry point for this application + */ +void CFE_TestRunner_AppMain(void) +{ + int32 rc; + uint32 RunStatus; + + /* + ** Register the app with Executive services + */ + rc = CFE_ES_RegisterApp(); + if (rc != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("Error in CFE_ES_RegisterApp(): %08lx\n", (unsigned long)rc); + return; + } + + /* + * Delay until the system reaches "operational" state -- this is when all libs have initialized + * and all apps have reached their RunLoop. + */ + rc = CFE_ES_WaitForSystemState(CFE_ES_SystemState_OPERATIONAL, CFE_TESTRUNNER_MAX_STARTUP_WAIT); + if (rc != CFE_SUCCESS) + { + CFE_ES_WriteToSysLog("Error while waiting for OPERATIONAL state: %08lx\n", (unsigned long)rc); + return; + } + + /* + * Startup Phase has ended. + */ + UtAssert_EndTest(); + + /* + * Note - in a normal app this would be a while loop, + * but is just an "if" right now as it only runs once. + * + * A future enhancement to this app might be to create an SB pipe + * and execute tests based on the receipt of a command to do so. + * + * For now, it just works in a one-shot mode to run tests that were + * registered during startup, then it self-exits. + */ + RunStatus = CFE_ES_RunStatus_APP_RUN; + if (CFE_ES_RunLoop(&RunStatus)) + { + OS_TaskDelay(CFE_TESTRUNNER_START_DELAY); + + /* + * Run all registered test cases. + */ + UtTest_Run(); + + /* + * Exit the main task. + */ + RunStatus = CFE_ES_RunStatus_APP_EXIT; + } + + CFE_ES_ExitApp(RunStatus); +}