From 6eb4ec0df1be825a667c3bb6ed442872b32115b9 Mon Sep 17 00:00:00 2001 From: "D.R.racer" Date: Thu, 9 Jun 2022 17:30:55 +0200 Subject: [PATCH] Improve robustness of unit tests --- .../logic/tool_change/test_tool_change.cpp | 4 +- tests/unit/modules/buttons/test_buttons.cpp | 136 ++++++++---------- tests/unit/modules/stubs/stub_adc.cpp | 8 +- tests/unit/modules/stubs/stub_adc.h | 3 + 4 files changed, 71 insertions(+), 80 deletions(-) diff --git a/tests/unit/logic/tool_change/test_tool_change.cpp b/tests/unit/logic/tool_change/test_tool_change.cpp index 1145c86..421af33 100644 --- a/tests/unit/logic/tool_change/test_tool_change.cpp +++ b/tests/unit/logic/tool_change/test_tool_change.cpp @@ -250,7 +250,7 @@ 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 - hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::high); + SetFINDAStateAndDebounce(true); mfs::fsensor.ProcessMessage(true); PressButtonAndDebounce(tc, mb::Right); @@ -261,7 +261,7 @@ void ToolChangeFailLoadToFindaRightBtnFINDA_FSensor(logic::ToolChange &tc, uint8 void ToolChangeFailLoadToFindaRightBtnFINDA(logic::ToolChange &tc, uint8_t toSlot) { // now waiting for user input - press FINDA - hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::high); + SetFINDAStateAndDebounce(true); PressButtonAndDebounce(tc, mb::Right); REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), toSlot, true, false, ml::off, ml::blink0, ErrorCode::FSENSOR_DIDNT_SWITCH_ON, ProgressCode::ERRWaitingForUser)); diff --git a/tests/unit/modules/buttons/test_buttons.cpp b/tests/unit/modules/buttons/test_buttons.cpp index 2b5a844..fe25777 100644 --- a/tests/unit/modules/buttons/test_buttons.cpp +++ b/tests/unit/modules/buttons/test_buttons.cpp @@ -2,6 +2,7 @@ #include "../stubs/stub_adc.h" #include "../stubs/stub_timebase.h" #include "buttons.h" +#include "../hal/adc.h" bool Step_Basic_One_Button_Test(mb::Buttons &b, uint8_t oversampleFactor, uint8_t testedButtonIndex, uint8_t otherButton1, uint8_t otherButton2) { for (uint8_t i = 0; i < oversampleFactor; ++i) { @@ -12,7 +13,7 @@ bool Step_Basic_One_Button_Test(mb::Buttons &b, uint8_t oversampleFactor, uint8_ CHECK(!b.ButtonPressed(otherButton1)); CHECK(!b.ButtonPressed(otherButton2)); - for (uint8_t i = 0; i < oversampleFactor; ++i) { + for (uint8_t i = 0; i < oversampleFactor - 1; ++i) { b.Step(); mt::IncMillis(); } @@ -47,7 +48,7 @@ bool Step_Basic_One_Button(hal::adc::TADCData &&d, uint8_t testedButtonIndex) { mt::ReinitTimebase(); mb::Buttons b; - // need to oversample the data as debouncing takes 100 cycles to accept a pressed button + // need to oversample the data as debouncing takes some cycles to accept a pressed button constexpr uint8_t oversampleFactor = config::buttonsDebounceMs; hal::adc::ReinitADC(config::buttonsADCIndex, std::move(d), oversampleFactor); @@ -87,7 +88,7 @@ TEST_CASE("buttons::Step-basic-button-one-after-other", "[buttons]") { M1(config::buttonADCLimits[2][0]), config::buttonADCLimits[2][0] + 1, config::buttonADCMaxValue }); mb::Buttons b; - // need to oversample the data as debouncing takes 100 cycles to accept a pressed button + // need to oversample the data as debouncing takes some cycles to accept a pressed button constexpr uint8_t oversampleFactor = config::buttonsDebounceMs; hal::adc::ReinitADC(config::buttonsADCIndex, std::move(d), oversampleFactor); @@ -96,96 +97,79 @@ TEST_CASE("buttons::Step-basic-button-one-after-other", "[buttons]") { CHECK(Step_Basic_One_Button_Test(b, oversampleFactor, 2, 0, 1)); } +void StepAndCheck(mb::Buttons &b, uint8_t oversampleFactor, bool rightPressed, bool middlePressed, bool leftPressed) { + for (uint8_t i = 0; i < oversampleFactor; ++i) { + b.Step(); // should detect the press but remain in detected state - wait for debounce + mt::IncMillis(); + } + CHECK(b.ButtonPressed(mb::Right) == rightPressed); + CHECK(b.ButtonPressed(mb::Middle) == middlePressed); + CHECK(b.ButtonPressed(mb::Left) == leftPressed); +} + /// This test tries to simulate a bouncing effect on data from ADC on the first button TEST_CASE("buttons::Step-debounce-one-button", "[buttons]") { // make a bounce event on the first press hal::adc::TADCData d({ 5, config::buttonADCMaxValue, 5, 9, 6, 7, 8, config::buttonADCMaxValue, config::buttonADCMaxValue }); // need to oversample the data as debouncing takes 100 cycles to accept a pressed button - constexpr uint8_t oversampleFactor = 25; + constexpr uint8_t oversampleFactor = config::buttonsDebounceMs / 4; hal::adc::ReinitADC(config::buttonsADCIndex, std::move(d), oversampleFactor); mt::ReinitTimebase(); mb::Buttons b; - // 5 - for (uint8_t i = 0; i < oversampleFactor; ++i) { - b.Step(); // should detect the press but remain in detected state - wait for debounce - mt::IncMillis(); - } - CHECK(!b.ButtonPressed(mb::Right)); - CHECK(!b.ButtonPressed(mb::Middle)); - CHECK(!b.ButtonPressed(mb::Left)); + // 5: should detect the press but remain in detected state - wait for debounce + StepAndCheck(b, oversampleFactor, false, false, false); - // 1023 - for (uint8_t i = 0; i < oversampleFactor; ++i) { - b.Step(); // reset to waiting - mt::IncMillis(); - } - CHECK(!b.ButtonPressed(mb::Right)); - CHECK(!b.ButtonPressed(mb::Middle)); - CHECK(!b.ButtonPressed(mb::Left)); + // 1023: reset to waiting + StepAndCheck(b, oversampleFactor, false, false, false); - // 5 - for (uint8_t i = 0; i < oversampleFactor; ++i) { - b.Step(); // pressed again, still in debouncing state - mt::IncMillis(); - } - CHECK(!b.ButtonPressed(mb::Right)); - CHECK(!b.ButtonPressed(mb::Middle)); - CHECK(!b.ButtonPressed(mb::Left)); + // 5: pressed again, still in debouncing state + StepAndCheck(b, oversampleFactor, false, false, false); - // 9 - for (uint8_t i = 0; i < oversampleFactor; ++i) { - b.Step(); // no change - mt::IncMillis(); - } - CHECK(!b.ButtonPressed(mb::Left)); - CHECK(!b.ButtonPressed(mb::Middle)); - CHECK(!b.ButtonPressed(mb::Right)); + // 9: no change + StepAndCheck(b, oversampleFactor, false, false, false); - // 6 - for (uint8_t i = 0; i < oversampleFactor; ++i) { - b.Step(); // no change - mt::IncMillis(); - } - CHECK(!b.ButtonPressed(mb::Right)); - CHECK(!b.ButtonPressed(mb::Middle)); - CHECK(!b.ButtonPressed(mb::Left)); + // 6: no change + StepAndCheck(b, oversampleFactor, false, false, false); - // 7 - for (uint8_t i = 0; i < oversampleFactor; ++i) { - b.Step(); // one step from "pressed" - mt::IncMillis(); - } - CHECK(!b.ButtonPressed(mb::Right)); - CHECK(!b.ButtonPressed(mb::Middle)); - CHECK(!b.ButtonPressed(mb::Left)); + // 7: one step from "pressed" + StepAndCheck(b, oversampleFactor, false, false, false); - // 8 - for (uint8_t i = 0; i < oversampleFactor; ++i) { - b.Step(); // fifth set of samples - should report "pressed" finally - mt::IncMillis(); - } - CHECK(b.ButtonPressed(mb::Right)); - CHECK(!b.ButtonPressed(mb::Middle)); - CHECK(!b.ButtonPressed(mb::Left)); + // 8: fifth set of samples - should report "pressed" finally + StepAndCheck(b, oversampleFactor, true, false, false); - // 1023 - for (uint8_t i = 0; i < oversampleFactor; ++i) { - b.Step(); // sixth set of samples - button released (no debouncing on release) - mt::IncMillis(); - } - CHECK(!b.ButtonPressed(mb::Right)); - CHECK(!b.ButtonPressed(mb::Middle)); - CHECK(!b.ButtonPressed(mb::Left)); + // 1023: sixth set of samples - button released (no debouncing on release) + StepAndCheck(b, oversampleFactor, false, false, false); - // 1023 - for (uint8_t i = 0; i < oversampleFactor; ++i) { - b.Step(); // seventh set of samples - still released - mt::IncMillis(); - } - CHECK(!b.ButtonPressed(mb::Right)); - CHECK(!b.ButtonPressed(mb::Middle)); - CHECK(!b.ButtonPressed(mb::Left)); + // 1023: seventh set of samples - still released + StepAndCheck(b, oversampleFactor, false, false, false); +} + +TEST_CASE("buttons::verify_ADC_stub", "[buttons]") { + hal::adc::TADCData d({ 5, config::buttonADCMaxValue, 5, 9, 6, 7, 8, config::buttonADCMaxValue, config::buttonADCMaxValue }); + + // need to oversample the data as debouncing takes 100 cycles to accept a pressed button + constexpr uint8_t oversampleFactor = config::buttonsDebounceMs / 4; + hal::adc::ReinitADC(config::buttonsADCIndex, std::move(d), oversampleFactor); + mt::ReinitTimebase(); + + for (uint8_t i = 0; i < oversampleFactor; ++i) { + uint16_t v = hal::adc::ReadADC(config::buttonsADCIndex); + REQUIRE(v == 5); + mt::IncMillis(); + } + + for (uint8_t i = 0; i < oversampleFactor; ++i) { + uint16_t v = hal::adc::ReadADC(config::buttonsADCIndex); + REQUIRE(v == config::buttonADCMaxValue); + mt::IncMillis(); + } + + for (uint8_t i = 0; i < oversampleFactor; ++i) { + uint16_t v = hal::adc::ReadADC(config::buttonsADCIndex); + REQUIRE(v == 5); + mt::IncMillis(); + } } diff --git a/tests/unit/modules/stubs/stub_adc.cpp b/tests/unit/modules/stubs/stub_adc.cpp index 6e1929e..310cb07 100644 --- a/tests/unit/modules/stubs/stub_adc.cpp +++ b/tests/unit/modules/stubs/stub_adc.cpp @@ -12,11 +12,15 @@ static uint8_t oversample = 1; ///< current count of oversampled values returned void ReinitADC(uint8_t channel, TADCData &&d, uint8_t ovsmpl) { values2Return[channel] = std::move(d); - oversampleFactor = ovsmpl; + oversampleFactor = ovsmpl - 1; oversample = ovsmpl; rdptr[channel] = values2Return[channel].cbegin(); } +uint16_t CurrentADC(uint8_t adc) { + return rdptr[adc] != values2Return[adc].end() ? *rdptr[adc] : values2Return[adc].back(); +} + /// ADC access routines uint16_t ReadADC(uint8_t adc) { if (!oversample) { @@ -26,7 +30,7 @@ uint16_t ReadADC(uint8_t adc) { } else { --oversample; } - return rdptr[adc] != values2Return[adc].end() ? *rdptr[adc] : values2Return[adc].back(); + return CurrentADC(adc); } void SetADC(uint8_t channel, uint16_t value) { diff --git a/tests/unit/modules/stubs/stub_adc.h b/tests/unit/modules/stubs/stub_adc.h index 16f6ee0..20ab20b 100644 --- a/tests/unit/modules/stubs/stub_adc.h +++ b/tests/unit/modules/stubs/stub_adc.h @@ -14,5 +14,8 @@ void ReinitADC(uint8_t channel, TADCData &&d, uint8_t ovsmpl); /// set ADC value on a channel to some fixed value from now on void SetADC(uint8_t channel, uint16_t value); +/// @returns current ADC value without advancing to the next one +uint16_t CurrentADC(uint8_t adc); + } // namespace adc } // namespace hal