HealthIF extensions and upstream updates #82
59
CHANGELOG.md
59
CHANGELOG.md
@ -25,8 +25,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||||
- HAL Devicehandlers: Periodic printout is run-time configurable now
|
- HAL Devicehandlers: Periodic printout is run-time configurable now
|
||||||
- `oneShotAction` flag in the `TestTask` class is not static anymore
|
- `oneShotAction` flag in the `TestTask` class is not static anymore
|
||||||
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
|
|
||||||
- Major update for version handling, using `git describe` to fetch version information with git.
|
- Major update for version handling, using `git describe` to fetch version information with git.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/601
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/601
|
||||||
- Place `Version` class outside of `fsfw` namespace. It is generic
|
- Place `Version` class outside of `fsfw` namespace. It is generic
|
||||||
@ -45,12 +43,39 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
creation call. It allows passing context information and an arbitrary user argument into
|
creation call. It allows passing context information and an arbitrary user argument into
|
||||||
the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs
|
the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
|
||||||
- Clock:
|
|
||||||
- `timeval` to `TimeOfDay_t`
|
### HAL
|
||||||
- Added Mutex for gmtime calls: (compare http://www.opengate.at/blog/2020/01/timeless/)
|
|
||||||
- Moved the statics used by Clock in ClockCommon.cpp to this file
|
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
||||||
- Better check for leap seconds
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
|
||||||
- Added Unittests for Clock (only getter)
|
- HAL Linux SPI: Set the Clock Default State when setting new SPI speed
|
||||||
|
and mode
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573
|
||||||
|
- GPIO HAL: `Direction`, `GpioOperation` and `Levels` are enum classes now, which prevents
|
||||||
|
name clashes with Windows defines.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||||
|
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
|
||||||
|
|
||||||
|
### Time
|
||||||
|
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/584 and
|
||||||
|
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
|
||||||
|
|
||||||
|
- `timeval` to `TimeOfDay_t`
|
||||||
|
- Added Mutex for gmtime calls: (compare http://www.opengate.at/blog/2020/01/timeless/)
|
||||||
|
- Moved the statics used by Clock in ClockCommon.cpp to this file
|
||||||
|
- Better check for leap seconds
|
||||||
|
- Added Unittests for Clock (only getter)
|
||||||
|
|
||||||
|
### Power
|
||||||
|
|
||||||
|
- `PowerSwitchIF`: Remove `const` specifier from `sendSwitchCommand` and `sendFuseOnCommand` and
|
||||||
|
also specify a `ReturnValue_t` return type
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
|
- Extend `PowerSwitcher` module to optionally check current state when calling `turnOn` or
|
||||||
|
`turnOff`. Tis can be helpful to avoid commanding switches which do not need commanding
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
|
|
||||||
## Removed
|
## Removed
|
||||||
|
|
||||||
@ -60,11 +85,29 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Additions
|
## Additions
|
||||||
|
|
||||||
|
- LTO support: Allow using LTO/IPO by setting `FSFW_ENABLE_LTO=1`. CMake is able to detect whether
|
||||||
|
the user compiler supports IPO/LPO. LTO is on by default now. Most modern compilers support it,
|
||||||
|
can make good use of it and it usually makes the code faster and/or smaller.
|
||||||
|
After some more research:
|
||||||
|
Enabling LTO will actually cause the compiler to only produce thin LTO by adding
|
||||||
|
`-flto -fno-fat-lto-objects` to the compiler options. I am not sure this is an ideal choice
|
||||||
|
because if an application linking against the FSFW does not use LTO, there can be compile
|
||||||
|
issues (e.g. observed when compiling the FSFW tests without LTO). This is a known issue as
|
||||||
|
can be seen in the multiple CMake issues for it:
|
||||||
|
- https://gitlab.kitware.com/cmake/cmake/-/issues/22913,
|
||||||
|
- https://gitlab.kitware.com/cmake/cmake/-/issues/16808,
|
||||||
|
- https://gitlab.kitware.com/cmake/cmake/-/issues/21696
|
||||||
|
Easiest solution for now: Keep this option OFF by default.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
|
||||||
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
||||||
inside `fsfw/version.h`
|
inside `fsfw/version.h`
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
||||||
- Added ETL dependency and improved library dependency management
|
- Added ETL dependency and improved library dependency management
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592
|
||||||
|
- Add a `DummyPowerSwitcher` module which can be useful for test setups when no PCDU is available
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
|
- New typedef for switcher type
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
- `Subsystem`: New API to add table and sequence entries
|
- `Subsystem`: New API to add table and sequence entries
|
||||||
|
|
||||||
## HAL
|
## HAL
|
||||||
|
@ -18,6 +18,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" )
|
|||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake-modules")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake-modules")
|
||||||
set(MSG_PREFIX "fsfw |")
|
set(MSG_PREFIX "fsfw |")
|
||||||
|
|
||||||
|
set(FSFW_ETL_LIB_NAME etl)
|
||||||
set(FSFW_ETL_LIB_MAJOR_VERSION 20 CACHE STRING
|
set(FSFW_ETL_LIB_MAJOR_VERSION 20 CACHE STRING
|
||||||
"ETL library major version requirement"
|
"ETL library major version requirement"
|
||||||
)
|
)
|
||||||
@ -33,7 +34,16 @@ set(FSFW_CATCH2_LIB_VERSION v${FSFW_CATCH2_LIB_MAJOR_VERSION}.0.0-preview5 CACHE
|
|||||||
"Catch2 library exact version requirement"
|
"Catch2 library exact version requirement"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(FSFW_ETL_LIB_NAME etl)
|
# Keep this off by default for now. See PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
|
||||||
|
# for information which keeping this on by default is problematic
|
||||||
|
option(FSFW_ENABLE_IPO "Enable interprocedural optimization or link-time optimization if available" OFF)
|
||||||
|
if(FSFW_ENABLE_IPO)
|
||||||
|
include(CheckIPOSupported)
|
||||||
|
check_ipo_supported(RESULT IPO_SUPPORTED OUTPUT IPO_ERROR)
|
||||||
|
if(NOT IPO_SUPPORTED)
|
||||||
|
message(STATUS "FSFW | IPO/LTO not supported: ${IPO_ERROR}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
option(FSFW_GENERATE_SECTIONS
|
option(FSFW_GENERATE_SECTIONS
|
||||||
"Generate function and data sections. Required to remove unused code" ON
|
"Generate function and data sections. Required to remove unused code" ON
|
||||||
@ -72,6 +82,10 @@ set(FSFW_DUMMY_TGT fsfw-dummy)
|
|||||||
|
|
||||||
add_library(${LIB_FSFW_NAME})
|
add_library(${LIB_FSFW_NAME})
|
||||||
|
|
||||||
|
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||||
|
set_property(TARGET ${LIB_FSFW_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(FSFW_GIT_VER_HANDLING_OK FALSE)
|
set(FSFW_GIT_VER_HANDLING_OK FALSE)
|
||||||
# Version handling
|
# Version handling
|
||||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
|
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
|
||||||
@ -128,6 +142,9 @@ if(FSFW_BUILD_UNITTESTS)
|
|||||||
|
|
||||||
project(${FSFW_TEST_TGT} CXX C)
|
project(${FSFW_TEST_TGT} CXX C)
|
||||||
add_executable(${FSFW_TEST_TGT})
|
add_executable(${FSFW_TEST_TGT})
|
||||||
|
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||||
|
set_property(TARGET ${FSFW_TEST_TGT} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(FSFW_TESTS_GEN_COV)
|
if(FSFW_TESTS_GEN_COV)
|
||||||
message(STATUS "${MSG_PREFIX} Generating coverage data for the library")
|
message(STATUS "${MSG_PREFIX} Generating coverage data for the library")
|
||||||
|
@ -16,10 +16,15 @@ class HasHealthIF {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
|
||||||
static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1);
|
static constexpr ReturnValue_t OBJECT_NOT_HEALTHY =
|
||||||
static const ReturnValue_t INVALID_HEALTH_STATE = MAKE_RETURN_CODE(2);
|
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 1);
|
||||||
|
static constexpr ReturnValue_t INVALID_HEALTH_STATE =
|
||||||
|
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 2);
|
||||||
|
static constexpr ReturnValue_t IS_EXTERNALLY_CONTROLLED =
|
||||||
|
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 3);
|
||||||
|
|
||||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER_1;
|
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER_1;
|
||||||
|
//! P1: New Health, P2: Old Health
|
||||||
static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO);
|
static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO);
|
||||||
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO);
|
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO);
|
||||||
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
|
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#include "DummyPowerSwitcher.h"
|
#include "DummyPowerSwitcher.h"
|
||||||
|
|
||||||
DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches,
|
DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches,
|
||||||
size_t numberOfFuses, uint32_t switchDelayMs)
|
size_t numberOfFuses, bool registerGlobally,
|
||||||
: SystemObject(objectId),
|
uint32_t switchDelayMs)
|
||||||
|
: SystemObject(objectId, registerGlobally),
|
||||||
switcherList(numberOfSwitches),
|
switcherList(numberOfSwitches),
|
||||||
fuseList(numberOfFuses),
|
fuseList(numberOfFuses),
|
||||||
switchDelayMs(switchDelayMs) {}
|
switchDelayMs(switchDelayMs) {}
|
||||||
|
@ -8,10 +8,17 @@
|
|||||||
#include "definitions.h"
|
#include "definitions.h"
|
||||||
#include "fsfw/objectmanager/SystemObject.h"
|
#include "fsfw/objectmanager/SystemObject.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This component can be used to simulate a power switcher like a
|
||||||
|
* Power Control Distribution Unit (PCDU)
|
||||||
|
* @details
|
||||||
|
* The dummy switcher will simply cache the commanded fuse and switch states and return them
|
||||||
|
* in the according switch getter functions. In that sense, it simulates an ideal PCDU.
|
||||||
|
*/
|
||||||
class DummyPowerSwitcher : public SystemObject, public PowerSwitchIF {
|
class DummyPowerSwitcher : public SystemObject, public PowerSwitchIF {
|
||||||
public:
|
public:
|
||||||
DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches, size_t numberOfFuses,
|
DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches, size_t numberOfFuses,
|
||||||
uint32_t switchDelayMs = 5000);
|
bool registerGlobally = true, uint32_t switchDelayMs = 5000);
|
||||||
|
|
||||||
void setInitialSwitcherList(std::vector<ReturnValue_t> switcherList);
|
void setInitialSwitcherList(std::vector<ReturnValue_t> switcherList);
|
||||||
void setInitialFusesList(std::vector<ReturnValue_t> switcherList);
|
void setInitialFusesList(std::vector<ReturnValue_t> switcherList);
|
||||||
|
@ -18,7 +18,8 @@ class PowerSwitcher : public HasReturnvaluesIF {
|
|||||||
static const uint8_t INTERFACE_ID = CLASS_ID::POWER_SWITCHER;
|
static const uint8_t INTERFACE_ID = CLASS_ID::POWER_SWITCHER;
|
||||||
static const ReturnValue_t IN_POWER_TRANSITION = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t IN_POWER_TRANSITION = MAKE_RETURN_CODE(1);
|
||||||
static const ReturnValue_t SWITCH_STATE_MISMATCH = MAKE_RETURN_CODE(2);
|
static const ReturnValue_t SWITCH_STATE_MISMATCH = MAKE_RETURN_CODE(2);
|
||||||
PowerSwitcher(PowerSwitchIF* switcher, uint8_t setSwitch1, uint8_t setSwitch2 = power::NO_SWITCH,
|
PowerSwitcher(PowerSwitchIF* switcher, power::Switch_t setSwitch1,
|
||||||
|
power::Switch_t setSwitch2 = power::NO_SWITCH,
|
||||||
State_t setStartState = SWITCH_IS_OFF);
|
State_t setStartState = SWITCH_IS_OFF);
|
||||||
void turnOn(bool checkCurrentState = true);
|
void turnOn(bool checkCurrentState = true);
|
||||||
void turnOff(bool checkCurrentState = true);
|
void turnOff(bool checkCurrentState = true);
|
||||||
|
@ -11,7 +11,10 @@ target_sources(${FSFW_TEST_TGT} PRIVATE
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(testcfg)
|
add_subdirectory(testcfg)
|
||||||
|
add_subdirectory(mocks)
|
||||||
|
|
||||||
add_subdirectory(action)
|
add_subdirectory(action)
|
||||||
|
add_subdirectory(power)
|
||||||
add_subdirectory(container)
|
add_subdirectory(container)
|
||||||
add_subdirectory(osal)
|
add_subdirectory(osal)
|
||||||
add_subdirectory(serialize)
|
add_subdirectory(serialize)
|
||||||
|
3
tests/src/fsfw_tests/unit/mocks/CMakeLists.txt
Normal file
3
tests/src/fsfw_tests/unit/mocks/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||||
|
PowerSwitcherMock.cpp
|
||||||
|
)
|
77
tests/src/fsfw_tests/unit/mocks/PowerSwitcherMock.cpp
Normal file
77
tests/src/fsfw_tests/unit/mocks/PowerSwitcherMock.cpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#include "PowerSwitcherMock.h"
|
||||||
|
|
||||||
|
static uint32_t SWITCH_REQUEST_UPDATE_VALUE = 0;
|
||||||
|
|
||||||
|
PowerSwitcherMock::PowerSwitcherMock() {}
|
||||||
|
|
||||||
|
ReturnValue_t PowerSwitcherMock::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) {
|
||||||
|
if (switchMap.count(switchNr) == 0) {
|
||||||
|
switchMap.emplace(switchNr, SwitchInfo(switchNr, onOff));
|
||||||
|
} else {
|
||||||
|
SwitchInfo& info = switchMap.at(switchNr);
|
||||||
|
info.currentState = onOff;
|
||||||
|
if (onOff == PowerSwitchIF::SWITCH_ON) {
|
||||||
|
info.timesCalledOn++;
|
||||||
|
} else {
|
||||||
|
info.timesCalledOff++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PowerSwitcherMock::sendFuseOnCommand(uint8_t fuseNr) {
|
||||||
|
if (fuseMap.count(fuseNr) == 0) {
|
||||||
|
fuseMap.emplace(fuseNr, FuseInfo(fuseNr));
|
||||||
|
} else {
|
||||||
|
FuseInfo& info = fuseMap.at(fuseNr);
|
||||||
|
info.timesCalled++;
|
||||||
|
}
|
||||||
|
return RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PowerSwitcherMock::getSwitchState(power::Switch_t switchNr) const {
|
||||||
|
if (switchMap.count(switchNr) == 1) {
|
||||||
|
auto& info = switchMap.at(switchNr);
|
||||||
|
SWITCH_REQUEST_UPDATE_VALUE++;
|
||||||
|
return info.currentState;
|
||||||
|
}
|
||||||
|
return RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PowerSwitcherMock::getFuseState(uint8_t fuseNr) const {
|
||||||
|
if (fuseMap.count(fuseNr) == 1) {
|
||||||
|
return FUSE_ON;
|
||||||
|
} else {
|
||||||
|
return FUSE_OFF;
|
||||||
|
}
|
||||||
|
return RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PowerSwitcherMock::getSwitchDelayMs(void) const { return 5000; }
|
||||||
|
|
||||||
|
SwitchInfo::SwitchInfo() : switcher(0) {}
|
||||||
|
|
||||||
|
SwitchInfo::SwitchInfo(power::Switch_t switcher, ReturnValue_t initState)
|
||||||
|
: switcher(switcher), currentState(initState) {}
|
||||||
|
|
||||||
|
FuseInfo::FuseInfo(uint8_t fuse) : fuse(fuse) {}
|
||||||
|
|
||||||
|
void PowerSwitcherMock::getSwitchInfo(power::Switch_t switcher, SwitchInfo& info) {
|
||||||
|
if (switchMap.count(switcher) == 1) {
|
||||||
|
info = switchMap.at(switcher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PowerSwitcherMock::getFuseInfo(uint8_t fuse, FuseInfo& info) {
|
||||||
|
if (fuseMap.count(fuse) == 1) {
|
||||||
|
info = fuseMap.at(fuse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PowerSwitcherMock::getAmountSwitchStatWasRequested() {
|
||||||
|
return SWITCH_REQUEST_UPDATE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PowerSwitcherMock::initSwitch(power::Switch_t switchNr) {
|
||||||
|
switchMap.emplace(switchNr, SwitchInfo(switchNr, PowerSwitchIF::SWITCH_OFF));
|
||||||
|
}
|
52
tests/src/fsfw_tests/unit/mocks/PowerSwitcherMock.h
Normal file
52
tests/src/fsfw_tests/unit/mocks/PowerSwitcherMock.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#ifndef FSFW_TESTS_SRC_FSFW_TESTS_UNIT_MOCKS_POWERSWITCHERMOCK_H_
|
||||||
|
#define FSFW_TESTS_SRC_FSFW_TESTS_UNIT_MOCKS_POWERSWITCHERMOCK_H_
|
||||||
|
|
||||||
|
#include <fsfw/power/PowerSwitchIF.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
struct SwitchInfo {
|
||||||
|
public:
|
||||||
|
SwitchInfo();
|
||||||
|
SwitchInfo(power::Switch_t switcher, ReturnValue_t initState);
|
||||||
|
|
||||||
|
power::Switch_t switcher;
|
||||||
|
ReturnValue_t currentState = PowerSwitchIF::SWITCH_OFF;
|
||||||
|
uint32_t timesCalledOn = 0;
|
||||||
|
uint32_t timesCalledOff = 0;
|
||||||
|
uint32_t timesStatusRequested = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FuseInfo {
|
||||||
|
public:
|
||||||
|
FuseInfo(uint8_t fuse);
|
||||||
|
uint8_t fuse;
|
||||||
|
uint32_t timesCalled = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PowerSwitcherMock : public PowerSwitchIF {
|
||||||
|
public:
|
||||||
|
PowerSwitcherMock();
|
||||||
|
|
||||||
|
ReturnValue_t sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) override;
|
||||||
|
ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) override;
|
||||||
|
ReturnValue_t getSwitchState(power::Switch_t switchNr) const override;
|
||||||
|
ReturnValue_t getFuseState(uint8_t fuseNr) const override;
|
||||||
|
uint32_t getSwitchDelayMs(void) const override;
|
||||||
|
|
||||||
|
void getSwitchInfo(power::Switch_t switcher, SwitchInfo& info);
|
||||||
|
void getFuseInfo(uint8_t fuse, FuseInfo& info);
|
||||||
|
|
||||||
|
uint32_t getAmountSwitchStatWasRequested();
|
||||||
|
|
||||||
|
void initSwitch(power::Switch_t switchNr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
using SwitchOnOffPair = std::pair<power::Switch_t, ReturnValue_t>;
|
||||||
|
using FuseOnOffPair = std::pair<uint8_t, ReturnValue_t>;
|
||||||
|
std::map<power::Switch_t, SwitchInfo> switchMap;
|
||||||
|
std::map<uint8_t, FuseInfo> fuseMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FSFW_TESTS_SRC_FSFW_TESTS_UNIT_MOCKS_POWERSWITCHERMOCK_H_ */
|
3
tests/src/fsfw_tests/unit/power/CMakeLists.txt
Normal file
3
tests/src/fsfw_tests/unit/power/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||||
|
testPowerSwitcher.cpp
|
||||||
|
)
|
73
tests/src/fsfw_tests/unit/power/testPowerSwitcher.cpp
Normal file
73
tests/src/fsfw_tests/unit/power/testPowerSwitcher.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include <fsfw/power/DummyPowerSwitcher.h>
|
||||||
|
#include <fsfw/power/PowerSwitcher.h>
|
||||||
|
#include <fsfw_tests/unit/mocks/PowerSwitcherMock.h>
|
||||||
|
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
|
#include "objects/systemObjectList.h"
|
||||||
|
|
||||||
|
TEST_CASE("Power Switcher", "[power-switcher]") {
|
||||||
|
PowerSwitcherMock mock;
|
||||||
|
PowerSwitcher switcher(&mock, 1);
|
||||||
|
DummyPowerSwitcher dummySwitcher(objects::DUMMY_POWER_SWITCHER, 5, 5, false);
|
||||||
|
PowerSwitcher switcherUsingDummy(&dummySwitcher, 1);
|
||||||
|
SwitchInfo switchInfo;
|
||||||
|
mock.initSwitch(1);
|
||||||
|
|
||||||
|
SECTION("Basic Tests") {
|
||||||
|
REQUIRE(switcher.getFirstSwitch() == 1);
|
||||||
|
REQUIRE(switcher.getSecondSwitch() == power::NO_SWITCH);
|
||||||
|
// Default start state
|
||||||
|
REQUIRE(switcher.getState() == PowerSwitcher::SWITCH_IS_OFF);
|
||||||
|
switcher.turnOn(true);
|
||||||
|
REQUIRE(mock.getAmountSwitchStatWasRequested() == 1);
|
||||||
|
REQUIRE(switcher.getState() == PowerSwitcher::WAIT_ON);
|
||||||
|
REQUIRE(switcher.checkSwitchState() == PowerSwitcher::IN_POWER_TRANSITION);
|
||||||
|
REQUIRE(switcher.active());
|
||||||
|
switcher.doStateMachine();
|
||||||
|
REQUIRE(switcher.getState() == PowerSwitcher::SWITCH_IS_ON);
|
||||||
|
mock.getSwitchInfo(1, switchInfo);
|
||||||
|
REQUIRE(switchInfo.timesCalledOn == 1);
|
||||||
|
REQUIRE(not switcher.active());
|
||||||
|
REQUIRE(mock.getAmountSwitchStatWasRequested() == 2);
|
||||||
|
REQUIRE(switcher.checkSwitchState() == HasReturnvaluesIF::RETURN_OK);
|
||||||
|
REQUIRE(mock.getAmountSwitchStatWasRequested() == 3);
|
||||||
|
switcher.turnOff(false);
|
||||||
|
REQUIRE(mock.getAmountSwitchStatWasRequested() == 3);
|
||||||
|
REQUIRE(switcher.getState() == PowerSwitcher::WAIT_OFF);
|
||||||
|
REQUIRE(switcher.active());
|
||||||
|
REQUIRE(switcher.getState() == PowerSwitcher::WAIT_OFF);
|
||||||
|
switcher.doStateMachine();
|
||||||
|
mock.getSwitchInfo(1, switchInfo);
|
||||||
|
REQUIRE(switcher.getState() == PowerSwitcher::SWITCH_IS_OFF);
|
||||||
|
REQUIRE(switchInfo.timesCalledOn == 1);
|
||||||
|
REQUIRE(switchInfo.timesCalledOff == 1);
|
||||||
|
REQUIRE(not switcher.active());
|
||||||
|
REQUIRE(mock.getAmountSwitchStatWasRequested() == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Dummy Test") {
|
||||||
|
// Same tests, but we can't really check the dummy
|
||||||
|
REQUIRE(switcherUsingDummy.getFirstSwitch() == 1);
|
||||||
|
REQUIRE(switcherUsingDummy.getSecondSwitch() == power::NO_SWITCH);
|
||||||
|
REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::SWITCH_IS_OFF);
|
||||||
|
switcherUsingDummy.turnOn(true);
|
||||||
|
REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::WAIT_ON);
|
||||||
|
REQUIRE(switcherUsingDummy.active());
|
||||||
|
switcherUsingDummy.doStateMachine();
|
||||||
|
REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::SWITCH_IS_ON);
|
||||||
|
REQUIRE(not switcherUsingDummy.active());
|
||||||
|
|
||||||
|
switcherUsingDummy.turnOff(false);
|
||||||
|
REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::WAIT_OFF);
|
||||||
|
REQUIRE(switcherUsingDummy.active());
|
||||||
|
REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::WAIT_OFF);
|
||||||
|
switcherUsingDummy.doStateMachine();
|
||||||
|
REQUIRE(switcherUsingDummy.getState() == PowerSwitcher::SWITCH_IS_OFF);
|
||||||
|
REQUIRE(not switcherUsingDummy.active());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("More Dummy Tests") {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -21,8 +21,9 @@ enum sourceObjects : uint32_t {
|
|||||||
HK_RECEIVER_MOCK = 22,
|
HK_RECEIVER_MOCK = 22,
|
||||||
TEST_LOCAL_POOL_OWNER_BASE = 25,
|
TEST_LOCAL_POOL_OWNER_BASE = 25,
|
||||||
|
|
||||||
SHARED_SET_ID = 26
|
SHARED_SET_ID = 26,
|
||||||
|
|
||||||
|
DUMMY_POWER_SWITCHER = 27
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user