Add unit tests for logic state machines reusal

as it will work in the real FW
pull/83/head
D.R.racer 2021-08-11 17:44:31 +02:00 committed by DRracer
parent ccefe32ba1
commit e0ea47595f
5 changed files with 87 additions and 33 deletions

View File

@ -21,12 +21,11 @@ using Catch::Matchers::Equals;
#include "../helpers/helpers.ipp"
void CutSlot(uint8_t cutSlot) {
void CutSlot(logic::CutFilament &cf, uint8_t cutSlot) {
ForceReinitAllAutomata();
logic::CutFilament cf;
REQUIRE(VerifyState(cf, false, mi::Idler::IdleSlotIndex(), 0, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK));
REQUIRE(VerifyEnvironmentState(false, mi::Idler::IdleSlotIndex(), 0, false, ml::off, ml::off));
EnsureActiveSlotIndex(cutSlot);
@ -87,12 +86,30 @@ void CutSlot(uint8_t cutSlot) {
TEST_CASE("cut_filament::cut0", "[cut_filament]") {
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
CutSlot(cutSlot);
logic::CutFilament cf;
CutSlot(cf, cutSlot);
}
}
TEST_CASE("cut_filament::invalid_slot", "[cut_filament]") {
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
InvalidSlot<logic::CutFilament>(config::toolCount, cutSlot);
for (uint8_t activeSlot = 0; activeSlot < config::toolCount; ++activeSlot) {
logic::CutFilament cf;
InvalidSlot<logic::CutFilament>(cf, activeSlot, config::toolCount);
}
}
TEST_CASE("cut_filament::state_machine_reusal", "[cut_filament]") {
logic::CutFilament cf;
for (uint8_t activeSlot = 0; activeSlot < config::toolCount; ++activeSlot) {
InvalidSlot<logic::CutFilament>(cf, activeSlot, config::toolCount);
}
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
CutSlot(cf, cutSlot);
}
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
CutSlot(cf, cutSlot);
InvalidSlot<logic::CutFilament>(cf, cutSlot, config::toolCount);
}
}

View File

@ -70,12 +70,8 @@ TEST_CASE("eject_filament::eject0", "[eject_filament][.]") {
}
TEST_CASE("eject_filament::invalid_slot", "[eject_filament]") {
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
InvalidSlot<logic::EjectFilament>(config::toolCount, cutSlot);
for (uint8_t activeSlot = 0; activeSlot < config::toolCount; ++activeSlot) {
logic::EjectFilament ef;
InvalidSlot<logic::EjectFilament>(ef, activeSlot, config::toolCount);
}
}
// comments:
// The tricky part of the whole state machine are the edge cases - filament not loaded, stall guards etc.
// ... all the external influence we can get on the real HW
// But the good news is we can simulate them all in the unit test and thus ensure proper handling

View File

@ -1,7 +1,5 @@
// LED checked at selector's index
template<typename SM>
bool VerifyState(SM &uf, bool filamentLoaded, uint8_t idlerSlotIndex, uint8_t selectorSlotIndex,
bool findaPressed, ml::Mode greenLEDMode, ml::Mode redLEDMode, ErrorCode err, ProgressCode topLevelProgress) {
bool VerifyEnvironmentState(bool filamentLoaded, uint8_t idlerSlotIndex, uint8_t selectorSlotIndex,
bool findaPressed, ml::Mode greenLEDMode, ml::Mode redLEDMode) {
CHECKED_ELSE(mg::globals.FilamentLoaded() == filamentLoaded) { return false; }
CHECKED_ELSE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(idlerSlotIndex).v) { return false; }
CHECKED_ELSE(mi::idler.Engaged() == (idlerSlotIndex < config::toolCount)) { return false; }
@ -19,8 +17,19 @@ bool VerifyState(SM &uf, bool filamentLoaded, uint8_t idlerSlotIndex, uint8_t se
CHECKED_ELSE(ml::leds.Mode(selectorSlotIndex, ml::green) == greenLEDMode) { return false; }
}
}
return true;
}
CHECKED_ELSE(uf.Error() == err) { return false; }
// LED checked at selector's index
template<typename SM>
bool VerifyState(SM &uf, bool filamentLoaded, uint8_t idlerSlotIndex, uint8_t selectorSlotIndex,
bool findaPressed, ml::Mode greenLEDMode, ml::Mode redLEDMode, ErrorCode err, ProgressCode topLevelProgress) {
VerifyEnvironmentState(filamentLoaded, idlerSlotIndex, selectorSlotIndex, findaPressed, greenLEDMode, redLEDMode);
CHECKED_ELSE(uf.Error() == err) {
return false;
}
CHECKED_ELSE(uf.TopLevelState() == topLevelProgress) { return false; }
return true;
}
@ -52,12 +61,13 @@ bool VerifyState2(SM &uf, bool filamentLoaded, uint8_t idlerSlotIndex, uint8_t s
return true;
}
template<typename SM>
void InvalidSlot(uint8_t invSlot, uint8_t activeSlot){
void InvalidSlot(SM &logicSM, uint8_t activeSlot, uint8_t invSlot){
ForceReinitAllAutomata();
SM logicSM;
REQUIRE(VerifyState(logicSM, false, mi::Idler::IdleSlotIndex(), 0, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK));
REQUIRE(VerifyEnvironmentState(false, mi::Idler::IdleSlotIndex(), 0, false, ml::off, ml::off));
EnsureActiveSlotIndex(activeSlot);

View File

@ -161,7 +161,24 @@ TEST_CASE("load_filament::failed_load_to_finda_0-4_resolve_help_second_fail", "[
}
TEST_CASE("load_filament::invalid_slot", "[load_filament]") {
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
InvalidSlot<logic::LoadFilament>(config::toolCount, cutSlot);
for (uint8_t activeSlot = 0; activeSlot < config::toolCount; ++activeSlot) {
logic::LoadFilament lf;
InvalidSlot<logic::LoadFilament>(lf, activeSlot, config::toolCount);
}
}
TEST_CASE("load_filament::state_machine_reusal", "[load_filament]") {
logic::LoadFilament lf;
for (uint8_t fromSlot = 0; fromSlot < config::toolCount; ++fromSlot) {
for (uint8_t toSlot = 0; toSlot < config::toolCount + 2; ++toSlot) {
logic::LoadFilament lf;
if (toSlot >= config::toolCount) {
InvalidSlot<logic::LoadFilament>(lf, fromSlot, toSlot);
} else {
LoadFilamentCommonSetup(toSlot, lf);
LoadFilamentSuccessful(toSlot, lf);
}
}
}
}

View File

@ -21,11 +21,9 @@ using Catch::Matchers::Equals;
#include "../helpers/helpers.ipp"
void ToolChange(uint8_t fromSlot, uint8_t toSlot) {
void ToolChange(logic::ToolChange tc, uint8_t fromSlot, uint8_t toSlot) {
ForceReinitAllAutomata();
logic::ToolChange tc;
EnsureActiveSlotIndex(fromSlot);
// restart the automaton
@ -55,11 +53,9 @@ void ToolChange(uint8_t fromSlot, uint8_t toSlot) {
REQUIRE(mg::globals.ActiveSlot() == toSlot);
}
void NoToolChange(uint8_t fromSlot, uint8_t toSlot) {
void NoToolChange(logic::ToolChange tc, uint8_t fromSlot, uint8_t toSlot) {
ForceReinitAllAutomata();
logic::ToolChange tc;
EnsureActiveSlotIndex(fromSlot);
// restart the automaton
@ -73,17 +69,35 @@ void NoToolChange(uint8_t fromSlot, uint8_t toSlot) {
TEST_CASE("tool_change::test0", "[tool_change]") {
for (uint8_t fromSlot = 0; fromSlot < config::toolCount; ++fromSlot) {
for (uint8_t toSlot = 0; toSlot < config::toolCount; ++toSlot) {
logic::ToolChange tc;
if (fromSlot != toSlot) {
ToolChange(fromSlot, toSlot);
ToolChange(tc, fromSlot, toSlot);
} else {
NoToolChange(fromSlot, toSlot);
NoToolChange(tc, fromSlot, toSlot);
}
}
}
}
TEST_CASE("tool_change::invalid_slot", "[tool_change]") {
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
InvalidSlot<logic::ToolChange>(config::toolCount, cutSlot);
for (uint8_t fromSlot = 0; fromSlot < config::toolCount; ++fromSlot) {
logic::ToolChange tc;
InvalidSlot<logic::ToolChange>(tc, fromSlot, config::toolCount);
}
}
TEST_CASE("tool_change::state_machine_reusal", "[tool_change]") {
logic::ToolChange tc;
for (uint8_t fromSlot = 0; fromSlot < config::toolCount; ++fromSlot) {
for (uint8_t toSlot = 0; toSlot < config::toolCount + 2; ++toSlot) {
if (toSlot >= config::toolCount) {
InvalidSlot<logic::ToolChange>(tc, fromSlot, toSlot);
} else if (fromSlot != toSlot) {
ToolChange(tc, fromSlot, toSlot);
} else {
NoToolChange(tc, fromSlot, toSlot);
}
}
}
}