From d80a58cfdb6a16b2b8526e7a7c1cdfeb548b770c Mon Sep 17 00:00:00 2001 From: "D.R.racer" Date: Sat, 18 Jun 2022 16:27:54 +0200 Subject: [PATCH] Fix unit tests --- src/config/config.h | 2 +- src/modules/user_input.cpp | 24 +++++-- src/modules/user_input.h | 11 +-- .../load_filament/test_load_filament.cpp | 35 +++++++-- tests/unit/logic/stubs/homing.cpp | 2 +- tests/unit/logic/stubs/main_loop_stub.cpp | 22 ++++-- tests/unit/logic/stubs/main_loop_stub.h | 4 +- .../logic/tool_change/test_tool_change.cpp | 27 +++---- .../unload_filament/test_unload_filament.cpp | 16 +++-- .../unload_to_finda/test_unload_to_finda.cpp | 8 +-- tests/unit/modules/CMakeLists.txt | 1 + tests/unit/modules/user_input/CMakeLists.txt | 15 ++++ .../modules/user_input/test_user_input.cpp | 71 +++++++++++++++++++ 13 files changed, 194 insertions(+), 44 deletions(-) create mode 100644 tests/unit/modules/user_input/CMakeLists.txt create mode 100644 tests/unit/modules/user_input/test_user_input.cpp diff --git a/src/config/config.h b/src/config/config.h index baeffe1..1b090b7 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -22,7 +22,7 @@ static constexpr const uint8_t toolCount = 5U; ///< Max number of extruders/tool static_assert(toolCount < 15, "Up to 14 valid slots (+1 parking) is supported in EEPROM storage"); // Printer's filament sensor setup -static constexpr const uint16_t fsensorDebounceMs = 10; +static constexpr const uint16_t fsensorDebounceMs = 2; // LEDS /// The complete period of LED's blinking (i.e. ON and OFF together) diff --git a/src/modules/user_input.cpp b/src/modules/user_input.cpp index e2a22f2..82bd17f 100644 --- a/src/modules/user_input.cpp +++ b/src/modules/user_input.cpp @@ -17,23 +17,39 @@ void UserInput::Step() { } void UserInput::ProcessMessage(uint8_t ev) { - eventQueue.push((Event)ev); + eventQueue.push((Event)(ev | Event::FromPrinter)); +} + +Event UserInput::StripFromPrinterBit(uint8_t e) { + e &= (uint8_t)(~Event::FromPrinter); + return (Event)e; } Event UserInput::ConsumeEvent() { if (printerInCharge) { + Event rv = eventQueue.front(); + if (rv & Event::FromPrinter) { + eventQueue.pop(rv); + return StripFromPrinterBit(rv); + } return Event::NoEvent; } else { - return ConsumeEventForPrinter(); + Event rv; + eventQueue.pop(rv); + return StripFromPrinterBit(rv); } } Event UserInput::ConsumeEventForPrinter() { if (eventQueue.empty()) return Event::NoEvent; - Event rv; + Event rv = eventQueue.front(); + if (rv & Event::FromPrinter) { + // do not send the same buttons back but leave them in the queue for the MMU FW + return Event::NoEvent; + } eventQueue.pop(rv); - return rv; + return StripFromPrinterBit(rv); } void UserInput::Clear() { diff --git a/src/modules/user_input.h b/src/modules/user_input.h index 6c3115e..f128623 100644 --- a/src/modules/user_input.h +++ b/src/modules/user_input.h @@ -9,11 +9,12 @@ namespace modules { namespace user_input { /// Beware - button codes intentionally match the protocol button encoding for optimization purposes -enum class Event : int8_t { - NoEvent = -1, - Left = 0, +enum Event : uint8_t { + NoEvent = 0x7f, + Right = 0, Middle = 1, - Right = 2 + Left = 2, + FromPrinter = 0x80 }; class UserInput { @@ -58,6 +59,8 @@ public: private: CircularBuffer eventQueue; bool printerInCharge = false; + + static Event StripFromPrinterBit(uint8_t e); }; extern UserInput userInput; diff --git a/tests/unit/logic/load_filament/test_load_filament.cpp b/tests/unit/logic/load_filament/test_load_filament.cpp index a057043..d496630 100644 --- a/tests/unit/logic/load_filament/test_load_filament.cpp +++ b/tests/unit/logic/load_filament/test_load_filament.cpp @@ -79,6 +79,25 @@ void LoadFilamentSuccessful(uint8_t slot, logic::LoadFilament &lf) { REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK)); } +void LoadFilamentSuccessfulWithRehomeSelector(uint8_t slot, logic::LoadFilament &lf) { + // Stage 2 - feeding to finda + // make FINDA switch on + REQUIRE(WhileCondition(lf, std::bind(SimulateFeedToFINDA, _1, 100), 5000)); + REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, slot, slot, true, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::RetractingFromFinda)); + + // Stage 3 - retracting from finda + // we'll assume the finda is working correctly here + REQUIRE(WhileCondition(lf, std::bind(SimulateRetractFromFINDA, _1, 100), 5000)); + REQUIRE(WhileCondition( + lf, [&](uint32_t) { return lf.State() == ProgressCode::RetractingFromFinda; }, 50000)); + REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, slot, 0xff, false, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::DisengagingIdler)); + + // Stage 4 - disengaging Idler + homing Selector simultaneously + SimulateSelectorHoming(lf); + + REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK)); +} + TEST_CASE("load_filament::regular_load_to_slot_0-4", "[load_filament]") { for (uint8_t slot = 0; slot < config::toolCount; ++slot) { logic::LoadFilament lf; @@ -106,10 +125,12 @@ void FailedLoadToFindaResolveHelp(uint8_t slot, logic::LoadFilament &lf) { // - resolve the problem by hand - after pressing the button we shall check, that FINDA is off and we should do what? // In this case we check the first option - PressButtonAndDebounce(lf, mb::Left); + PressButtonAndDebounce(lf, mb::Left, false); REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::blink0, ErrorCode::RUNNING, ProgressCode::ERREngagingIdler)); + SimulateIdlerHoming(lf); + // Stage 4 - engage the idler REQUIRE(WhileTopState(lf, ProgressCode::ERREngagingIdler, idlerEngageDisengageMaxSteps)); @@ -144,7 +165,7 @@ void FailedLoadToFindaResolveManual(uint8_t slot, logic::LoadFilament &lf) { // Perform press on button 2 + debounce + switch on FINDA hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::high); - PressButtonAndDebounce(lf, mb::Right); + PressButtonAndDebounce(lf, mb::Right, false); // the Idler also engages in this call as this is planned as the next step SimulateIdlerHoming(lf); @@ -189,7 +210,7 @@ void FailedLoadToFindaResolveManual(uint8_t slot, logic::LoadFilament &lf) { void FailedLoadToFindaResolveManualNoFINDA(uint8_t slot, logic::LoadFilament &lf) { // Perform press on button 2 + debounce + keep FINDA OFF (i.e. the user didn't solve anything) - PressButtonAndDebounce(lf, mb::Right); + PressButtonAndDebounce(lf, mb::Right, false); SimulateIdlerHoming(lf); @@ -200,14 +221,16 @@ void FailedLoadToFindaResolveManualNoFINDA(uint8_t slot, logic::LoadFilament &lf } void FailedLoadToFindaResolveTryAgain(uint8_t slot, logic::LoadFilament &lf) { - PressButtonAndDebounce(lf, mb::Middle); + PressButtonAndDebounce(lf, mb::Middle, false); // the state machine should have restarted // Idler's position needs to be ignored as it has started homing after the button press REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, config::toolCount, slot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::FeedingToFinda)); ClearButtons(lf); - LoadFilamentSuccessful(slot, lf); + SimulateIdlerHoming(lf); + + LoadFilamentSuccessfulWithRehomeSelector(slot, lf); } TEST_CASE("load_filament::failed_load_to_finda_0-4_resolve_help_second_ok", "[load_filament]") { @@ -330,7 +353,7 @@ void LoadFilamentStopped(uint8_t slot, logic::LoadFilament &lf) { REQUIRE_FALSE(WhileTopState(lf, ProgressCode::FeedingToFinda, 5000)); // now press a button - PressButtonAndDebounce(lf, mb::Middle); + PressButtonAndDebounce(lf, mb::Middle, false); REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, slot, slot, false, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::RetractingFromFinda)); diff --git a/tests/unit/logic/stubs/homing.cpp b/tests/unit/logic/stubs/homing.cpp index 48d1d5e..4e2c87f 100644 --- a/tests/unit/logic/stubs/homing.cpp +++ b/tests/unit/logic/stubs/homing.cpp @@ -134,7 +134,7 @@ bool SimulateFailedHomeSelectorPostfix(logic::CommandBase &cb) { if (mm::motion.Enabled(mm::Selector)) return false; - PressButtonAndDebounce(cb, mb::Middle); + PressButtonAndDebounce(cb, mb::Middle, false); // it shall start homing again if (cb.Error() != ErrorCode::RUNNING) diff --git a/tests/unit/logic/stubs/main_loop_stub.cpp b/tests/unit/logic/stubs/main_loop_stub.cpp index 9ca7bb5..da3f840 100644 --- a/tests/unit/logic/stubs/main_loop_stub.cpp +++ b/tests/unit/logic/stubs/main_loop_stub.cpp @@ -58,6 +58,7 @@ void ForceReinitAllAutomata() { new (&mpu::pulley) mpu::Pulley(); new (&ms::selector) ms::Selector(); new (&mm::motion) mm::Motion(); + new (&mui::userInput) mui::UserInput(); hal::eeprom::ClearEEPROM(); @@ -133,11 +134,17 @@ bool SimulateRetractFromFINDA(uint32_t step, uint32_t findaOff) { return mf::finda.Pressed(); } -void PressButtonAndDebounce(logic::CommandBase &cb, uint8_t btnIndex) { - hal::adc::SetADC(config::buttonsADCIndex, config::buttonADCLimits[btnIndex][0] + 1); - while (!mb::buttons.ButtonPressed(btnIndex)) { +void PressButtonAndDebounce(logic::CommandBase &cb, uint8_t btnIndex, bool fromPrinter) { + if (fromPrinter) { + mui::userInput.ProcessMessage(btnIndex); main_loop(); - cb.Step(); // Inner + cb.Step(); + } else { + hal::adc::SetADC(config::buttonsADCIndex, config::buttonADCLimits[btnIndex][0] + 1); + while (!mb::buttons.ButtonPressed(btnIndex)) { + main_loop(); + cb.Step(); // Inner + } } } @@ -148,3 +155,10 @@ void ClearButtons(logic::CommandBase &cb) { cb.Step(); // Inner } } + +void SetFSensorStateAndDebounce(bool press) { + mfs::fsensor.ProcessMessage(press); + for (uint8_t fs = 0; fs < config::fsensorDebounceMs + 1; ++fs) { + main_loop(); + } +} diff --git a/tests/unit/logic/stubs/main_loop_stub.h b/tests/unit/logic/stubs/main_loop_stub.h index beab977..23a935c 100644 --- a/tests/unit/logic/stubs/main_loop_stub.h +++ b/tests/unit/logic/stubs/main_loop_stub.h @@ -29,9 +29,11 @@ bool SimulateUnloadToFINDA(uint32_t step, uint32_t fsOff, uint32_t findaOff); bool SimulateFeedToFINDA(uint32_t step, uint32_t findaOn); bool SimulateRetractFromFINDA(uint32_t step, uint32_t findaOff); -void PressButtonAndDebounce(logic::CommandBase &cb, uint8_t btnIndex); +void PressButtonAndDebounce(logic::CommandBase &cb, uint8_t btnIndex, bool fromPrinter); void ClearButtons(logic::CommandBase &cb); +void SetFSensorStateAndDebounce(bool press); + // these are recommended max steps for simulated movement of the idler and selector // - roughly the amount of motion steps from one end to the other + some margin // ... could be computed in the future from the pre-set number of microsteps and real positions diff --git a/tests/unit/logic/tool_change/test_tool_change.cpp b/tests/unit/logic/tool_change/test_tool_change.cpp index 25960d3..fb0f3af 100644 --- a/tests/unit/logic/tool_change/test_tool_change.cpp +++ b/tests/unit/logic/tool_change/test_tool_change.cpp @@ -9,6 +9,7 @@ #include "../../../../src/modules/motion.h" #include "../../../../src/modules/permanent_storage.h" #include "../../../../src/modules/selector.h" +#include "../../../../src/modules/user_input.h" #include "../../../../src/logic/tool_change.h" @@ -67,7 +68,7 @@ void ToolChange(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSlot) { REQUIRE(EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle)); SetFINDAStateAndDebounce(true); - mfs::fsensor.ProcessMessage(true); + SetFSensorStateAndDebounce(true); // restart the automaton tc.Reset(toSlot); @@ -98,8 +99,8 @@ void NoToolChange(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSlot) { REQUIRE(EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle)); // the filament is LOADED - mfs::fsensor.ProcessMessage(true); SetFINDAStateAndDebounce(true); + SetFSensorStateAndDebounce(true); REQUIRE(VerifyEnvironmentState(mg::FilamentLoadState::InNozzle, mi::Idler::IdleSlotIndex(), toSlot, true, false, ml::off, ml::off)); @@ -177,7 +178,7 @@ void ToolChangeFailLoadToFinda(logic::ToolChange &tc, uint8_t fromSlot, uint8_t REQUIRE(EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle)); SetFINDAStateAndDebounce(true); - mfs::fsensor.ProcessMessage(true); + SetFSensorStateAndDebounce(true); // restart the automaton tc.Reset(toSlot); @@ -197,7 +198,7 @@ void ToolChangeFailLoadToFinda(logic::ToolChange &tc, uint8_t fromSlot, uint8_t void ToolChangeFailLoadToFindaLeftBtn(logic::ToolChange &tc, uint8_t toSlot) { // now waiting for user input - PressButtonAndDebounce(tc, mb::Left); + PressButtonAndDebounce(tc, mb::Left, true); REQUIRE(WhileTopState(tc, ProgressCode::ERREngagingIdler, 5000UL)); ClearButtons(tc); @@ -223,7 +224,7 @@ void ToolChangeFailLoadToFindaLeftBtn(logic::ToolChange &tc, uint8_t toSlot) { void ToolChangeFailLoadToFindaMiddleBtn(logic::ToolChange &tc, uint8_t toSlot) { // now waiting for user input - PressButtonAndDebounce(tc, mb::Middle); + PressButtonAndDebounce(tc, mb::Middle, true); REQUIRE(WhileCondition( tc, @@ -251,8 +252,10 @@ void ToolChangeFailLoadToFindaMiddleBtn(logic::ToolChange &tc, uint8_t toSlot) { void ToolChangeFailLoadToFindaRightBtnFINDA_FSensor(logic::ToolChange &tc, uint8_t toSlot) { // now waiting for user input - press FINDA and FSensor SetFINDAStateAndDebounce(true); - mfs::fsensor.ProcessMessage(true); - PressButtonAndDebounce(tc, mb::Right); + REQUIRE(mf::finda.Pressed()); + SetFSensorStateAndDebounce(true); + REQUIRE(mfs::fsensor.Pressed()); + PressButtonAndDebounce(tc, mb::Right, true); CheckFinishedCorrectly(tc, toSlot); @@ -262,7 +265,7 @@ void ToolChangeFailLoadToFindaRightBtnFINDA_FSensor(logic::ToolChange &tc, uint8 void ToolChangeFailLoadToFindaRightBtnFINDA(logic::ToolChange &tc, uint8_t toSlot) { // now waiting for user input - press FINDA SetFINDAStateAndDebounce(true); - PressButtonAndDebounce(tc, mb::Right); + PressButtonAndDebounce(tc, mb::Right, true); REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), toSlot, true, false, ml::off, ml::blink0, ErrorCode::FSENSOR_DIDNT_SWITCH_ON, ProgressCode::ERRWaitingForUser)); @@ -271,7 +274,7 @@ void ToolChangeFailLoadToFindaRightBtnFINDA(logic::ToolChange &tc, uint8_t toSlo void ToolChangeFailLoadToFindaRightBtn(logic::ToolChange &tc, uint8_t toSlot) { // now waiting for user input - do not press anything - PressButtonAndDebounce(tc, mb::Right); + PressButtonAndDebounce(tc, mb::Right, true); REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), toSlot, false, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERRWaitingForUser)); @@ -332,7 +335,7 @@ void ToolChangeFailFSensor(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSl REQUIRE(EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle)); SetFINDAStateAndDebounce(true); - mfs::fsensor.ProcessMessage(true); + SetFSensorStateAndDebounce(true); // restart the automaton tc.Reset(toSlot); @@ -348,8 +351,8 @@ void ToolChangeFailFSensorMiddleBtn(logic::ToolChange &tc, uint8_t fromSlot, uin using namespace std::placeholders; // user pulls filament out from the fsensor and presses Retry - mfs::fsensor.ProcessMessage(false); - PressButtonAndDebounce(tc, mb::Middle); + SetFSensorStateAndDebounce(false); + PressButtonAndDebounce(tc, mb::Middle, true); REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::idler.IdleSlotIndex(), fromSlot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingFilament)); REQUIRE(tc.unl.State() == ProgressCode::FeedingToFinda); // MMU must find out where the filament is FS is OFF, FINDA is OFF diff --git a/tests/unit/logic/unload_filament/test_unload_filament.cpp b/tests/unit/logic/unload_filament/test_unload_filament.cpp index bbd66a4..619b8af 100644 --- a/tests/unit/logic/unload_filament/test_unload_filament.cpp +++ b/tests/unit/logic/unload_filament/test_unload_filament.cpp @@ -171,7 +171,7 @@ void FindaDidntTriggerResolveHelp(uint8_t slot, logic::UnloadFilament &uf) { // In this case we check the first option // Perform press on button 0 + debounce - PressButtonAndDebounce(uf, mb::Left); + PressButtonAndDebounce(uf, mb::Left, false); // we still think we have filament loaded at this stage // idler should have been disengaged @@ -180,6 +180,8 @@ void FindaDidntTriggerResolveHelp(uint8_t slot, logic::UnloadFilament &uf) { // red LED should blink, green LED should be off REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, true, false, ml::off, ml::blink0, ErrorCode::RUNNING, ProgressCode::ERREngagingIdler)); + SimulateIdlerHoming(uf); + // Stage 4 - engage the idler REQUIRE(WhileTopState(uf, ProgressCode::ERREngagingIdler, idlerEngageDisengageMaxSteps)); @@ -249,7 +251,7 @@ void FindaDidntTriggerResolveTryAgain(uint8_t slot, logic::UnloadFilament &uf) { // - resolve the problem by hand - after pressing the button we shall check, that FINDA is off and we should do what? // In this case we check the second option - PressButtonAndDebounce(uf, mb::Middle); + PressButtonAndDebounce(uf, mb::Middle, false); // we still think we have filament loaded at this stage // idler should have been disengaged @@ -296,7 +298,7 @@ void FailedUnloadResolveManual(uint8_t slot, logic::UnloadFilament &uf) { // Perform press on button 2 + debounce + switch off FINDA hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low); - PressButtonAndDebounce(uf, mb::Right); + PressButtonAndDebounce(uf, mb::Right, false); REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::FeedingToFinda)); @@ -320,7 +322,7 @@ void FailedUnloadResolveManualFINDAon(uint8_t slot, logic::UnloadFilament &uf) { // simulate the user fixed the issue himself // Perform press on button 2 + debounce + keep FINDA on - PressButtonAndDebounce(uf, mb::Right); + PressButtonAndDebounce(uf, mb::Right, false); REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, true, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERRWaitingForUser)); } @@ -329,9 +331,9 @@ void FailedUnloadResolveManualFSensorOn(uint8_t slot, logic::UnloadFilament &uf) // simulate the user fixed the issue himself // Perform press on button 2 + debounce + keep FSensor on - mfs::fsensor.ProcessMessage(true); + SetFSensorStateAndDebounce(true); hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low); - PressButtonAndDebounce(uf, mb::Right); + PressButtonAndDebounce(uf, mb::Right, false); REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::blink0, ErrorCode::FSENSOR_DIDNT_SWITCH_OFF, ProgressCode::ERRWaitingForUser)); } @@ -367,7 +369,7 @@ TEST_CASE("unload_filament::unload_homing_retry", "[unload_filament][homing]") { // simulate the user fixed the issue himself (not really important, we are after a failed homing of the selector) hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low); - PressButtonAndDebounce(uf, mb::Right); + PressButtonAndDebounce(uf, mb::Right, false); SimulateIdlerHoming(uf); // make Idler happy REQUIRE(WhileCondition(uf, std::bind(SimulateFeedToFINDA, _1, 100), 5000)); diff --git a/tests/unit/logic/unload_to_finda/test_unload_to_finda.cpp b/tests/unit/logic/unload_to_finda/test_unload_to_finda.cpp index e55f5ea..ff411e8 100644 --- a/tests/unit/logic/unload_to_finda/test_unload_to_finda.cpp +++ b/tests/unit/logic/unload_to_finda/test_unload_to_finda.cpp @@ -31,7 +31,7 @@ TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") { // we need finda ON SetFINDAStateAndDebounce(true); // fsensor should be ON - mfs::fsensor.ProcessMessage(true); + SetFSensorStateAndDebounce(true); // and MMU "thinks" it has the filament loaded mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle); @@ -83,7 +83,7 @@ TEST_CASE("unload_to_finda::unload_without_FINDA_trigger", "[unload_to_finda]") // we need finda ON SetFINDAStateAndDebounce(true); // fsensor should be ON - mfs::fsensor.ProcessMessage(true); + SetFSensorStateAndDebounce(true); // and MMU "thinks" it has the filament loaded mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle); @@ -124,7 +124,7 @@ TEST_CASE("unload_to_finda::unload_without_FSensor_trigger", "[unload_to_finda]" // we need finda ON SetFINDAStateAndDebounce(true); // fsensor should be ON - mfs::fsensor.ProcessMessage(true); + SetFSensorStateAndDebounce(true); // and MMU "thinks" it has the filament loaded mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle); @@ -165,7 +165,7 @@ TEST_CASE("unload_to_finda::unload_repeated", "[unload_to_finda]") { // we need finda ON SetFINDAStateAndDebounce(true); // fsensor should be ON - mfs::fsensor.ProcessMessage(true); + SetFSensorStateAndDebounce(true); // and MMU "thinks" it has the filament loaded mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle); diff --git a/tests/unit/modules/CMakeLists.txt b/tests/unit/modules/CMakeLists.txt index f487280..4fec6a2 100644 --- a/tests/unit/modules/CMakeLists.txt +++ b/tests/unit/modules/CMakeLists.txt @@ -5,3 +5,4 @@ add_subdirectory(speed_table) add_subdirectory(pulse_gen) add_subdirectory(motion) add_subdirectory(timebase) +add_subdirectory(user_input) diff --git a/tests/unit/modules/user_input/CMakeLists.txt b/tests/unit/modules/user_input/CMakeLists.txt new file mode 100644 index 0000000..136ad93 --- /dev/null +++ b/tests/unit/modules/user_input/CMakeLists.txt @@ -0,0 +1,15 @@ +# define the test executable +add_executable( + user_input_tests + ${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp ${CMAKE_SOURCE_DIR}/src/modules/debouncer.cpp + ${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp ${MODULES_STUBS_DIR}/stub_adc.cpp + ${MODULES_STUBS_DIR}/stub_timebase.cpp test_user_input.cpp + ) + +# define required search paths +target_include_directories( + user_input_tests PUBLIC ${CMAKE_SOURCE_DIR}/src/modules ${CMAKE_SOURCE_DIR}/src/hal + ) + +# tell build system about the test case +add_catch_test(user_input_tests) diff --git a/tests/unit/modules/user_input/test_user_input.cpp b/tests/unit/modules/user_input/test_user_input.cpp new file mode 100644 index 0000000..8c2e267 --- /dev/null +++ b/tests/unit/modules/user_input/test_user_input.cpp @@ -0,0 +1,71 @@ +#include "catch2/catch.hpp" +#include "../stubs/stub_adc.h" +#include "../stubs/stub_timebase.h" +#include "buttons.h" +#include "../hal/adc.h" +#include "user_input.h" + +void PressButtonAndDebounce(uint8_t btnIndex) { + hal::adc::SetADC(config::buttonsADCIndex, config::buttonADCLimits[btnIndex][0] + 1); + while (!mb::buttons.ButtonPressed(btnIndex)) { + mb::buttons.Step(); + mui::userInput.Step(); + mt::IncMillis(); + } +} + +TEST_CASE("user_input::printer_in_charge", "[user_input]") { + uint8_t button; + mui::Event event; + std::tie(button, event) = GENERATE( + std::make_tuple(mb::Left, mui::Event::Left), + std::make_tuple(mb::Middle, mui::Event::Middle), + std::make_tuple(mb::Right, mui::Event::Right)); + + mt::ReinitTimebase(); + mb::Buttons b; + // reset UI + new (&mui::userInput) mui::UserInput(); + REQUIRE_FALSE(mui::userInput.PrinterInCharge()); + + // set printer in charge + mui::userInput.SetPrinterInCharge(true); + REQUIRE(mui::userInput.PrinterInCharge()); + + // put some button into the buffer - should be marked as "from printer" + mui::userInput.ProcessMessage(button); + // i.e. we should NOT be able to extract that message with ConsumeEventForPrinter() + REQUIRE(mui::userInput.ConsumeEventForPrinter() == mui::NoEvent); + // but we should be able to extract that message with ConsumeEvent() + REQUIRE(mui::userInput.ConsumeEvent() == event); + + // press a button on the MMU + PressButtonAndDebounce(button); + REQUIRE(mb::buttons.ButtonPressed(button)); + // we should NOT be able to extract the event with ConsumeEvent + REQUIRE(mui::userInput.ConsumeEvent() == mui::NoEvent); + // but we should be able to extract that message with ConsumeEventForPrinter + REQUIRE(mui::userInput.ConsumeEventForPrinter() == event); +} + +TEST_CASE("user_input::button_pressed_MMU", "[user_input]") { + uint8_t button; + mui::Event event; + std::tie(button, event) = GENERATE( + std::make_tuple(mb::Left, mui::Event::Left), + std::make_tuple(mb::Middle, mui::Event::Middle), + std::make_tuple(mb::Right, mui::Event::Right)); + + // create a button press + mt::ReinitTimebase(); + mb::Buttons b; + + // reset UI + new (&mui::userInput) mui::UserInput(); + REQUIRE_FALSE(mui::userInput.PrinterInCharge()); + + PressButtonAndDebounce(button); + REQUIRE(mb::buttons.ButtonPressed(button)); + // we should be able to extract the event with ConsumeEvent + REQUIRE(mui::userInput.ConsumeEvent() == event); +}