diff --git a/.gitmodules b/.gitmodules index 16cf7e2..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "externals/qpcpp"] - path = externals/qpcpp - url = https://github.com/QuantumLeaps/qpcpp.git diff --git a/CMakeLists.txt b/CMakeLists.txt index f878344..5cca402 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,21 +1,25 @@ cmake_minimum_required(VERSION 3.16) -project(cpputest-for-qpcpp) +project(cpputest-for-qpcpp-lib VERSION 1.0.1) +include(FetchContent) set(CMAKE_CXX_STANDARD 14) +set(CMAKE_C_STANDARD 11) add_compile_options(-Wall -Wextra -Werror) -include_directories(include) -include_directories(utilities/include) -include(externals/qpcppCMakeSupport.txt) +set(CMS_EXTERNALS_TOP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/externals) +set(CMS_CMAKE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cpputest-for-qpcpp-lib/cmake CACHE INTERNAL "") -set(TEST_SUPPORT_TOP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test_support) -set(MOCKS_TOP_DIR ${TEST_SUPPORT_TOP_DIR}/mocks) -set(SERVICES_TOP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/services) -set(EXTERNALS_TOP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/externals) -set(DRIVERS_TOP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/drivers) +if(NOT DEFINED CMS_QPCPP_TOP_DIR) + set(CMS_QPCPP_TOP_DIR ${CMS_EXTERNALS_TOP_DIR}/qpcpp) + FetchContent_Declare(qpcpp + GIT_REPOSITORY https://github.com/QuantumLeaps/qpcpp.git + GIT_TAG 6b7d766521a5c9681f61922a64027690721c2478 #7.2.1 + SOURCE_DIR ${CMS_QPCPP_TOP_DIR} + ) + message("Fetching QP/C++ git repository") + FetchContent_MakeAvailable(qpcpp) +endif(NOT DEFINED CMS_QPCPP_TOP_DIR) -add_subdirectory(utilities) -add_subdirectory(test_support) -add_subdirectory(drivers) -add_subdirectory(examples) +include(${CMS_CMAKE_DIR}/qpcppCMakeSupport.cmake) +add_subdirectory(cpputest-for-qpcpp-lib) diff --git a/LICENSE.txt b/LICENSE.txt index da2684b..73fcc0d 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,10 +1,13 @@ The software supporting this CppUTest port of the -QP/C++ Real-Time Embedded Framework is licensed under a -dual-licensing model. Most of the files present in this -repository are only needed for host PC based test execution. -However, a few of the examples and files may find their way -into a product's build. To request a commercial -license see contact information below. +QP/C++ Real-Time Embedded Framework (qpcpp) is licensed under a +dual-licensing model, with the default license being GPL. + +Most of the files present in this repository are only needed for +host PC based test execution. However, a few of the examples +and files may find their way into a product's build. + +To request a commercial license see contact information +below. Contact Information: ==================== diff --git a/README.md b/README.md index 3ae447b..07aebb0 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,15 @@ Build and Test status: ![Build and Tests](https://github.com/covemountainsoftwar Copyright Matthew Eshleman -If this project inspires your team to select the qpcpp +If this project inspires your team to select the QP/C++ (qpcpp) framework for commercial use, please note "Matthew Eshleman" or "Cove Mountain Software" in the referral field when acquiring a commercial license from Quantum Leaps. Referrals -encourage and support this effort. Thank you! +encourage and support efforts like this. Thank you! # Introduction -The `cpputest-for-qpcpp` project enables CppUTest for the +The `cpputest-for-qpcpp` library project enables CppUTest for the QP/C++ Real-Time Embedded Framework. This project provides for the following capabilities: @@ -46,22 +46,20 @@ Benefits of this approach to unit testing active objects include: # Environment -This project was developed and proven in Ubuntu 20.04. In theory any +This project was developed and proven in Ubuntu 20.04 and 22.04. In theory any build or host operating system environment supported by CppUTest will be compatible with this code. ## Prerequisites -* qpcpp (pulled in as a git submodule) - * After cloning this repository, do not forget to: - * `git submodule init` - * `git submodule update --recursive` - * NOTE: As of January 2023, qpcpp is also using submodules. Developers - may need to perform similar steps within the externals/qpcpp/ - directory as well. -* CppUTest (version 3.8-7, the default in Ubuntu 20.04) * CMake and associated build tools were used to develop and prove out this project. +* QP/C++ + * You can override the QP/C++ to another directory with your project's exact QP/C++ source code. + Define the cmake variable CMS_QPCPP_TOP_DIR before including the internal CMakeLists.txt. + * or: + * Do not define CMS_QPCPP_TOP_DIR, and the internal cmake will fetch the appropriate QP/C++ repo. +* CppUTest (version 3.8-7 or version 4.0) (3.8 is the default in Ubuntu 20.04 while 4.0 is the default in Ubuntu 22.04) * This project requires support for C++14. ## Continuous Integration @@ -131,13 +129,14 @@ behavior, using the exact same interfaces the active object would use in the production target. CppUTest provides for the mocking capabilities to ensure that the active object under test is calling the expected APIs. -Within this project, please see the tests for `cms::HwLockCtrl::Service` which +Within the associated examples project, please see the tests for `examples/hwLockCtrlService` which provides examples of: * Testing for reaction to a published event, where the reaction is observed through a CppUTest `mock()`. * Testing to ensure the active object published an expected event. This project provides for functionality (`cms::test::PublishedEventRecorder`) to record all - events published during a test. The recorded events can be retrieved and verified by the test. + events published during a test. The recorded events can be retrieved and verified + by the test. * Testing of time related behavior. This project provides for the ability to `MoveTimeForward` within a test. * Direct POST of events and testing of direct POST responses. See @@ -172,16 +171,16 @@ provides for convenience and helper methods such as: events published into the framework. Useful when a test expects an active object under test to publish an event. - ## The basic active object test pattern To create tests for an active object, the following outline is considered: 1. Implement the `setup()` handler for the test. Initialize the QF framework as desired using `cms::test::qf_ctrl::Setup(...)`. -2. Instantiate the active object under test. -3. `start` the active object under test. -4. Begin writing a test. +2. Instantiate or otherwise initialize the active object under test. +3. `start` the active object under test, perhaps as part of the `setup` + or as a separate step. +4. Prep a single test. 5. Prepare a CppUTest mock() or other resources as needed for the test. 6. Stimulate the unit under test as appropriate. For example, publish an event into the framework that the active object is expected to be subscribed to @@ -196,7 +195,7 @@ examples at: `examples/hwLockCtrlService/test/hwLockCtrlServiceTests.cpp` to learn more. Other tips: -* Avoid internal state knowledge as much as is reasonable. This allows for internal +* Avoid internal state knowledge as much as possible. This allows for internal state machine refactoring without impacting the tests. * Follow best practices in your test code, especially follow the DRY principle. diff --git a/cpputest-for-qpcpp-lib/CMakeLists.txt b/cpputest-for-qpcpp-lib/CMakeLists.txt new file mode 100644 index 0000000..85ff90c --- /dev/null +++ b/cpputest-for-qpcpp-lib/CMakeLists.txt @@ -0,0 +1,20 @@ +include_directories(include) +include_directories(${CMS_QPCPP_SRC_DIR}) +include_directories(${CMS_CPPUTEST_QP_PORT_TOP_DIR}/include) + +add_definitions(-DCPPUTEST_FOR_QPCPP_LIB_VERSION=\"${cpputest-for-qpcpp-lib_VERSION}\") + +add_library(cpputest-for-qpcpp-lib + src/cpputest_qf_port.cpp + src/cms_cpputest_qf_ctrl.cpp + src/cms_cpputest_q_onAssert.cpp + src/cms_cpputest_qf_onCleanup.cpp + src/cpputestMain.cpp + ${CMS_QPCPP_QF_SRCS}) + +add_subdirectory(tests) + +target_include_directories(cpputest-for-qpcpp-lib PUBLIC + ${CMS_QPCPP_INCLUDE_DIR} + include) + diff --git a/test_support/common/cpputestCMake.txt b/cpputest-for-qpcpp-lib/cmake/cpputestCMake.cmake similarity index 100% rename from test_support/common/cpputestCMake.txt rename to cpputest-for-qpcpp-lib/cmake/cpputestCMake.cmake diff --git a/cpputest-for-qpcpp-lib/cmake/qpcppCMakeSupport.cmake b/cpputest-for-qpcpp-lib/cmake/qpcppCMakeSupport.cmake new file mode 100644 index 0000000..bfc3b51 --- /dev/null +++ b/cpputest-for-qpcpp-lib/cmake/qpcppCMakeSupport.cmake @@ -0,0 +1,17 @@ +set(CMS_QPCPP_SRC_DIR ${CMS_QPCPP_TOP_DIR}/src) +set(CMS_QPCPP_INCLUDE_DIR ${CMS_QPCPP_TOP_DIR}/include) +set(CMS_QPCPP_QF_SRC_DIR ${CMS_QPCPP_SRC_DIR}/qf) + +set(CMS_QPCPP_QF_SRCS + ${CMS_QPCPP_QF_SRC_DIR}/qep_hsm.cpp + ${CMS_QPCPP_QF_SRC_DIR}/qep_msm.cpp + ${CMS_QPCPP_QF_SRC_DIR}/qf_act.cpp + ${CMS_QPCPP_QF_SRC_DIR}/qf_actq.cpp + ${CMS_QPCPP_QF_SRC_DIR}/qf_defer.cpp + ${CMS_QPCPP_QF_SRC_DIR}/qf_dyn.cpp + ${CMS_QPCPP_QF_SRC_DIR}/qf_mem.cpp + ${CMS_QPCPP_QF_SRC_DIR}/qf_ps.cpp + ${CMS_QPCPP_QF_SRC_DIR}/qf_qact.cpp + ${CMS_QPCPP_QF_SRC_DIR}/qf_qeq.cpp + ${CMS_QPCPP_QF_SRC_DIR}/qf_qmact.cpp + ${CMS_QPCPP_QF_SRC_DIR}/qf_time.cpp) diff --git a/cpputest-for-qpcpp-lib/cmake/qpcppPosixPortCMakeSupport.cmake b/cpputest-for-qpcpp-lib/cmake/qpcppPosixPortCMakeSupport.cmake new file mode 100644 index 0000000..494084a --- /dev/null +++ b/cpputest-for-qpcpp-lib/cmake/qpcppPosixPortCMakeSupport.cmake @@ -0,0 +1,2 @@ +include_directories(${CMS_QPCPP_TOP_DIR}/include) +include_directories(${CMS_QPCPP_TOP_DIR}/ports/posix) diff --git a/utilities/include/cmsArrayBackedQEQueue.hpp b/cpputest-for-qpcpp-lib/include/cmsArrayBackedQEQueue.hpp similarity index 100% rename from utilities/include/cmsArrayBackedQEQueue.hpp rename to cpputest-for-qpcpp-lib/include/cmsArrayBackedQEQueue.hpp diff --git a/test_support/cpputest-qpcpp-port/include/cmsDummyActiveObject.hpp b/cpputest-for-qpcpp-lib/include/cmsDummyActiveObject.hpp similarity index 100% rename from test_support/cpputest-qpcpp-port/include/cmsDummyActiveObject.hpp rename to cpputest-for-qpcpp-lib/include/cmsDummyActiveObject.hpp diff --git a/utilities/include/cmsOrthogonalComponent.hpp b/cpputest-for-qpcpp-lib/include/cmsOrthogonalComponent.hpp similarity index 100% rename from utilities/include/cmsOrthogonalComponent.hpp rename to cpputest-for-qpcpp-lib/include/cmsOrthogonalComponent.hpp diff --git a/utilities/include/cmsOrthogonalContainer.hpp b/cpputest-for-qpcpp-lib/include/cmsOrthogonalContainer.hpp similarity index 100% rename from utilities/include/cmsOrthogonalContainer.hpp rename to cpputest-for-qpcpp-lib/include/cmsOrthogonalContainer.hpp diff --git a/test_support/cpputest-qpcpp-port/include/cmsTestPublishedEventRecorder.hpp b/cpputest-for-qpcpp-lib/include/cmsTestPublishedEventRecorder.hpp similarity index 100% rename from test_support/cpputest-qpcpp-port/include/cmsTestPublishedEventRecorder.hpp rename to cpputest-for-qpcpp-lib/include/cmsTestPublishedEventRecorder.hpp diff --git a/utilities/include/cmsVectorBackedQEQueue.hpp b/cpputest-for-qpcpp-lib/include/cmsVectorBackedQEQueue.hpp similarity index 100% rename from utilities/include/cmsVectorBackedQEQueue.hpp rename to cpputest-for-qpcpp-lib/include/cmsVectorBackedQEQueue.hpp diff --git a/test_support/cpputest-qpcpp-port/include/cms_cpputest_qf_ctrl.hpp b/cpputest-for-qpcpp-lib/include/cms_cpputest_qf_ctrl.hpp similarity index 97% rename from test_support/cpputest-qpcpp-port/include/cms_cpputest_qf_ctrl.hpp rename to cpputest-for-qpcpp-lib/include/cms_cpputest_qf_ctrl.hpp index b3bea7f..ed94e80 100644 --- a/test_support/cpputest-qpcpp-port/include/cms_cpputest_qf_ctrl.hpp +++ b/cpputest-for-qpcpp-lib/include/cms_cpputest_qf_ctrl.hpp @@ -95,6 +95,10 @@ void PublishAndProcess(enum_t sig, void PublishAndProcess(QP::QEvt const * e, PublishedEventRecorder* recorder = nullptr); +/// Get the internal library version string. +/// Uses semantic versioning. +const char * GetVersion(); + } //namespace qf_ctrl } //namespace test } //namespace cms diff --git a/test_support/cpputest-qpcpp-port/include/qassertMockSupport.hpp b/cpputest-for-qpcpp-lib/include/qassertMockSupport.hpp similarity index 100% rename from test_support/cpputest-qpcpp-port/include/qassertMockSupport.hpp rename to cpputest-for-qpcpp-lib/include/qassertMockSupport.hpp diff --git a/test_support/cpputest-qpcpp-port/include/qep_port.hpp b/cpputest-for-qpcpp-lib/include/qep_port.hpp similarity index 100% rename from test_support/cpputest-qpcpp-port/include/qep_port.hpp rename to cpputest-for-qpcpp-lib/include/qep_port.hpp diff --git a/utilities/include/qevtUniquePtr.hpp b/cpputest-for-qpcpp-lib/include/qevtUniquePtr.hpp similarity index 100% rename from utilities/include/qevtUniquePtr.hpp rename to cpputest-for-qpcpp-lib/include/qevtUniquePtr.hpp diff --git a/test_support/cpputest-qpcpp-port/include/qf_port.hpp b/cpputest-for-qpcpp-lib/include/qf_port.hpp similarity index 100% rename from test_support/cpputest-qpcpp-port/include/qf_port.hpp rename to cpputest-for-qpcpp-lib/include/qf_port.hpp diff --git a/test_support/cpputest-qpcpp-port/include/safe_std.h b/cpputest-for-qpcpp-lib/include/safe_std.h similarity index 100% rename from test_support/cpputest-qpcpp-port/include/safe_std.h rename to cpputest-for-qpcpp-lib/include/safe_std.h diff --git a/test_support/cpputest-qpcpp-port/src/cms_cpputest_q_onAssert.cpp b/cpputest-for-qpcpp-lib/src/cms_cpputest_q_onAssert.cpp similarity index 100% rename from test_support/cpputest-qpcpp-port/src/cms_cpputest_q_onAssert.cpp rename to cpputest-for-qpcpp-lib/src/cms_cpputest_q_onAssert.cpp diff --git a/test_support/cpputest-qpcpp-port/src/cms_cpputest_qf_ctrl.cpp b/cpputest-for-qpcpp-lib/src/cms_cpputest_qf_ctrl.cpp similarity index 91% rename from test_support/cpputest-qpcpp-port/src/cms_cpputest_qf_ctrl.cpp rename to cpputest-for-qpcpp-lib/src/cms_cpputest_qf_ctrl.cpp index 735ace5..b01613c 100644 --- a/test_support/cpputest-qpcpp-port/src/cms_cpputest_qf_ctrl.cpp +++ b/cpputest-for-qpcpp-lib/src/cms_cpputest_qf_ctrl.cpp @@ -109,17 +109,19 @@ void Teardown() // Instead, we modified the QF port stop() method, which // internally will perform the memory check, as it has // friend access. - if (l_memPoolOption == MemPoolTeardownOption::CHECK_FOR_LEAKS) { - for (size_t i = 0; i < l_pubSubEventMemPoolConfigs->size(); ++i) { + if (l_pubSubEventMemPoolConfigs != nullptr) { + if (l_memPoolOption == MemPoolTeardownOption::CHECK_FOR_LEAKS) { + for (size_t i = 0; i < l_pubSubEventMemPoolConfigs->size(); ++i) { - const size_t poolNumOfEvents = l_pubSubEventMemPoolConfigs->at(i).config.numberOfEvents; + const size_t poolNumOfEvents = + l_pubSubEventMemPoolConfigs->at(i).config.numberOfEvents; - CHECK_TRUE_TEXT(poolNumOfEvents == QP::QF::ePool_[i].getNFree(), - "A leak was detected in an internal QF event pool!"); + CHECK_TRUE_TEXT( + poolNumOfEvents == QP::QF::ePool_[i].getNFree(), + "A leak was detected in an internal QF event pool!"); + } } - } - if (l_pubSubEventMemPoolConfigs != nullptr) { delete l_pubSubEventMemPoolConfigs; l_pubSubEventMemPoolConfigs = nullptr; } @@ -202,6 +204,11 @@ void CreatePoolConfigsFromArg(const MemPoolConfigs& pubSubEventMemPoolConfigs) } } +const char * GetVersion() +{ + return CPPUTEST_FOR_QPCPP_LIB_VERSION; +} + } // namespace qf_ctrl } // namespace test } // namespace cms diff --git a/test_support/cpputest-qpcpp-port/src/cms_cpputest_qf_onCleanup.cpp b/cpputest-for-qpcpp-lib/src/cms_cpputest_qf_onCleanup.cpp similarity index 100% rename from test_support/cpputest-qpcpp-port/src/cms_cpputest_qf_onCleanup.cpp rename to cpputest-for-qpcpp-lib/src/cms_cpputest_qf_onCleanup.cpp diff --git a/test_support/common/cpputestMain.cpp b/cpputest-for-qpcpp-lib/src/cpputestMain.cpp similarity index 100% rename from test_support/common/cpputestMain.cpp rename to cpputest-for-qpcpp-lib/src/cpputestMain.cpp diff --git a/test_support/cpputest-qpcpp-port/src/cpputest_qf_port.cpp b/cpputest-for-qpcpp-lib/src/cpputest_qf_port.cpp similarity index 100% rename from test_support/cpputest-qpcpp-port/src/cpputest_qf_port.cpp rename to cpputest-for-qpcpp-lib/src/cpputest_qf_port.cpp diff --git a/test_support/cpputest-qpcpp-port/test/CMakeLists.txt b/cpputest-for-qpcpp-lib/tests/CMakeLists.txt similarity index 54% rename from test_support/cpputest-qpcpp-port/test/CMakeLists.txt rename to cpputest-for-qpcpp-lib/tests/CMakeLists.txt index d1a94a6..7555c34 100644 --- a/test_support/cpputest-qpcpp-port/test/CMakeLists.txt +++ b/cpputest-for-qpcpp-lib/tests/CMakeLists.txt @@ -1,15 +1,18 @@ # prep for cpputest based build -set(TEST_APP_NAME cpputest-qpcpp-portTests) +set(TEST_APP_NAME cpputest-for-qpcpp-lib-tests) set(TEST_SOURCES qassertTests.cpp cms_cpputest_qf_ctrlTests.cpp cms_cpputest_qf_ctrlPublishTests.cpp publishedEventRecorderTests.cpp + backedQueueTests.cpp + orthogonalComponentTests.cpp + orthogonalContainerTests.cpp ) # this include expects TEST_SOURCES and TEST_APP_NAME to be # defined, and creates the cpputest based test executable target -include(${TEST_SUPPORT_TOP_DIR}/common/cpputestCMake.txt) +include(${CMS_CMAKE_DIR}/cpputestCMake.cmake) -target_link_libraries(${TEST_APP_NAME} cpputestqpcpplib ${CPPUTEST_LDFLAGS}) \ No newline at end of file +target_link_libraries(${TEST_APP_NAME} cpputest-for-qpcpp-lib ${CPPUTEST_LDFLAGS}) \ No newline at end of file diff --git a/utilities/test/backedQueueTests.cpp b/cpputest-for-qpcpp-lib/tests/backedQueueTests.cpp similarity index 100% rename from utilities/test/backedQueueTests.cpp rename to cpputest-for-qpcpp-lib/tests/backedQueueTests.cpp diff --git a/test_support/cpputest-qpcpp-port/test/cms_cpputest_qf_ctrlPublishTests.cpp b/cpputest-for-qpcpp-lib/tests/cms_cpputest_qf_ctrlPublishTests.cpp similarity index 100% rename from test_support/cpputest-qpcpp-port/test/cms_cpputest_qf_ctrlPublishTests.cpp rename to cpputest-for-qpcpp-lib/tests/cms_cpputest_qf_ctrlPublishTests.cpp diff --git a/test_support/cpputest-qpcpp-port/test/cms_cpputest_qf_ctrlTests.cpp b/cpputest-for-qpcpp-lib/tests/cms_cpputest_qf_ctrlTests.cpp similarity index 94% rename from test_support/cpputest-qpcpp-port/test/cms_cpputest_qf_ctrlTests.cpp rename to cpputest-for-qpcpp-lib/tests/cms_cpputest_qf_ctrlTests.cpp index d5dcbe3..766cd00 100644 --- a/test_support/cpputest-qpcpp-port/test/cms_cpputest_qf_ctrlTests.cpp +++ b/cpputest-for-qpcpp-lib/tests/cms_cpputest_qf_ctrlTests.cpp @@ -138,4 +138,13 @@ TEST(qf_ctrlTests, CHECK_EQUAL(1, sigOneCount); CHECK_EQUAL(3, sigTwoCount); +} + +TEST(qf_ctrlTests, qf_ctrl_provides_cpputest_for_qpcpp_lib_version) +{ + auto version = qf_ctrl::GetVersion(); + CHECK_TRUE(version != nullptr); + + std::string version_str(version); + CHECK_FALSE(version_str.empty()); } \ No newline at end of file diff --git a/utilities/test/orthogonalComponentTests.cpp b/cpputest-for-qpcpp-lib/tests/orthogonalComponentTests.cpp similarity index 100% rename from utilities/test/orthogonalComponentTests.cpp rename to cpputest-for-qpcpp-lib/tests/orthogonalComponentTests.cpp diff --git a/utilities/test/orthogonalContainerTests.cpp b/cpputest-for-qpcpp-lib/tests/orthogonalContainerTests.cpp similarity index 100% rename from utilities/test/orthogonalContainerTests.cpp rename to cpputest-for-qpcpp-lib/tests/orthogonalContainerTests.cpp diff --git a/test_support/cpputest-qpcpp-port/test/publishedEventRecorderTests.cpp b/cpputest-for-qpcpp-lib/tests/publishedEventRecorderTests.cpp similarity index 100% rename from test_support/cpputest-qpcpp-port/test/publishedEventRecorderTests.cpp rename to cpputest-for-qpcpp-lib/tests/publishedEventRecorderTests.cpp diff --git a/test_support/cpputest-qpcpp-port/test/qassertTests.cpp b/cpputest-for-qpcpp-lib/tests/qassertTests.cpp similarity index 100% rename from test_support/cpputest-qpcpp-port/test/qassertTests.cpp rename to cpputest-for-qpcpp-lib/tests/qassertTests.cpp diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt deleted file mode 100644 index 0f0fa27..0000000 --- a/drivers/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(hwLockCtrl) diff --git a/drivers/hwLockCtrl/CMakeLists.txt b/drivers/hwLockCtrl/CMakeLists.txt deleted file mode 100644 index ae96151..0000000 --- a/drivers/hwLockCtrl/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -include_directories(include) -add_library(hwLockCtrl include/hwLockCtrl.h src/hwLockCtrl.c) -target_include_directories(hwLockCtrl PUBLIC include) diff --git a/drivers/hwLockCtrl/include/hwLockCtrl.h b/drivers/hwLockCtrl/include/hwLockCtrl.h deleted file mode 100644 index 873c99b..0000000 --- a/drivers/hwLockCtrl/include/hwLockCtrl.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -MIT License - -Copyright (c) <2019-2020> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** - * @brief public header for the Hw Lock Ctrl driver. - * This driver controls a physical electronic - * controlled hardware lock. - * - * The driver API is fully synchronous. - */ -#ifndef ACTIVEOBJECTUNITTESTINGDEMO_HWLOCKCTRL_H -#define ACTIVEOBJECTUNITTESTINGDEMO_HWLOCKCTRL_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief HwLockCtrlSelfTestResult enumerates - * possible self test results. - */ -typedef enum HwLockCtrlSelfTestResult -{ - HW_LOCK_CTRL_SELF_TEST_PASSED, - HW_LOCK_CTRL_SELF_TEST_FAILED_POWER, - HW_LOCK_CTRL_SELF_TEST_FAILED_MOTOR, -} HwLockCtrlSelfTestResultT; - -/** - * @brief HwLockCtrlInit initializes the driver. Lock state is undefined. - * @return true - initialization completed successfully. - * false - some error. - */ -bool HwLockCtrlInit(); - -/** - * @brief HwLockCtrlLock locks the lock. - * @return true - lock operation completed successfully - * false - some error. - */ -bool HwLockCtrlLock(); - -/** - * @brief HwLockCtrlUnlock unlocks the lock. - * @return true - unlock operation completed successfully - * false - some error. - */ -bool HwLockCtrlUnlock(); - -/** - * @brief HwLockCtrlSelfTest executes a self test. When completed, the Lock is always LOCKED. - * @arg outResult: [out] output the self test results - * @return true - self test completed and results are available in 'outResult' - * false - self test failed to execute. - */ -bool HwLockCtrlSelfTest(HwLockCtrlSelfTestResultT* outResult); - -/** - * @brief HwLockCtrlIsCommOk Confirms communications with the lock without changing lock state. - * @return true - all good. - * false - some unexpected error or communication failed. - */ -bool HwLockCtrlIsCommOk(); - -#ifdef __cplusplus -} -#endif - -#endif //ACTIVEOBJECTUNITTESTINGDEMO_HWLOCKCTRL_H diff --git a/drivers/hwLockCtrl/src/hwLockCtrl.c b/drivers/hwLockCtrl/src/hwLockCtrl.c deleted file mode 100644 index 95a0207..0000000 --- a/drivers/hwLockCtrl/src/hwLockCtrl.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This concrete implementation of the LockCtrl "C" style interface - * is for demo purposes only. The focus of this project - * is how to test state machines and active objects, hence - * this fake hardware driver module. - */ -#include "hwLockCtrl.h" -#include - -bool HwLockCtrlInit() -{ - printf("%s() executed\n", __FUNCTION__); - return true; -} - -bool HwLockCtrlLock() -{ - printf("%s() executed\n", __FUNCTION__); - return true; -} - -bool HwLockCtrlUnlock() -{ - printf("%s() executed\n", __FUNCTION__); - return true; -} - -bool HwLockCtrlSelfTest(HwLockCtrlSelfTestResultT* outResult) -{ - printf("%s() executed\n", __FUNCTION__); - if (outResult) - { - *outResult = HW_LOCK_CTRL_SELF_TEST_PASSED; - return true; - } - else - { - printf("%s() executed with nullptr arg\n", __FUNCTION__); - return false; - } -} - -bool HwLockCtrlIsCommOk() -{ - printf("%s() executed\n", __FUNCTION__); - return true; -} diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt deleted file mode 100644 index 433f7fb..0000000 --- a/examples/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -include_directories(include) -add_subdirectory(hwLockCtrlService) diff --git a/examples/hwLockCtrlService/CMakeLists.txt b/examples/hwLockCtrlService/CMakeLists.txt deleted file mode 100644 index 5e4f2c8..0000000 --- a/examples/hwLockCtrlService/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -include_directories(include) -add_subdirectory(test) -add_library(hwLockCtrlService include/hwLockCtrlService.hpp src/hwLockCtrlService.cpp) -target_link_libraries(hwLockCtrlService hwLockCtrl) -target_include_directories(hwLockCtrlService PUBLIC include) - -# TODO: setting up QP should probably be a higher level build option -include_directories(${QP_CPP_INCLUDE_DIR}) -include(${EXTERNALS_TOP_DIR}/qpcppPosixPortCMakeSupport.txt) diff --git a/examples/hwLockCtrlService/include/hwLockCtrlSelfTestEvent.hpp b/examples/hwLockCtrlService/include/hwLockCtrlSelfTestEvent.hpp deleted file mode 100644 index e980938..0000000 --- a/examples/hwLockCtrlService/include/hwLockCtrlSelfTestEvent.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/// @brief The HwLockCtrl Self Test Event class. -/// @ingroup -/// @cond -///*************************************************************************** -/// -/// Copyright (C) 2022 Matthew Eshleman. All rights reserved. -/// -/// This program is open source software: you can redistribute it and/or -/// modify it under the terms of the GNU General Public License as published -/// by the Free Software Foundation, either version 3 of the License, or -/// (at your option) any later version. -/// -/// Alternatively, upon written permission from Matthew Eshleman, this program -/// may be distributed and modified under the terms of a Commercial -/// License. For further details, see the Contact Information below. -/// -/// Contact Information: -/// Matthew Eshleman -/// https://covemountainsoftware.com -/// info@covemountainsoftware.com -///*************************************************************************** -/// @endcond - -#ifndef HWLOCKCTRLSELFTESTEVENT_HPP -#define HWLOCKCTRLSELFTESTEVENT_HPP - -#include "qpcpp.hpp" -#include "hwLockCtrlSelfTestResultEnum.hpp" - -namespace cms { -namespace HwLockCtrl { - -/// event type holding the results of a -/// HwLockCtrl Service Self Test. -/// note the handy 'publish' static method. -class SelfTestEvent : public QP::QEvt { -public: - SelfTestResult m_result; - - explicit SelfTestEvent(SelfTestResult result) : QP::QEvt(), m_result(result) - { - } - - template static void publish(SelfTestResult result) - { - auto e = Q_NEW(SelfTestEvent, sig); - e->m_result = result; - QP::QF::PUBLISH(e, nullptr); - } -}; - -} // namespace HwLockCtrl -} // namespace cms -#endif // HWLOCKCTRLSELFTESTEVENT_HPP diff --git a/examples/hwLockCtrlService/include/hwLockCtrlSelfTestResultEnum.hpp b/examples/hwLockCtrlService/include/hwLockCtrlSelfTestResultEnum.hpp deleted file mode 100644 index 0919572..0000000 --- a/examples/hwLockCtrlService/include/hwLockCtrlSelfTestResultEnum.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/// @brief The HwLockCtrl Self Test Result Enum. -/// @ingroup -/// @cond -///*************************************************************************** -/// -/// Copyright (C) 2022 Matthew Eshleman. All rights reserved. -/// -/// This program is open source software: you can redistribute it and/or -/// modify it under the terms of the GNU General Public License as published -/// by the Free Software Foundation, either version 3 of the License, or -/// (at your option) any later version. -/// -/// Alternatively, upon written permission from Matthew Eshleman, this program -/// may be distributed and modified under the terms of a Commercial -/// License. For further details, see the Contact Information below. -/// -/// Contact Information: -/// Matthew Eshleman -/// https://covemountainsoftware.com -/// info@covemountainsoftware.com -///*************************************************************************** -/// @endcond - -#ifndef HWLOCKCTRLSELFTESTRESULTENUM_HPP -#define HWLOCKCTRLSELFTESTRESULTENUM_HPP - -namespace cms { -namespace HwLockCtrl { - -enum class SelfTestResult { - PASS, - FAIL, -}; - -} -} // namespace cms - -#endif // HWLOCKCTRLSELFTESTRESULTENUM_HPP diff --git a/examples/hwLockCtrlService/include/hwLockCtrlService.hpp b/examples/hwLockCtrlService/include/hwLockCtrlService.hpp deleted file mode 100644 index 9845343..0000000 --- a/examples/hwLockCtrlService/include/hwLockCtrlService.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/// @file hwLockCtrlService.hpp -/// @brief A service (active object) for demonstrating cpputest host -/// based unit testing. -/// @ingroup -/// @cond -///*************************************************************************** -/// -/// Copyright (C) 2022 Matthew Eshleman. All rights reserved. -/// -/// This program is open source software: you can redistribute it and/or -/// modify it under the terms of the GNU General Public License as published -/// by the Free Software Foundation, either version 3 of the License, or -/// (at your option) any later version. -/// -/// Alternatively, upon written permission from Matthew Eshleman, this program -/// may be distributed and modified under the terms of a Commercial -/// License. For further details, see the Contact Information below. -/// -/// Contact Information: -/// Matthew Eshleman -/// https://covemountainsoftware.com -/// info@covemountainsoftware.com -///*************************************************************************** -/// @endcond - -#ifndef DEMO_HWLOCKCTRLSERVICE_HPP -#define DEMO_HWLOCKCTRLSERVICE_HPP - -#include -#include "qpcpp.hpp" -#include "hwLockCtrlSelfTestResultEnum.hpp" -#include "pubsub_signals.hpp" - -namespace cms { -namespace HwLockCtrl { - -/** - * @brief the HwLockCtrl::Service demonstration active object provides for - * higher level hardware lock control behavior. - * For example, this service will automatically return the hardware lock - * to its last state after completing a self test request. - */ -class Service final : public QP::QActive { -public: - enum class LockState { UNKNOWN, LOCKED, UNLOCKED }; - - enum DirectSignals { PING = PubSub::MAX_PUB_SIG, MAX_DIRECT_SIG }; - - Service(); - ~Service() = default; - - Service(const Service&) = delete; - Service& operator=(const Service&) = delete; - Service(Service&&) = delete; - Service& operator=(Service&&) = delete; - -protected: - enum InternalSignals { - REQUEST_GOTO_HISTORY = DirectSignals::MAX_DIRECT_SIG, - POLL_COMM_STATUS - }; - - Q_STATE_DECL(initial); - Q_STATE_DECL(common); - Q_STATE_DECL(locked); - Q_STATE_DECL(unlocked); - Q_STATE_DECL(selftest); - -private: - static void notifySelfTestResult(SelfTestResult result); - void notifyChangedState(LockState state); - void performSelfTest(); - - QP::QStateHandler m_history; - QP::QTimeEvt m_poll; -}; -} // namespace HwLockCtrl -} // namespace cms - -#endif // DEMO_HWLOCKCTRLSERVICE_HPP diff --git a/examples/hwLockCtrlService/include/hwLockCtrlServiceExpectedPubSubSigs.hpp b/examples/hwLockCtrlService/include/hwLockCtrlServiceExpectedPubSubSigs.hpp deleted file mode 100644 index b7482e8..0000000 --- a/examples/hwLockCtrlService/include/hwLockCtrlServiceExpectedPubSubSigs.hpp +++ /dev/null @@ -1,8 +0,0 @@ - -HW_LOCK_CTRL_SERVICE_REQUEST_UNLOCKED_SIG, -HW_LOCK_CTRL_SERVICE_REQUEST_LOCKED_SIG, -HW_LOCK_CTRL_SERVICE_REQUEST_SELF_TEST_SIG, - -HW_LOCK_CTRL_SERVICE_IS_UNLOCKED_SIG, -HW_LOCK_CTRL_SERVICE_IS_LOCKED_SIG, -HW_LOCK_CTRL_SERVICE_SELF_TEST_RESULTS_SIG, //uses event type HwLockCtrl::SelfTestEvent diff --git a/examples/hwLockCtrlService/src/hwLockCtrlService.cpp b/examples/hwLockCtrlService/src/hwLockCtrlService.cpp deleted file mode 100644 index 51ede30..0000000 --- a/examples/hwLockCtrlService/src/hwLockCtrlService.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/// @brief A sample/demonstration QActive based service used -/// to demonstrate host based unit testing of an active object -/// @ingroup -/// @cond -///*************************************************************************** -/// -/// Copyright (C) 2022 Matthew Eshleman. All rights reserved. -/// -/// This program is open source software: you can redistribute it and/or -/// modify it under the terms of the GNU General Public License as published -/// by the Free Software Foundation, either version 3 of the License, or -/// (at your option) any later version. -/// -/// Alternatively, upon written permission from Matthew Eshleman, this program -/// may be distributed and modified under the terms of a Commercial -/// License. For further details, see the Contact Information below. -/// -/// Contact Information: -/// Matthew Eshleman -/// https://covemountainsoftware.com -/// info@covemountainsoftware.com -///*************************************************************************** -/// @endcond - -#include "hwLockCtrlService.hpp" -#include "hwLockCtrl.h" -#include "pubsub_signals.hpp" -#include "hwLockCtrlSelfTestEvent.hpp" -#include "pingPongEvents.hpp" -#include "bspTicks.hpp" -#include "qassert.h" - -Q_DEFINE_THIS_MODULE("hwLockCtrlService"); - -using namespace PubSub; - -namespace cms { -namespace HwLockCtrl { - -// 10 second polling rate -static constexpr uint32_t TICKS_PER_POLL = bsp::TICKS_PER_SECOND * 10; - -Service::Service() : - QActive(initial), - m_history(nullptr), - m_poll(this, POLL_COMM_STATUS) -{ -} - -Q_STATE_DEF(Service, initial) -{ - (void)e; - HwLockCtrlInit(); - subscribe(HW_LOCK_CTRL_SERVICE_REQUEST_SELF_TEST_SIG); - subscribe(HW_LOCK_CTRL_SERVICE_REQUEST_LOCKED_SIG); - subscribe(HW_LOCK_CTRL_SERVICE_REQUEST_UNLOCKED_SIG); - return tran(&common); -} - -Q_STATE_DEF(Service, common) -{ - QP::QState rtn; - switch (e->sig) { - case Q_INIT_SIG: - rtn = tran(locked); - break; - case Q_ENTRY_SIG: - m_poll.armX(TICKS_PER_POLL, TICKS_PER_POLL); - rtn = Q_RET_HANDLED; - break; - case Q_EXIT_SIG: - rtn = Q_RET_HANDLED; - break; - case HW_LOCK_CTRL_SERVICE_REQUEST_SELF_TEST_SIG: - rtn = tran(selftest); - break; - case HW_LOCK_CTRL_SERVICE_REQUEST_LOCKED_SIG: - rtn = tran(locked); - break; - case HW_LOCK_CTRL_SERVICE_REQUEST_UNLOCKED_SIG: - rtn = tran(unlocked); - break; - case POLL_COMM_STATUS: - // this is just to demonstrate unit testing of time - // based functionality. Perhaps a real module would - // publish a result if this fails, etc. - HwLockCtrlIsCommOk(); - rtn = Q_RET_HANDLED; - break; - case DEMONSTRATE_TEST_OF_QASSERT: - // demonstrate testing assertions from cpputest - Q_ASSERT(true == false); - rtn = Q_RET_HANDLED; - break; - case DirectSignals::PING: { - auto ping = static_cast(e); - Pong::sendTo(ping->m_requester, ping->responseSig, this); - rtn = Q_RET_HANDLED; - } break; - default: - rtn = super(&top); - break; - } - - return rtn; -} - -Q_STATE_DEF(Service, locked) -{ - QP::QState rtn; - switch (e->sig) { - case Q_ENTRY_SIG: - HwLockCtrlLock(); - notifyChangedState(LockState::LOCKED); - rtn = Q_RET_HANDLED; - break; - case Q_EXIT_SIG: - rtn = Q_RET_HANDLED; - break; - case HW_LOCK_CTRL_SERVICE_REQUEST_LOCKED_SIG: - rtn = Q_RET_HANDLED; - break; - default: - rtn = super(&common); - break; - } - - return rtn; -} - -Q_STATE_DEF(Service, unlocked) -{ - QP::QState rtn; - switch (e->sig) { - case Q_ENTRY_SIG: - HwLockCtrlUnlock(); - notifyChangedState(LockState::UNLOCKED); - rtn = Q_RET_HANDLED; - break; - case Q_EXIT_SIG: - rtn = Q_RET_HANDLED; - break; - case HW_LOCK_CTRL_SERVICE_REQUEST_UNLOCKED_SIG: - rtn = Q_RET_HANDLED; - break; - default: - rtn = super(&common); - break; - } - - return rtn; -} - -Q_STATE_DEF(Service, selftest) -{ - QP::QState rtn; - switch (e->sig) { - case Q_ENTRY_SIG: - performSelfTest(); - rtn = Q_RET_HANDLED; - break; - case REQUEST_GOTO_HISTORY: - rtn = tran_hist(m_history); - break; - case HW_LOCK_CTRL_SERVICE_REQUEST_SELF_TEST_SIG: - rtn = Q_RET_HANDLED; - break; - case POLL_COMM_STATUS: - // drop during self test - rtn = Q_RET_HANDLED; - break; - default: - rtn = super(&common); - break; - } - - return rtn; -} - -void Service::performSelfTest() -{ - HwLockCtrlSelfTestResult result; - bool ok = HwLockCtrlSelfTest(&result); - if (ok && (result == HW_LOCK_CTRL_SELF_TEST_PASSED)) { - notifySelfTestResult(SelfTestResult::PASS); - } - else { - notifySelfTestResult(SelfTestResult::FAIL); - } - - // remind self to transition back to - // history per this service's requirements - // note the use of "postLIFO" (urgent) as per: - // - // https://covemountainsoftware.com/2020/03/08/uml-statechart-handling-errors-when-entering-a-state/ - // - static const QP::QEvt event = {REQUEST_GOTO_HISTORY, 0U, 0U}; - postLIFO(&event); -} - -void Service::notifyChangedState(Service::LockState state) -{ - static const QP::QEvt lockedEvent = {HW_LOCK_CTRL_SERVICE_IS_LOCKED_SIG, 0U, - 0U}; - static const QP::QEvt unlockedEvent = {HW_LOCK_CTRL_SERVICE_IS_UNLOCKED_SIG, - 0U, 0U}; - - switch (state) { - case LockState::LOCKED: - QP::QF::PUBLISH(&lockedEvent, this); - m_history = &locked; - break; - case LockState::UNLOCKED: - QP::QF::PUBLISH(&unlockedEvent, this); - m_history = &unlocked; - break; - default: - Q_ASSERT(true == false); - break; - } -} - -void Service::notifySelfTestResult(SelfTestResult result) -{ - switch (result) { - case SelfTestResult::PASS: // fall through on purpose - case SelfTestResult::FAIL: - SelfTestEvent::publish( - result); - break; - default: - Q_ASSERT(true == false); - break; - } -} - -} // namespace HwLockCtrl -} // namespace cms \ No newline at end of file diff --git a/examples/hwLockCtrlService/test/CMakeLists.txt b/examples/hwLockCtrlService/test/CMakeLists.txt deleted file mode 100644 index 5488f32..0000000 --- a/examples/hwLockCtrlService/test/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ - -# prep for cpputest based build -set(TEST_APP_NAME HwLockCtrlServiceTests) - -include_directories(${DRIVERS_TOP_DIR}/hwLockCtrl/include) - -#note: we are building and linking with the MOCK LockCtrl module, instead -# of the actual LockCtrl driver. We must also pull in -# sources for cpputest execution and QP and our fake port of QP -set(TEST_SOURCES - hwLockCtrlServiceTests.cpp - ../src/hwLockCtrlService.cpp - ${MOCKS_TOP_DIR}/hwLockCtrl/mockHwLockCtrl.cpp) - -# this include expects TEST_SOURCES and TEST_APP_NAME to be -# defined, and creates the cpputest based test executable target -include(${TEST_SUPPORT_TOP_DIR}/common/cpputestCMake.txt) - -target_link_libraries(${TEST_APP_NAME} cpputestqpcpplib ${CPPUTEST_LDFLAGS}) \ No newline at end of file diff --git a/examples/hwLockCtrlService/test/hwLockCtrlServiceTests.cpp b/examples/hwLockCtrlService/test/hwLockCtrlServiceTests.cpp deleted file mode 100644 index 80437d9..0000000 --- a/examples/hwLockCtrlService/test/hwLockCtrlServiceTests.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/// @brief Tests for the HwLockCtrl::Service, demonstrating various unit -/// testing capabilities of the 'fake' cms::test::qf_ctrl environment, -/// using cpputest. -/// @ingroup -/// @cond -///*************************************************************************** -/// -/// Copyright (C) 2022 Matthew Eshleman. All rights reserved. -/// -/// This program is open source software: you can redistribute it and/or -/// modify it under the terms of the GNU General Public License as published -/// by the Free Software Foundation, either version 3 of the License, or -/// (at your option) any later version. -/// -/// Alternatively, upon written permission from Matthew Eshleman, this program -/// may be distributed and modified under the terms of a Commercial -/// License. For further details, see the Contact Information below. -/// -/// Contact Information: -/// Matthew Eshleman -/// https://covemountainsoftware.com -/// info@covemountainsoftware.com -///*************************************************************************** -/// @endcond - -#include -#include -#include "hwLockCtrl.h" -#include "pubsub_signals.hpp" -#include "hwLockCtrlService.hpp" -#include "cms_cpputest_qf_ctrl.hpp" -#include "cmsTestPublishedEventRecorder.hpp" -#include "hwLockCtrlSelfTestEvent.hpp" -#include "bspTicks.hpp" -#include "qassertMockSupport.hpp" -#include "pingPongEvents.hpp" -#include "cmsDummyActiveObject.hpp" - -// the cpputest headers must always be last -#include "CppUTest/TestHarness.h" -#include "CppUTestExt/MockSupport.h" - -static constexpr const char* HW_LOCK_CTRL_MOCK = "HwLockCtrl"; - -using namespace PubSub; -using namespace cms; -using namespace cms::test; - -static std::array testQueueStorage; - -/** - * @brief These tests demonstrate the following key points: - * 1) Does NOT test any thread that may be associated with the active - * object, rather, the associated cms:test::qf_ctrl environment is - * thread free, and "faked" to required the test to drive - * processing time. - * 2) Tests the internal behavior of the active object without - * knowledge of the internal state machine. Rather, only - * by observing the behavior and associated output/results. - * 3) Follow software engineering best practices, such - * as adhering to the DRY principle. - * 4) Shows how to test if an event was published to the QP framework, - * using a published event recorder available from - * cms::test::qf_ctrl. - * 5) Shows how to test if a published event has a custom type and - * payload. - * 6) Shows how to test behavior driven by QActive timers (i.e. how - * to test the forward movement of time and expected behavior being - * tested.) - */ -TEST_GROUP(HwLockCtrlServiceTests) -{ - HwLockCtrl::Service* mUnderTest = nullptr; - test::PublishedEventRecorder* mRecorder = nullptr; - - void setup() final - { - using namespace cms::test; - qf_ctrl::Setup(MAX_PUB_SIG, bsp::TICKS_PER_SECOND); - mRecorder = cms::test::PublishedEventRecorder::CreatePublishedEventRecorder( - qf_ctrl::RECORDER_PRIORITY, QP::Q_USER_SIG, MAX_PUB_SIG); - mUnderTest = new HwLockCtrl::Service(); - } - - void teardown() final - { - delete mUnderTest; - mock().clear(); - qf_ctrl::Teardown(); - delete mRecorder; - } - - void startServiceToLocked() - { - // setup mock to ensure the service under test calls the driver - // API as expected. - mock(HW_LOCK_CTRL_MOCK).expectOneCall("Init"); - mock(HW_LOCK_CTRL_MOCK).expectOneCall("Lock"); - - // start the active object under test. - mUnderTest->start(qf_ctrl::UNIT_UNDER_TEST_PRIORITY, - testQueueStorage.data(), testQueueStorage.size(), - nullptr, 0U); - - // give the system some processing time to handle - // any internal or queued events - giveProcessingTime(); - - // check that the driver/mock interactions were all as expected. - mock().checkExpectations(); - - // check that the event recorder captured the expected published event - CHECK_TRUE( - mRecorder->isSignalRecorded(HW_LOCK_CTRL_SERVICE_IS_LOCKED_SIG)); - } - - void startServiceToUnlocked() - { - startServiceToLocked(); - testUnlock(); - } - - void testUnlock() - { - mock(HW_LOCK_CTRL_MOCK).expectOneCall("Unlock"); - qf_ctrl::PublishAndProcess(HW_LOCK_CTRL_SERVICE_REQUEST_UNLOCKED_SIG, - mRecorder); - mock().checkExpectations(); - CHECK_TRUE( - mRecorder->isSignalRecorded(HW_LOCK_CTRL_SERVICE_IS_UNLOCKED_SIG)); - } - - void giveProcessingTime() - { - qf_ctrl::ProcessEvents(); - } -}; - -TEST(HwLockCtrlServiceTests, given_init_when_created_then_does_not_crash) -{ - // setup() is automatically called by cpputest, which creates our unit under - // test fully representing this trivial starting test. -} - -TEST(HwLockCtrlServiceTests, - given_startup_when_started_then_service_ensures_the_lock_is_locked) -{ - // When originally developed, this test contained all the code - // in the below helper method. Since this "setup" was needed by - // other tests, it was extracted into a helper method. - // This pattern of developing tests, discovering the need for common - // setup helper methods, takes place throughout coding of these unit tests, - // and represents adhering to the DRY principle, even in our unit testing - // code. - startServiceToLocked(); -} - -TEST(HwLockCtrlServiceTests, - given_locked_when_another_lock_request_then_service_is_silent) -{ - startServiceToLocked(); - qf_ctrl::PublishAndProcess(HW_LOCK_CTRL_SERVICE_REQUEST_LOCKED_SIG, - mRecorder); - CHECK_TRUE(mRecorder->isEmpty()); - mock().checkExpectations(); -} - -TEST(HwLockCtrlServiceTests, - given_locked_when_unlock_request_then_service_unlocks_the_driver) -{ - startServiceToLocked(); - testUnlock(); -} - -TEST(HwLockCtrlServiceTests, - given_unlocked_when_another_unlock_request_then_service_is_silent) -{ - startServiceToUnlocked(); - qf_ctrl::PublishAndProcess(HW_LOCK_CTRL_SERVICE_REQUEST_UNLOCKED_SIG, - mRecorder); - CHECK_TRUE(mRecorder->isEmpty()); - mock().checkExpectations(); -} - -TEST(HwLockCtrlServiceTests, - given_unlocked_a_lock_request_will_return_to_locked) -{ - startServiceToUnlocked(); - mock(HW_LOCK_CTRL_MOCK).expectOneCall("Lock"); - qf_ctrl::PublishAndProcess(HW_LOCK_CTRL_SERVICE_REQUEST_LOCKED_SIG, - mRecorder); - CHECK_TRUE(mRecorder->isSignalRecorded(HW_LOCK_CTRL_SERVICE_IS_LOCKED_SIG)); - mock().checkExpectations(); -} - -TEST(HwLockCtrlServiceTests, - given_locked_when_selftest_requested_then_service_performs_selftest_publishes_results_and_returns_to_locked) -{ - startServiceToLocked(); - - auto passed = HW_LOCK_CTRL_SELF_TEST_PASSED; - mock(HW_LOCK_CTRL_MOCK) - .expectOneCall("SelfTest") - .withOutputParameterReturning("outResult", &passed, sizeof(passed)); - mock(HW_LOCK_CTRL_MOCK).expectOneCall("Lock"); - qf_ctrl::PublishAndProcess(HW_LOCK_CTRL_SERVICE_REQUEST_SELF_TEST_SIG, - mRecorder); - mock().checkExpectations(); - auto event = mRecorder->getRecordedEvent(); - CHECK_TRUE(event != nullptr); - CHECK_EQUAL(HW_LOCK_CTRL_SERVICE_SELF_TEST_RESULTS_SIG, event->sig); - CHECK_TRUE(HwLockCtrl::SelfTestResult::PASS == event->m_result); - CHECK_TRUE(mRecorder->isSignalRecorded(HW_LOCK_CTRL_SERVICE_IS_LOCKED_SIG)); -} - -TEST(HwLockCtrlServiceTests, - given_unlocked_when_selftest_request_then_service_performs_selftest_emits_results_and_returns_to_unlocked) -{ - startServiceToUnlocked(); - - auto passed = HW_LOCK_CTRL_SELF_TEST_PASSED; - mock(HW_LOCK_CTRL_MOCK) - .expectOneCall("SelfTest") - .withOutputParameterReturning("outResult", &passed, sizeof(passed)); - mock(HW_LOCK_CTRL_MOCK).expectOneCall("Unlock"); - qf_ctrl::PublishAndProcess(HW_LOCK_CTRL_SERVICE_REQUEST_SELF_TEST_SIG, - mRecorder); - mock().checkExpectations(); - auto event = mRecorder->getRecordedEvent(); - CHECK_TRUE(event != nullptr); - CHECK_EQUAL(HW_LOCK_CTRL_SERVICE_SELF_TEST_RESULTS_SIG, event->sig); - CHECK_TRUE(HwLockCtrl::SelfTestResult::PASS == event->m_result); - CHECK_TRUE( - mRecorder->isSignalRecorded(HW_LOCK_CTRL_SERVICE_IS_UNLOCKED_SIG)); -} - -TEST(HwLockCtrlServiceTests, - given_locked_when_selftest_request_which_fails_then_service_still_returns_to_locked) -{ - startServiceToLocked(); - - auto passed = HW_LOCK_CTRL_SELF_TEST_FAILED_POWER; - mock(HW_LOCK_CTRL_MOCK) - .expectOneCall("SelfTest") - .withOutputParameterReturning("outResult", &passed, sizeof(passed)); - mock(HW_LOCK_CTRL_MOCK).expectOneCall("Lock"); - qf_ctrl::PublishAndProcess(HW_LOCK_CTRL_SERVICE_REQUEST_SELF_TEST_SIG, - mRecorder); - mock().checkExpectations(); - auto event = mRecorder->getRecordedEvent(); - CHECK_TRUE(event != nullptr); - CHECK_EQUAL(HW_LOCK_CTRL_SERVICE_SELF_TEST_RESULTS_SIG, event->sig); - CHECK_TRUE(HwLockCtrl::SelfTestResult::FAIL == event->m_result); - CHECK_TRUE(mRecorder->isSignalRecorded(HW_LOCK_CTRL_SERVICE_IS_LOCKED_SIG)); -} - -TEST(HwLockCtrlServiceTests, - given_unlocked_when_selftest_request_which_fails_then_service_still_returns_to_unlocked) -{ - startServiceToUnlocked(); - - auto passed = HW_LOCK_CTRL_SELF_TEST_FAILED_MOTOR; - mock(HW_LOCK_CTRL_MOCK) - .expectOneCall("SelfTest") - .withOutputParameterReturning("outResult", &passed, sizeof(passed)); - mock(HW_LOCK_CTRL_MOCK).expectOneCall("Unlock"); - qf_ctrl::PublishAndProcess(HW_LOCK_CTRL_SERVICE_REQUEST_SELF_TEST_SIG, - mRecorder); - mock().checkExpectations(); - auto event = mRecorder->getRecordedEvent(); - CHECK_TRUE(event != nullptr); - CHECK_EQUAL(HW_LOCK_CTRL_SERVICE_SELF_TEST_RESULTS_SIG, event->sig); - CHECK_TRUE(HwLockCtrl::SelfTestResult::FAIL == event->m_result); - CHECK_TRUE( - mRecorder->isSignalRecorded(HW_LOCK_CTRL_SERVICE_IS_UNLOCKED_SIG)); -} - -TEST(HwLockCtrlServiceTests, - given_locked_when_10secs_passes_then_service_polls_lock_comm_status) -{ - using namespace std::chrono_literals; - - startServiceToLocked(); - mock(HW_LOCK_CTRL_MOCK).expectOneCall("IsCommOk"); - qf_ctrl::MoveTimeForward(10s); - mock().checkExpectations(); -} - -TEST(HwLockCtrlServiceTests, - given_locked_when_9900ms_passes_then_service_has_not_polled_yet) -{ - using namespace std::chrono_literals; - - startServiceToLocked(); - mock(HW_LOCK_CTRL_MOCK).expectNoCall("IsCommOk"); - qf_ctrl::MoveTimeForward(9900ms); - mock().checkExpectations(); - - // while here, lets see if it calls the driver upon hitting the 10s mark. - mock(HW_LOCK_CTRL_MOCK).expectOneCall("IsCommOk"); - qf_ctrl::MoveTimeForward(100ms); - mock().checkExpectations(); -} - -TEST(HwLockCtrlServiceTests, - given_locked_when_60s_passes_then_service_has_polled_six_times) -{ - using namespace std::chrono_literals; - - // Demo multiple events over time, and confirm that the - // service is polling in an ongoing manner. - - startServiceToLocked(); - mock(HW_LOCK_CTRL_MOCK).expectNCalls(6, "IsCommOk"); - qf_ctrl::MoveTimeForward(60s); - mock().checkExpectations(); -} - -TEST(HwLockCtrlServiceTests, - given_test_assert_event_will_assert_and_can_be_tested) -{ - static const QP::QEvt assertCausingEvent {DEMONSTRATE_TEST_OF_QASSERT, 0, - 0}; - - startServiceToLocked(); - - cms::test::MockExpectQAssert(); - mUnderTest->POST(&assertCausingEvent, 0); - giveProcessingTime(); - mock().checkExpectations(); -} - -TEST(HwLockCtrlServiceTests, the_service_responds_to_a_ping_with_a_pong) -{ - startServiceToLocked(); - - //+500 just to ensure outside any internal private signals - static constexpr enum_t RESPONSE_SIG = PubSub::MAX_PUB_SIG + 500; - - // this test demonstrates testing an AO that must respond directly - // to an event with a POST directly to an external requesting AO. - - Pong pongEvent; - pongEvent.sig = 0; - pongEvent.m_source = nullptr; - - auto dummy = std::unique_ptr( - new cms::DefaultDummyActiveObject()); - dummy->SetPostedEventHandler([&pongEvent](const QP::QEvt* event) { - auto p = static_cast(event); - pongEvent.sig = p->sig; - pongEvent.m_source = p->m_source; - }); - - // Reminder: QF requires that each AO be at a unique priority level - // hence the '- 1' below. - dummy->dummyStart(qf_ctrl::UNIT_UNDER_TEST_PRIORITY - 1); - - // Send the Ping to our AO under test and give it - // some processing time. - Ping::sendTo( - mUnderTest, RESPONSE_SIG, dummy.get()); - qf_ctrl::ProcessEvents(); - - // confirm that our dummy received a Pong with expected - // data. - CHECK_EQUAL(RESPONSE_SIG, pongEvent.sig); - CHECK_EQUAL(mUnderTest, pongEvent.m_source); -} \ No newline at end of file diff --git a/externals/.gitignore b/externals/.gitignore new file mode 100644 index 0000000..ef68333 --- /dev/null +++ b/externals/.gitignore @@ -0,0 +1 @@ +qpcpp/ diff --git a/externals/qpcpp b/externals/qpcpp deleted file mode 160000 index 6b7d766..0000000 --- a/externals/qpcpp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6b7d766521a5c9681f61922a64027690721c2478 diff --git a/externals/qpcppCMakeSupport.txt b/externals/qpcppCMakeSupport.txt deleted file mode 100644 index f2a1700..0000000 --- a/externals/qpcppCMakeSupport.txt +++ /dev/null @@ -1,17 +0,0 @@ -set(QP_CPP_TOP_DIR ${CMAKE_CURRENT_LIST_DIR}/../externals/qpcpp) -set(QP_CPP_SRC_DIR ${QP_CPP_TOP_DIR}/src) -set(QP_CPP_INCLUDE_DIR ${QP_CPP_TOP_DIR}/include) - -set(QP_CPP_QF_SRCS - ${QP_CPP_SRC_DIR}/qf/qep_hsm.cpp - ${QP_CPP_SRC_DIR}/qf/qep_msm.cpp - ${QP_CPP_SRC_DIR}/qf/qf_act.cpp - ${QP_CPP_SRC_DIR}/qf/qf_actq.cpp - ${QP_CPP_SRC_DIR}/qf/qf_defer.cpp - ${QP_CPP_SRC_DIR}/qf/qf_dyn.cpp - ${QP_CPP_SRC_DIR}/qf/qf_mem.cpp - ${QP_CPP_SRC_DIR}/qf/qf_ps.cpp - ${QP_CPP_SRC_DIR}/qf/qf_qact.cpp - ${QP_CPP_SRC_DIR}/qf/qf_qeq.cpp - ${QP_CPP_SRC_DIR}/qf/qf_qmact.cpp - ${QP_CPP_SRC_DIR}/qf/qf_time.cpp) diff --git a/externals/qpcppPosixPortCMakeSupport.txt b/externals/qpcppPosixPortCMakeSupport.txt deleted file mode 100644 index 03a3cb0..0000000 --- a/externals/qpcppPosixPortCMakeSupport.txt +++ /dev/null @@ -1,2 +0,0 @@ - -include_directories(${QP_CPP_TOP_DIR}/ports/posix) diff --git a/include/bspTicks.hpp b/include/bspTicks.hpp deleted file mode 100644 index 41d6a62..0000000 --- a/include/bspTicks.hpp +++ /dev/null @@ -1,11 +0,0 @@ - -#ifndef BSP_TICKS_HPP -#define BSP_TICKS_HPP - -#include - -namespace bsp { -static constexpr uint32_t TICKS_PER_SECOND = 100; -} // namespace bsp - -#endif // BSP_TICKS_HPP diff --git a/include/pingPongEvents.hpp b/include/pingPongEvents.hpp deleted file mode 100644 index a737840..0000000 --- a/include/pingPongEvents.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/// @brief Trivial 'Ping' and 'Pong' event types, used to demonstrate -/// direct post and response events to/from an active object. -/// @ingroup -/// @cond -///*************************************************************************** -/// -/// Copyright (C) 2022 Matthew Eshleman. All rights reserved. -/// -/// This program is open source software: you can redistribute it and/or -/// modify it under the terms of the GNU General Public License as published -/// by the Free Software Foundation, either version 3 of the License, or -/// (at your option) any later version. -/// -/// Alternatively, upon written permission from Matthew Eshleman, this program -/// may be distributed and modified under the terms of a Commercial -/// License. For further details, see the Contact Information below. -/// -/// Contact Information: -/// Matthew Eshleman -/// https://covemountainsoftware.com -/// info@covemountainsoftware.com -///*************************************************************************** -/// @endcond -#ifndef PING_PONG_EVENTS_HPP -#define PING_PONG_EVENTS_HPP - -#include "qpcpp.hpp" - -namespace cms { - -/// "Ping" - a trivial ping event. An active object -/// supporting this event is expected -/// to respond with a Pong event, using -/// the provided requester and response sig. -/// -class Ping : public QP::QEvt { -public: - QP::QActive* m_requester; - enum_t responseSig; - - template - static void sendTo(QP::QActive* destination, enum_t responseSig, - QP::QActive* requester) - { - auto e = Q_NEW(Ping, sig); - e->m_requester = requester; - e->responseSig = responseSig; - destination->POST(e, 0); - } -}; - -/// "Pong" - a trivial pong event, sent in response of -/// an active object that supports a Ping -/// event. -class Pong : public QP::QEvt { -public: - QP::QActive* m_source; - - static void sendTo(QP::QActive* destination, enum_t pongSig, - QP::QActive* source) - { - auto e = Q_NEW(Pong, pongSig); - e->m_source = source; - destination->POST(e, 0); - } -}; - -} // namespace cms - -#endif // PING_PONG_EVENTS_HPP diff --git a/include/pubsub_signals.hpp b/include/pubsub_signals.hpp deleted file mode 100644 index f2a3455..0000000 --- a/include/pubsub_signals.hpp +++ /dev/null @@ -1,25 +0,0 @@ -///*************************************************************************** -/// @brief The public signals used in the publish/subscribe event system -///*************************************************************************** - -#ifndef PUB_SUB_SIGNALS_HPP -#define PUB_SUB_SIGNALS_HPP - -#include "qpcpp.hpp" - -namespace PubSub { - -/// The publish/subscribe signals allocated for this project -enum Signals { - STARTING_PUB_SUB_SIG = QP::Q_USER_SIG, - - #include "hwLockCtrlServiceExpectedPubSubSigs.hpp" - - DEMONSTRATE_TEST_OF_QASSERT, - - MAX_PUB_SIG // the last published signal -}; - -} // namespace PubSub - -#endif // PUB_SUB_SIGNALS_HPP diff --git a/test_support/CMakeLists.txt b/test_support/CMakeLists.txt deleted file mode 100644 index c18808d..0000000 --- a/test_support/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(cpputest-qpcpp-port) diff --git a/test_support/cpputest-qpcpp-port/CMakeLists.txt b/test_support/cpputest-qpcpp-port/CMakeLists.txt deleted file mode 100644 index 4232817..0000000 --- a/test_support/cpputest-qpcpp-port/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ - -set(CPPUTEST_QP_PORT_TOP_DIR ${TEST_SUPPORT_TOP_DIR}/cpputest-qpcpp-port) -set(CPPUTEST_QP_PORT_SRC_DIR ${CPPUTEST_QP_PORT_TOP_DIR}/src) -set(CPPUTEST_QP_PORT_SRC_FILES - ${CPPUTEST_QP_PORT_SRC_DIR}/cpputest_qf_port.cpp - ${CPPUTEST_QP_PORT_SRC_DIR}/cms_cpputest_qf_ctrl.cpp - ${CPPUTEST_QP_PORT_SRC_DIR}/cms_cpputest_q_onAssert.cpp - ${CPPUTEST_QP_PORT_SRC_DIR}/cms_cpputest_qf_onCleanup.cpp - ${QP_CPP_QF_SRCS} - ) - -include_directories(${QP_CPP_SRC_DIR}) -include_directories(${CPPUTEST_QP_PORT_TOP_DIR}/include) -add_subdirectory(test) -add_library(cpputestqpcpplib ${QP_CPP_QF_SRCS} ${CPPUTEST_QP_PORT_SRC_FILES} ../common/cpputestMain.cpp) -target_include_directories(cpputestqpcpplib PUBLIC ${QP_CPP_INCLUDE_DIR} ${CPPUTEST_QP_PORT_TOP_DIR}/include) - - - - - diff --git a/test_support/mocks/hwLockCtrl/mockHwLockCtrl.cpp b/test_support/mocks/hwLockCtrl/mockHwLockCtrl.cpp deleted file mode 100644 index 2a0029a..0000000 --- a/test_support/mocks/hwLockCtrl/mockHwLockCtrl.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* -MIT License - -Copyright (c) <2019-2020> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "hwLockCtrl.h" -#include "CppUTestExt/MockSupport.h" - -static constexpr const char* MOCK_NAME = "HwLockCtrl"; - -bool HwLockCtrlInit() -{ - mock(MOCK_NAME).actualCall("Init"); - return static_cast(mock(MOCK_NAME).returnIntValueOrDefault(true)); //use IntValue due to bug in CppUTest bool handling. -} - -bool HwLockCtrlLock() -{ - mock(MOCK_NAME).actualCall("Lock"); - return static_cast(mock(MOCK_NAME).returnIntValueOrDefault(true)); -} - -bool HwLockCtrlUnlock() -{ - mock(MOCK_NAME).actualCall("Unlock"); - return static_cast(mock(MOCK_NAME).returnIntValueOrDefault(true)); -} - -bool HwLockCtrlSelfTest(HwLockCtrlSelfTestResultT* outResult) -{ - mock(MOCK_NAME).actualCall("SelfTest").withOutputParameter("outResult", outResult); - return static_cast(mock(MOCK_NAME).returnIntValueOrDefault(true)); -} - -bool HwLockCtrlIsCommOk() -{ - mock(MOCK_NAME).actualCall("IsCommOk"); - return static_cast(mock(MOCK_NAME).returnIntValueOrDefault(true)); //use IntValue due to bug in CppUTest bool handling. -} diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt deleted file mode 100644 index 4488799..0000000 --- a/utilities/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -include_directories(include) -add_subdirectory(test) diff --git a/utilities/test/CMakeLists.txt b/utilities/test/CMakeLists.txt deleted file mode 100644 index b5982f8..0000000 --- a/utilities/test/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -# prep for cpputest based build -set(TEST_APP_NAME utilityGeneralTests) - -# files to include in this test target -set(TEST_SOURCES - orthogonalComponentTests.cpp - orthogonalContainerTests.cpp - backedQueueTests.cpp) - -# this include expects TEST_SOURCES and TEST_APP_NAME to be -# defined, and creates the cpputest based test executable target -include(${TEST_SUPPORT_TOP_DIR}/common/cpputestCMake.txt) - -target_link_libraries(${TEST_APP_NAME} cpputestqpcpplib ${CPPUTEST_LDFLAGS}) \ No newline at end of file