Add forced reinit of all automata for the unit tests

+ added a few constexpr to constructors on the way
pull/26/head
D.R.racer 2021-06-17 08:33:33 +02:00 committed by DRracer
parent b8f6bc9a4e
commit 3cb3cebed9
8 changed files with 48 additions and 31 deletions

View File

@ -7,7 +7,7 @@ namespace finda {
class FINDA : protected debounce::Debouncer {
public:
inline FINDA()
inline constexpr FINDA()
: debounce::Debouncer(debounce) {};
void Step(uint16_t time);
using debounce::Debouncer::Pressed;

View File

@ -11,8 +11,9 @@ namespace fsensor {
class FSensor : protected debounce::Debouncer {
public:
inline FSensor()
: debounce::Debouncer(debounce) {};
inline constexpr FSensor()
: debounce::Debouncer(debounce)
, reportedFSensorState(false) {};
void Step(uint16_t time);
using debounce::Debouncer::Pressed;

View File

@ -11,12 +11,12 @@ namespace idler {
class Idler {
public:
enum {
Ready = 0,
Ready = 0, // intentionally set as zero in order to allow zeroing the Idler structure upon startup -> avoid explicit initialization code
Moving,
Failed
};
inline Idler()
inline constexpr Idler()
: state(Ready)
, plannedEngage(false)
, plannedSlot(0)

View File

@ -61,6 +61,8 @@ public:
/// @@TODO this is subject of discussion and change in the future
class Motion {
public:
inline constexpr Motion() = default;
/// Init axis driver - @@TODO this should be probably hidden somewhere deeper ... something should manage the axes and their state
/// especially when the TMC may get randomly reset (deinited)
void InitAxis(Axis axis);

View File

@ -16,7 +16,7 @@ public:
Failed
};
inline Selector()
inline constexpr Selector()
: state(Ready)
, plannedSlot(0)
, currentSlot(0) {}

View File

@ -31,17 +31,7 @@ bool WhileCondition(logic::FeedToFinda &ff, COND cond, uint32_t maxLoops = 5000)
TEST_CASE("feed_to_finda::feed_phase_unlimited", "[feed_to_finda]") {
using namespace logic;
// no buttons involved ;)
hal::adc::TADCData noButtons({ 0 });
hal::adc::ReinitADC(0, std::move(noButtons), 1);
// finda OFF
hal::adc::TADCData findaOFF({ 0 });
hal::adc::ReinitADC(1, std::move(findaOFF), 1);
// let's assume we have the filament NOT loaded and active slot 0
modules::globals::globals.SetFilamentLoaded(false);
modules::globals::globals.SetActiveSlot(0);
ForceReinitAllAutomata();
FeedToFinda ff;
main_loop();
@ -103,20 +93,7 @@ TEST_CASE("feed_to_finda::feed_phase_unlimited", "[feed_to_finda]") {
TEST_CASE("feed_to_finda::FINDA_failed", "[feed_to_finda]") {
using namespace logic;
// This is a problem - how to reset all the state machines at once?
// May be add an #ifdef unit_tests and a reset function for each of the automatons
// no buttons involved ;)
hal::adc::TADCData noButtons({ 0 });
hal::adc::ReinitADC(0, std::move(noButtons), 1);
// finda OFF
hal::adc::TADCData findaOFF({ 0 });
hal::adc::ReinitADC(1, std::move(findaOFF), 1);
// let's assume we have the filament NOT loaded and active slot 0
modules::globals::globals.SetFilamentLoaded(false);
modules::globals::globals.SetActiveSlot(0);
ForceReinitAllAutomata();
FeedToFinda ff;
main_loop();

View File

@ -1,4 +1,7 @@
#include "main_loop_stub.h"
#include "../../modules/stubs/stub_adc.h"
#include "../../../../src/modules/buttons.h"
#include "../../../../src/modules/finda.h"
#include "../../../../src/modules/fsensor.h"
@ -9,6 +12,8 @@
#include "../../../../src/modules/permanent_storage.h"
#include "../../../../src/modules/selector.h"
#include <new> // bring in placement new
logic::CommandBase *currentCommand = nullptr;
// just like in the real FW, step all the known automata
@ -26,3 +31,34 @@ void main_loop() {
currentCommand->Step();
++tmpTiming;
}
void ForceReinitAllAutomata() {
// This woodoo magic with placement new is just a forced reinit of global instances of firmware's state machines
// just for the purposes of separate unit tests. Each unit test needs a "freshly booted firmware" and since all unit tests
// in the test binary share the same global data structures, we need some way of making them fresh each time.
//
// This approach mimics the firmware behavior closely as the firmware initializes its global data structures
// on its very start once (by copying static init data from PROGMEM into RAM) - and we need exactly this approach in the unit tests.
//
// There are multiple other approaches, one of them is adding a special Init() function into each of these state machines.
// As this approach might look like a standard and safer way of doing stuff, it has several drawbacks, especially
// it needs an explicit call to the Init function every time an object like this is created - this can have negative influence on firmware's code size
new (&modules::buttons::buttons) modules::buttons::Buttons();
new (&modules::leds::leds) modules::leds::LEDs();
new (&modules::finda::finda) modules::finda::FINDA();
new (&modules::fsensor::fsensor) modules::fsensor::FSensor();
new (&modules::idler::idler) modules::idler::Idler();
new (&modules::selector::selector) modules::selector::Selector();
new (&modules::motion::motion) modules::motion::Motion();
// no buttons involved ;)
hal::adc::ReinitADC(0, hal::adc::TADCData({ 0 }), 1);
// finda OFF
hal::adc::ReinitADC(1, hal::adc::TADCData({ 0 }), 1);
// let's assume we have the filament NOT loaded and active slot 0
modules::globals::globals.SetFilamentLoaded(false);
modules::globals::globals.SetActiveSlot(0);
}

View File

@ -2,5 +2,6 @@
#include "../../../../src/logic/command_base.h"
extern void main_loop();
extern void ForceReinitAllAutomata();
extern logic::CommandBase *currentCommand;