From e20915061f84a8ce32d21cd139859b6d6b763d8c Mon Sep 17 00:00:00 2001 From: t0mpr1c3 Date: Mon, 2 Oct 2023 19:43:29 -0400 Subject: [PATCH] control --- src/ayab/com.cpp | 4 ++-- src/ayab/controller.cpp | 14 ++++++++++++++ src/ayab/controller.h | 6 ++++++ src/ayab/global_controller.cpp | 8 ++++++++ src/ayab/main.cpp | 26 +++++++++++++------------- test/mocks/controller_mock.cpp | 10 ++++++++++ test/mocks/controller_mock.h | 2 ++ test/test_OpError.cpp | 4 ++-- test/test_OpInit.cpp | 4 ++-- test/test_com.cpp | 8 +++++--- test/test_controller.cpp | 17 +++++++++++++++++ 11 files changed, 81 insertions(+), 22 deletions(-) diff --git a/src/ayab/com.cpp b/src/ayab/com.cpp index 24d7c8e8b..35098358d 100644 --- a/src/ayab/com.cpp +++ b/src/ayab/com.cpp @@ -140,7 +140,7 @@ void Com::send_indState(Err_t error) const { uint8_t payload[INDSTATE_LEN] = { static_cast(API_t::indState), static_cast(error), - static_cast(GlobalController::getState()->state()), + static_cast(GlobalController::state()), highByte(leftHallValue), lowByte(leftHallValue), highByte(rightHallValue), @@ -159,7 +159,7 @@ void Com::send_indState(Err_t error) const { * \param size The number of bytes in the data buffer. */ void Com::onPacketReceived(const uint8_t *buffer, size_t size) { - GlobalController::getState()->com(buffer, size); + GlobalController::com(buffer, size); } // Serial command handling diff --git a/src/ayab/controller.cpp b/src/ayab/controller.cpp index 3a3f75407..8a8e0deec 100644 --- a/src/ayab/controller.cpp +++ b/src/ayab/controller.cpp @@ -32,6 +32,13 @@ // Public methods +/*! + * \brief Return current machine state + */ +OpState_t Controller::state() { + return m_currentState->state(); +} + /*! * \brief Initialize Finite State Machine. */ @@ -57,6 +64,13 @@ void Controller::init() { m_nextState = &GlobalOpIdle::m_instance; } +/*! + * \brief Call communication method of current machine state + */ +void Controller::com(const uint8_t *buffer, size_t size) { + m_currentState->com(buffer, size); +} + /*! * \brief Dispatch on machine state; update machine state */ diff --git a/src/ayab/controller.h b/src/ayab/controller.h index b4f75c7e3..4515529ff 100644 --- a/src/ayab/controller.h +++ b/src/ayab/controller.h @@ -34,7 +34,9 @@ class ControllerInterface { virtual ~ControllerInterface() = default; // any methods that need to be mocked should go here + virtual OpState_t state() = 0; virtual void init() = 0; + virtual void com(const uint8_t *buffer, size_t size) = 0; virtual void update() = 0; virtual void cacheEncoders() = 0; virtual void setState(OpInterface *state) = 0; @@ -63,7 +65,9 @@ class GlobalController final { // reference to global instance whose methods are implemented static ControllerInterface& m_instance; + static OpState_t state(); static void init(); + static void com(const uint8_t *buffer, size_t size); static void update(); static void cacheEncoders(); static void setState(OpInterface *state); @@ -79,7 +83,9 @@ class GlobalController final { class Controller : public ControllerInterface { public: + OpState_t state() final; void init() final; + void com(const uint8_t *buffer, size_t size) final; void update() final; void cacheEncoders() final; void setState(OpInterface *state) final; diff --git a/src/ayab/global_controller.cpp b/src/ayab/global_controller.cpp index a8c383609..21b1d976b 100644 --- a/src/ayab/global_controller.cpp +++ b/src/ayab/global_controller.cpp @@ -24,10 +24,18 @@ // static member functions +OpState_t GlobalController::state() { + return m_instance.state(); +} + void GlobalController::init() { m_instance.init(); } +void GlobalController::com(const uint8_t *buffer, size_t size) { + m_instance.com(buffer, size); +} + void GlobalController::update() { m_instance.update(); } diff --git a/src/ayab/main.cpp b/src/ayab/main.cpp index 24bbc4672..cf985694c 100644 --- a/src/ayab/main.cpp +++ b/src/ayab/main.cpp @@ -43,21 +43,21 @@ // Global definitions: references elsewhere must use `extern`. // Each of the following is a pointer to a singleton class // containing static methods. -constexpr GlobalAnalogReadAsyncWrapper *analogReadasyncWrapper; -constexpr GlobalPacketSerialWrapper *packetSerialWrapper; +const GlobalAnalogReadAsyncWrapper *analogReadasyncWrapper; +const GlobalPacketSerialWrapper *packetSerialWrapper; -constexpr GlobalBeeper *beeper; -constexpr GlobalCom *com; -constexpr GlobalController *controller; -constexpr GlobalEncoders *encoders; -constexpr GlobalSolenoids *solenoids; +const GlobalBeeper *beeper; +const GlobalCom *com; +const GlobalController *controller; +const GlobalEncoders *encoders; +const GlobalSolenoids *solenoids; -constexpr GlobalOpIdle *opIdle; -constexpr GlobalOpInit *opInit; -constexpr GlobalOpReady *opReady; -constexpr GlobalOpKnit *opKnit; -constexpr GlobalOpTest *opTest; -constexpr GlobalOpError *opError; +const GlobalOpIdle *opIdle; +const GlobalOpInit *opInit; +const GlobalOpReady *opReady; +const GlobalOpKnit *opKnit; +const GlobalOpTest *opTest; +const GlobalOpError *opError; // Initialize static members. // Each singleton class contains a reference to a static instance diff --git a/test/mocks/controller_mock.cpp b/test/mocks/controller_mock.cpp index 886fb018a..fdd3428bb 100644 --- a/test/mocks/controller_mock.cpp +++ b/test/mocks/controller_mock.cpp @@ -40,11 +40,21 @@ void releaseControllerMock() { } } +OpState_t Controller::state() { + assert(gControllerMock != nullptr); + return gControllerMock->state(); +} + void Controller::init() { assert(gControllerMock != nullptr); gControllerMock->init(); } +void Controller::com(const uint8_t *buffer, size_t size) { + assert(gControllerMock != nullptr); + gControllerMock->com(buffer, size); +} + void Controller::update() { assert(gControllerMock != nullptr); gControllerMock->update(); diff --git a/test/mocks/controller_mock.h b/test/mocks/controller_mock.h index 1afd15e47..a4b6df211 100644 --- a/test/mocks/controller_mock.h +++ b/test/mocks/controller_mock.h @@ -31,7 +31,9 @@ class ControllerMock : public ControllerInterface { public: + MOCK_METHOD0(state, OpState_t()); MOCK_METHOD0(init, void()); + MOCK_METHOD2(com, void(const uint8_t *buffer, size_t size)); MOCK_METHOD0(update, void()); MOCK_METHOD0(cacheEncoders, void()); MOCK_METHOD1(setState, void(OpInterface *state)); diff --git a/test/test_OpError.cpp b/test/test_OpError.cpp index a13db4ff3..9c630fc5e 100644 --- a/test/test_OpError.cpp +++ b/test/test_OpError.cpp @@ -105,7 +105,7 @@ TEST_F(OpErrorTest, test_update) { EXPECT_CALL(*arduinoMock, digitalWrite(LED_PIN_A, LOW)); EXPECT_CALL(*arduinoMock, digitalWrite(LED_PIN_B, HIGH)); // send_indState - EXPECT_CALL(*controllerMock, getState).WillOnce(Return(&opError)); + EXPECT_CALL(*controllerMock, state); EXPECT_CALL(*controllerMock, getCarriage); EXPECT_CALL(*controllerMock, getPosition); EXPECT_CALL(*controllerMock, getDirection); @@ -116,7 +116,7 @@ TEST_F(OpErrorTest, test_update) { EXPECT_CALL(*arduinoMock, digitalWrite(LED_PIN_A, HIGH)); EXPECT_CALL(*arduinoMock, digitalWrite(LED_PIN_B, LOW)); // send_indState - EXPECT_CALL(*controllerMock, getState).WillOnce(Return(&opError)); + EXPECT_CALL(*controllerMock, state); EXPECT_CALL(*controllerMock, getCarriage); EXPECT_CALL(*controllerMock, getPosition); EXPECT_CALL(*controllerMock, getDirection); diff --git a/test/test_OpInit.cpp b/test/test_OpInit.cpp index e9cbe9088..e03efe173 100644 --- a/test/test_OpInit.cpp +++ b/test/test_OpInit.cpp @@ -85,7 +85,7 @@ class OpInitTest : public ::testing::Test { void expect_ready(bool ready) { if (ready) { - EXPECT_CALL(*controllerMock, getState).WillOnce(Return(&opInit)); + EXPECT_CALL(*controllerMock, state); } ASSERT_EQ(opInit.isReady(), ready); } @@ -144,7 +144,7 @@ TEST_F(OpInitTest, test_updateF) { TEST_F(OpInitTest, test_updateT) { // isReady() == true expect_update(get_position_past_left(Machine_t::Kh910), Direction_t::Right, Direction_t::Left); - EXPECT_CALL(*controllerMock, getState).WillOnce(Return(&opInit)); + EXPECT_CALL(*controllerMock, state); EXPECT_CALL(*controllerMock, setState(&opReady)); opInit.update(); diff --git a/test/test_com.cpp b/test/test_com.cpp index 02d409bf2..283bd0dc3 100644 --- a/test/test_com.cpp +++ b/test/test_com.cpp @@ -96,9 +96,11 @@ class ComTest : public ::testing::Test { void expected_write_onPacketReceived(uint8_t *buffer, size_t size, bool once) { - expect_send(once); - EXPECT_CALL(*controllerMock, getState).WillOnce(Return(&opTest)); + EXPECT_CALL(*controllerMock, com); com.onPacketReceived(buffer, size); + + expect_send(once); + opTest.com(buffer, size); } void reqInit(Machine_t machine) { @@ -469,7 +471,7 @@ TEST_F(ComTest, test_send_reqLine) { TEST_F(ComTest, test_send_indState) { EXPECT_CALL(*arduinoMock, analogRead(EOL_PIN_L)); EXPECT_CALL(*arduinoMock, analogRead(EOL_PIN_R)); - EXPECT_CALL(*controllerMock, getState).WillOnce(Return(&opInit)); + EXPECT_CALL(*controllerMock, state); EXPECT_CALL(*controllerMock, getCarriage); EXPECT_CALL(*controllerMock, getPosition); EXPECT_CALL(*controllerMock, getDirection); diff --git a/test/test_controller.cpp b/test/test_controller.cpp index 983b7ae34..904cea705 100644 --- a/test/test_controller.cpp +++ b/test/test_controller.cpp @@ -201,6 +201,14 @@ class ControllerTest : public ::testing::Test { } }; +TEST_F(ControllerTest, test_state) { + EXPECT_CALL(*opIdleMock, state); + controller.state(); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(opIdleMock)); +} + TEST_F(ControllerTest, test_init) { EXPECT_CALL(*arduinoMock, pinMode(ENC_PIN_A, INPUT)); EXPECT_CALL(*arduinoMock, pinMode(ENC_PIN_B, INPUT)); @@ -285,6 +293,15 @@ TEST_F(ControllerTest, test_update_test) { ASSERT_TRUE(Mock::VerifyAndClear(opTestMock)); } +TEST_F(ControllerTest, test_com) { + const uint8_t buffer[] = {0xFF}; + EXPECT_CALL(*opIdleMock, com); + controller.com(buffer, 1); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(opIdleMock)); +} + TEST_F(ControllerTest, test_error_state) { controller.setState(&opError); expected_update_idle();