Add unit tests for logic state machines reusal
as it will work in the real FWpull/83/head
parent
ccefe32ba1
commit
e0ea47595f
|
|
@ -21,12 +21,11 @@ using Catch::Matchers::Equals;
|
||||||
|
|
||||||
#include "../helpers/helpers.ipp"
|
#include "../helpers/helpers.ipp"
|
||||||
|
|
||||||
void CutSlot(uint8_t cutSlot) {
|
void CutSlot(logic::CutFilament &cf, uint8_t cutSlot) {
|
||||||
|
|
||||||
ForceReinitAllAutomata();
|
ForceReinitAllAutomata();
|
||||||
|
|
||||||
logic::CutFilament cf;
|
REQUIRE(VerifyEnvironmentState(false, mi::Idler::IdleSlotIndex(), 0, false, ml::off, ml::off));
|
||||||
REQUIRE(VerifyState(cf, false, mi::Idler::IdleSlotIndex(), 0, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK));
|
|
||||||
|
|
||||||
EnsureActiveSlotIndex(cutSlot);
|
EnsureActiveSlotIndex(cutSlot);
|
||||||
|
|
||||||
|
|
@ -87,12 +86,30 @@ void CutSlot(uint8_t cutSlot) {
|
||||||
|
|
||||||
TEST_CASE("cut_filament::cut0", "[cut_filament]") {
|
TEST_CASE("cut_filament::cut0", "[cut_filament]") {
|
||||||
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
|
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]") {
|
TEST_CASE("cut_filament::invalid_slot", "[cut_filament]") {
|
||||||
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
|
for (uint8_t activeSlot = 0; activeSlot < config::toolCount; ++activeSlot) {
|
||||||
InvalidSlot<logic::CutFilament>(config::toolCount, cutSlot);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,12 +70,8 @@ TEST_CASE("eject_filament::eject0", "[eject_filament][.]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("eject_filament::invalid_slot", "[eject_filament]") {
|
TEST_CASE("eject_filament::invalid_slot", "[eject_filament]") {
|
||||||
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
|
for (uint8_t activeSlot = 0; activeSlot < config::toolCount; ++activeSlot) {
|
||||||
InvalidSlot<logic::EjectFilament>(config::toolCount, cutSlot);
|
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
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
// LED checked at selector's index
|
bool VerifyEnvironmentState(bool filamentLoaded, uint8_t idlerSlotIndex, uint8_t selectorSlotIndex,
|
||||||
template<typename SM>
|
bool findaPressed, ml::Mode greenLEDMode, ml::Mode redLEDMode) {
|
||||||
bool VerifyState(SM &uf, bool filamentLoaded, uint8_t idlerSlotIndex, uint8_t selectorSlotIndex,
|
|
||||||
bool findaPressed, ml::Mode greenLEDMode, ml::Mode redLEDMode, ErrorCode err, ProgressCode topLevelProgress) {
|
|
||||||
CHECKED_ELSE(mg::globals.FilamentLoaded() == filamentLoaded) { return false; }
|
CHECKED_ELSE(mg::globals.FilamentLoaded() == filamentLoaded) { return false; }
|
||||||
CHECKED_ELSE(mm::axes[mm::Idler].pos == mi::Idler::SlotPosition(idlerSlotIndex).v) { 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; }
|
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; }
|
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; }
|
CHECKED_ELSE(uf.TopLevelState() == topLevelProgress) { return false; }
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -52,12 +61,13 @@ bool VerifyState2(SM &uf, bool filamentLoaded, uint8_t idlerSlotIndex, uint8_t s
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename SM>
|
template<typename SM>
|
||||||
void InvalidSlot(uint8_t invSlot, uint8_t activeSlot){
|
void InvalidSlot(SM &logicSM, uint8_t activeSlot, uint8_t invSlot){
|
||||||
ForceReinitAllAutomata();
|
ForceReinitAllAutomata();
|
||||||
|
|
||||||
SM logicSM;
|
REQUIRE(VerifyEnvironmentState(false, mi::Idler::IdleSlotIndex(), 0, false, ml::off, ml::off));
|
||||||
REQUIRE(VerifyState(logicSM, false, mi::Idler::IdleSlotIndex(), 0, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK));
|
|
||||||
|
|
||||||
EnsureActiveSlotIndex(activeSlot);
|
EnsureActiveSlotIndex(activeSlot);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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]") {
|
TEST_CASE("load_filament::invalid_slot", "[load_filament]") {
|
||||||
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
|
for (uint8_t activeSlot = 0; activeSlot < config::toolCount; ++activeSlot) {
|
||||||
InvalidSlot<logic::LoadFilament>(config::toolCount, cutSlot);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,9 @@ using Catch::Matchers::Equals;
|
||||||
|
|
||||||
#include "../helpers/helpers.ipp"
|
#include "../helpers/helpers.ipp"
|
||||||
|
|
||||||
void ToolChange(uint8_t fromSlot, uint8_t toSlot) {
|
void ToolChange(logic::ToolChange tc, uint8_t fromSlot, uint8_t toSlot) {
|
||||||
ForceReinitAllAutomata();
|
ForceReinitAllAutomata();
|
||||||
|
|
||||||
logic::ToolChange tc;
|
|
||||||
|
|
||||||
EnsureActiveSlotIndex(fromSlot);
|
EnsureActiveSlotIndex(fromSlot);
|
||||||
|
|
||||||
// restart the automaton
|
// restart the automaton
|
||||||
|
|
@ -55,11 +53,9 @@ void ToolChange(uint8_t fromSlot, uint8_t toSlot) {
|
||||||
REQUIRE(mg::globals.ActiveSlot() == 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();
|
ForceReinitAllAutomata();
|
||||||
|
|
||||||
logic::ToolChange tc;
|
|
||||||
|
|
||||||
EnsureActiveSlotIndex(fromSlot);
|
EnsureActiveSlotIndex(fromSlot);
|
||||||
|
|
||||||
// restart the automaton
|
// restart the automaton
|
||||||
|
|
@ -73,17 +69,35 @@ void NoToolChange(uint8_t fromSlot, uint8_t toSlot) {
|
||||||
TEST_CASE("tool_change::test0", "[tool_change]") {
|
TEST_CASE("tool_change::test0", "[tool_change]") {
|
||||||
for (uint8_t fromSlot = 0; fromSlot < config::toolCount; ++fromSlot) {
|
for (uint8_t fromSlot = 0; fromSlot < config::toolCount; ++fromSlot) {
|
||||||
for (uint8_t toSlot = 0; toSlot < config::toolCount; ++toSlot) {
|
for (uint8_t toSlot = 0; toSlot < config::toolCount; ++toSlot) {
|
||||||
|
logic::ToolChange tc;
|
||||||
if (fromSlot != toSlot) {
|
if (fromSlot != toSlot) {
|
||||||
ToolChange(fromSlot, toSlot);
|
ToolChange(tc, fromSlot, toSlot);
|
||||||
} else {
|
} else {
|
||||||
NoToolChange(fromSlot, toSlot);
|
NoToolChange(tc, fromSlot, toSlot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("tool_change::invalid_slot", "[tool_change]") {
|
TEST_CASE("tool_change::invalid_slot", "[tool_change]") {
|
||||||
for (uint8_t cutSlot = 0; cutSlot < config::toolCount; ++cutSlot) {
|
for (uint8_t fromSlot = 0; fromSlot < config::toolCount; ++fromSlot) {
|
||||||
InvalidSlot<logic::ToolChange>(config::toolCount, cutSlot);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue