From 69d0ad6dd3485cab35938550a56d476bb4ffd2f5 Mon Sep 17 00:00:00 2001 From: t0mpr1c3 Date: Sun, 1 Oct 2023 16:32:41 -0400 Subject: [PATCH] mock PacketSerial --- src/ayab/analogReadAsyncWrapper.cpp | 2 - src/ayab/com.cpp | 14 +-- src/ayab/com.h | 4 - src/ayab/global_analogReadAsyncWrapper.cpp | 2 - src/ayab/global_packetSerialWrapper.cpp | 42 +++++++ src/ayab/main.cpp | 6 + src/ayab/packetSerialWrapper.cpp | 67 ++++++++++++ src/ayab/packetSerialWrapper.h | 76 +++++++++++++ test/CMakeLists.txt | 8 +- test/mocks/packetSerialWrapper_mock.cpp | 59 ++++++++++ test/mocks/packetSerialWrapper_mock.h | 42 +++++++ test/test.sh | 4 +- test/test_OpTest.cpp | 121 +++++++++++++-------- test/test_all.cpp | 6 + test/test_boards.cpp | 3 + test/test_com.cpp | 112 ++++++++++++++----- 16 files changed, 481 insertions(+), 87 deletions(-) create mode 100644 src/ayab/global_packetSerialWrapper.cpp create mode 100644 src/ayab/packetSerialWrapper.cpp create mode 100644 src/ayab/packetSerialWrapper.h create mode 100644 test/mocks/packetSerialWrapper_mock.cpp create mode 100644 test/mocks/packetSerialWrapper_mock.h diff --git a/src/ayab/analogReadAsyncWrapper.cpp b/src/ayab/analogReadAsyncWrapper.cpp index e4b552d4c..be4b00843 100644 --- a/src/ayab/analogReadAsyncWrapper.cpp +++ b/src/ayab/analogReadAsyncWrapper.cpp @@ -1,7 +1,5 @@ /*! * \file analogReadAsyncWrapper.cpp - * \brief Class containing methods to actuate a analogReadAsyncWrapper connected - * to PIEZO_PIN. * * This file is part of AYAB. * diff --git a/src/ayab/com.cpp b/src/ayab/com.cpp index fd1e9468e..a54eff8c8 100644 --- a/src/ayab/com.cpp +++ b/src/ayab/com.cpp @@ -22,6 +22,8 @@ * http://ayab-knitting.com */ +#include "packetSerialWrapper.h" + #include "beeper.h" #include "com.h" #include "controller.h" @@ -34,17 +36,15 @@ * \brief Initialize serial communication. */ void Com::init() { - m_packetSerial.begin(SERIAL_BAUDRATE); -#ifndef AYAB_TESTS - m_packetSerial.setPacketHandler(GlobalCom::onPacketReceived); -#endif // AYAB_TESTS + GlobalPacketSerialWrapper::begin(SERIAL_BAUDRATE); + GlobalPacketSerialWrapper::setPacketHandler(GlobalCom::onPacketReceived); } /*! * \brief Service the serial connection. */ void Com::update() { - m_packetSerial.update(); + GlobalPacketSerialWrapper::update(); } /*! @@ -96,7 +96,7 @@ void Com::send(uint8_t *payload, size_t length) const { Serial.print(", Encoded as: "); #endif */ - m_packetSerial.send(payload, length); + GlobalPacketSerialWrapper::send(payload, length); } /*! @@ -110,7 +110,7 @@ void Com::sendMsg(API_t id, const char *msg) { while (*msg) { msgBuffer[length++] = static_cast(*msg++); } - m_packetSerial.send(msgBuffer, length); + GlobalPacketSerialWrapper::send(msgBuffer, length); } void Com::sendMsg(API_t id, char *msg) { sendMsg(id, static_cast(msg)); diff --git a/src/ayab/com.h b/src/ayab/com.h index 304c56abb..0474dd070 100644 --- a/src/ayab/com.h +++ b/src/ayab/com.h @@ -132,9 +132,6 @@ class GlobalCom final { static void h_reqTest(); static void h_quitCmd(); static void h_unrecognized(); - -private: - static SLIPPacketSerial m_packetSerial; }; class Com : public ComInterface { @@ -158,7 +155,6 @@ class Com : public ComInterface { void h_unrecognized() const final; private: - SLIPPacketSerial m_packetSerial; uint8_t lineBuffer[MAX_LINE_BUFFER_LEN] = {0}; uint8_t msgBuffer[MAX_MSG_BUFFER_LEN] = {0}; diff --git a/src/ayab/global_analogReadAsyncWrapper.cpp b/src/ayab/global_analogReadAsyncWrapper.cpp index 3431b714c..a17d041ea 100644 --- a/src/ayab/global_analogReadAsyncWrapper.cpp +++ b/src/ayab/global_analogReadAsyncWrapper.cpp @@ -1,7 +1,5 @@ /*! * \file global_analogReadAsyncWrapper.cpp - * \brief Singleton class containing methods to actuate a analogReadAsyncWrapper - * connected to PIEZO_PIN. * * This file is part of AYAB. * diff --git a/src/ayab/global_packetSerialWrapper.cpp b/src/ayab/global_packetSerialWrapper.cpp new file mode 100644 index 000000000..84719a606 --- /dev/null +++ b/src/ayab/global_packetSerialWrapper.cpp @@ -0,0 +1,42 @@ +/*! + * \file global_packetSerialWrapper.cpp + * + * This file is part of AYAB. + * + * AYAB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AYAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AYAB. If not, see . + * + * Original Work Copyright 2013 Christian Obersteiner, Andreas Müller + * Modified Work Copyright 2020-3 Sturla Lange, Tom Price + * http://ayab-knitting.com + */ + +#include "packetSerialWrapper.h" + +// static member functions + +void GlobalPacketSerialWrapper::begin(uint32_t speed) { + m_instance->begin(speed); +} + +void GlobalPacketSerialWrapper::send(const uint8_t *buffer, size_t size) { + m_instance->send(buffer, size); +} + +void GlobalPacketSerialWrapper::setPacketHandler(SLIPPacketSerial::PacketHandlerFunction onPacketFunction) { + m_instance->setPacketHandler(onPacketFunction); +} + +void GlobalPacketSerialWrapper::update() { + m_instance->update(); +} diff --git a/src/ayab/main.cpp b/src/ayab/main.cpp index 182996f34..c95bee80b 100644 --- a/src/ayab/main.cpp +++ b/src/ayab/main.cpp @@ -25,6 +25,8 @@ #include #include "analogReadAsyncWrapper.h" +#include "packetSerialWrapper.h" + #include "beeper.h" #include "com.h" #include "controller.h" @@ -42,6 +44,8 @@ // Each of the following is a pointer to a singleton class // containing static methods. constexpr GlobalAnalogReadAsyncWrapper *analogReadAsyncWrapper; +constexpr GlobalPacketSerialWrapper *packetSerialWrapper; + constexpr GlobalBeeper *beeper; constexpr GlobalCom *com; constexpr GlobalController *controller; @@ -60,6 +64,8 @@ constexpr GlobalOpError *opError; // that implements a public interface. When testing, a pointer // to an instance of a mock class can be substituted. AnalogReadAsyncWrapperInterface *GlobalAnalogReadAsyncWrapper::m_instance = new AnalogReadAsyncWrapper(); +PacketSerialWrapperInterface *GlobalPacketSerialWrapper::m_instance = new PacketSerialWrapper(); + BeeperInterface *GlobalBeeper::m_instance = new Beeper(); ComInterface *GlobalCom::m_instance = new Com(); EncodersInterface *GlobalEncoders::m_instance = new Encoders(); diff --git a/src/ayab/packetSerialWrapper.cpp b/src/ayab/packetSerialWrapper.cpp new file mode 100644 index 000000000..d918b4561 --- /dev/null +++ b/src/ayab/packetSerialWrapper.cpp @@ -0,0 +1,67 @@ +/*! + * \file packetSerialWrapper.cpp + * + * This file is part of AYAB. + * + * AYAB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AYAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AYAB. If not, see . + * + * Original Work Copyright 2013 Christian Obersteiner, Andreas Müller + * Modified Work Copyright 2020-3 Sturla Lange, Tom Price + * http://ayab-knitting.com + */ + +#include "packetSerialWrapper.h" + +/*! + * \brief Wrapper for PacketSerial::begin + */ +void PacketSerialWrapper::begin(uint32_t speed) { +#ifndef AYAB_TESTS + m_packetSerial.begin(speed); +#else + (void) speed; +#endif +} + +/*! + * \brief Wrapper for PacketSerial::send + */ +void PacketSerialWrapper::send(const uint8_t *buffer, size_t size) const { +#ifndef AYAB_TESTS + m_packetSerial.send(buffer, size); +#else + (void) buffer; + (void) size; +#endif +} + +/*! + * \brief Wrapper for PacketSerial::setPacketHandler + */ +void PacketSerialWrapper::setPacketHandler(SLIPPacketSerial::PacketHandlerFunction onPacketFunction) { +#ifndef AYAB_TESTS + m_packetSerial.setPacketHandler(onPacketFunction); +#else + (void) onPacketFunction; +#endif +} + +/*! + * \brief Wrapper for PacketSerial::update + */ +void PacketSerialWrapper::update() { +#ifndef AYAB_TESTS + m_packetSerial.update(); +#endif +} diff --git a/src/ayab/packetSerialWrapper.h b/src/ayab/packetSerialWrapper.h new file mode 100644 index 000000000..8896de7af --- /dev/null +++ b/src/ayab/packetSerialWrapper.h @@ -0,0 +1,76 @@ +/*! + * \file packetSerialWrapper.h + * + * This file is part of AYAB. + * + * AYAB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AYAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AYAB. If not, see . + * + * Original Work Copyright 2013 Christian Obersteiner, Andreas Müller + * Modified Work Copyright 2020-3 Sturla Lange, Tom Price + * http://ayab-knitting.com + */ + +#ifndef PACKETSERIALWRAPPER_H_ +#define PACKETSERIALWRAPPER_H_ + +#include +#include + +class PacketSerialWrapperInterface { +public: + virtual ~PacketSerialWrapperInterface() = default; + + // any methods that need to be mocked should go here + virtual void begin(uint32_t speed) = 0; + virtual void send(const uint8_t *buffer, size_t size) const = 0; + virtual void setPacketHandler(SLIPPacketSerial::PacketHandlerFunction onPacketFunction) = 0; + virtual void update() = 0; +}; + +// Container class for the static method packetSerial. +// Dependency injection is enabled using a pointer to a global instance of +// either `PacketSerialWrapper` or `PacketSerialWrapperMock`, +// both of which classes implement the +// pure virtual methods of `PacketSerialWrapperInterface`. + +class GlobalPacketSerialWrapper final { +private: + // singleton class so private constructor is appropriate + GlobalPacketSerialWrapper() = default; + +public: + // pointer to global instance whose methods are implemented + static PacketSerialWrapperInterface *m_instance; + + static void begin(uint32_t speed); + static void send(const uint8_t *buffer, size_t size); + static void setPacketHandler(SLIPPacketSerial::PacketHandlerFunction onPacketFunction); + static void update(); +}; + +/*! + * \brief Wrapper for packetSerial method + */ +class PacketSerialWrapper : public PacketSerialWrapperInterface { +public: + void begin(uint32_t speed) final; + void send(const uint8_t *buffer, size_t size) const final; + void setPacketHandler(SLIPPacketSerial::PacketHandlerFunction onPacketFunction) final; + void update() final; + +private: + SLIPPacketSerial m_packetSerial; +}; + +#endif // PACKETSERIALWRAPPER_H_ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6f430c551..b89f1a90d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -81,6 +81,9 @@ set(COMMON_SOURCES ${SOURCE_DIRECTORY}/global_analogReadAsyncWrapper.cpp ${PROJECT_SOURCE_DIR}/mocks/analogReadAsyncWrapper_mock.cpp + + ${SOURCE_DIRECTORY}/global_packetSerialWrapper.cpp + ${PROJECT_SOURCE_DIR}/mocks/packetSerialWrapper_mock.cpp ) set(COMMON_DEFINES ARDUINO=1819 @@ -181,8 +184,11 @@ add_executable(${PROJECT_NAME}_knit ${SOURCE_DIRECTORY}/analogReadAsyncWrapper.cpp ${SOURCE_DIRECTORY}/global_analogReadAsyncWrapper.cpp - #${LIBRARY_DIRECTORY}/AnalogReadAsync/src/analogReadAsync.cpp #${PROJECT_SOURCE_DIR}/test_analogReadAsyncWrapper.cpp + + ${SOURCE_DIRECTORY}/packetSerialWrapper.cpp + ${SOURCE_DIRECTORY}/global_packetSerialWrapper.cpp + #${PROJECT_SOURCE_DIR}/test_packetSerialWrapper.cpp ) target_include_directories(${PROJECT_NAME}_knit PRIVATE diff --git a/test/mocks/packetSerialWrapper_mock.cpp b/test/mocks/packetSerialWrapper_mock.cpp new file mode 100644 index 000000000..58226a8c2 --- /dev/null +++ b/test/mocks/packetSerialWrapper_mock.cpp @@ -0,0 +1,59 @@ +/*!` + * \file packetSerialWrapper_mock.cpp + * + * This file is part of AYAB. + * + * AYAB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AYAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AYAB. If not, see . + * + * Original Work Copyright 2013 Christian Obersteiner, Andreas Müller + * Modified Work Copyright 2020-3 Sturla Lange, Tom Price + * http://ayab-knitting.com + */ + +#include + +static PacketSerialWrapperMock *gPacketSerialWrapperMock = nullptr; +PacketSerialWrapperMock *packetSerialWrapperMockInstance() { + if (!gPacketSerialWrapperMock) { + gPacketSerialWrapperMock = new PacketSerialWrapperMock(); + } + return gPacketSerialWrapperMock; +} + +void releasePacketSerialWrapperMock() { + if (gPacketSerialWrapperMock) { + delete gPacketSerialWrapperMock; + gPacketSerialWrapperMock = nullptr; + } +} + +void PacketSerialWrapper::begin(uint32_t speed) { + assert(gPacketSerialWrapperMock != nullptr); + gPacketSerialWrapperMock->begin(speed); +} + +void PacketSerialWrapper::send(const uint8_t *buffer, size_t size) const { + assert(gPacketSerialWrapperMock != nullptr); + gPacketSerialWrapperMock->send(buffer, size); +} + +void PacketSerialWrapper::setPacketHandler(SLIPPacketSerial::PacketHandlerFunction onPacketFunction) { + assert(gPacketSerialWrapperMock != nullptr); + gPacketSerialWrapperMock->setPacketHandler(onPacketFunction); +} + +void PacketSerialWrapper::update() { + assert(gPacketSerialWrapperMock != nullptr); + gPacketSerialWrapperMock->update(); +} diff --git a/test/mocks/packetSerialWrapper_mock.h b/test/mocks/packetSerialWrapper_mock.h new file mode 100644 index 000000000..5d7b36ce6 --- /dev/null +++ b/test/mocks/packetSerialWrapper_mock.h @@ -0,0 +1,42 @@ +/*!` + * \file packetSerialWrapper_mock.h + * + * This file is part of AYAB. + * + * AYAB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AYAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AYAB. If not, see . + * + * Original Work Copyright 2013 Christian Obersteiner, Andreas Müller + * Modified Work Copyright 2020-3 Sturla Lange, Tom Price + * http://ayab-knitting.com + */ + +#ifndef PACKETSERIALWRAPPER_MOCK_H_ +#define PACKETSERIALWRAPPER_MOCK_H_ + +#include + +#include + +class PacketSerialWrapperMock : public PacketSerialWrapperInterface { +public: + MOCK_METHOD1(begin, void(uint32_t speed)); + MOCK_CONST_METHOD2(send, void(const uint8_t *buffer, size_t size)); + MOCK_METHOD1(setPacketHandler, void(SLIPPacketSerial::PacketHandlerFunction onPacketFunction)); + MOCK_METHOD0(update, void()); +}; + +PacketSerialWrapperMock *packetSerialWrapperMockInstance(); +void releasePacketSerialWrapperMock(); + +#endif // PACKETSERIALWRAPPER_MOCK_H_ diff --git a/test/test.sh b/test/test.sh index 09a7f869b..b55595e3d 100755 --- a/test/test.sh +++ b/test/test.sh @@ -51,6 +51,7 @@ GCOVR_ARGS="--exclude-unreachable-branches \ --exclude-directories 'test/build/arduino_mock$' \ -e test_* -e lib* \ -e src/ayab/analogReadAsyncWrapper.cpp \ + -e src/ayab/packetSerialWrapper.cpp \ -e src/ayab/global_OpIdle.cpp \ -e src/ayab/global_OpInit.cpp \ -e src/ayab/global_OpTest.cpp \ @@ -62,7 +63,8 @@ GCOVR_ARGS="--exclude-unreachable-branches \ -e src/ayab/global_controller.cpp \ -e src/ayab/global_encoders.cpp \ -e src/ayab/global_solenoids.cpp \ - -e src/ayab/global_analogReadAsyncWrapper.cpp" + -e src/ayab/global_analogReadAsyncWrapper.cpp \ + -e src/ayab/global_packetSerialWrapper.cpp" if [[ $sonar -eq 1 ]]; then gcovr -r . $GCOVR_ARGS --sonarqube ./test/build/coverage.xml diff --git a/test/test_OpTest.cpp b/test/test_OpTest.cpp index 828c8a126..7567b2a84 100644 --- a/test/test_OpTest.cpp +++ b/test/test_OpTest.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -44,57 +45,53 @@ extern OpInit *opInit; extern OpReady *opReady; extern OpTest *opTest; -extern OpKnitMock *opKnit; extern ControllerMock *controller; +extern OpKnitMock *opKnit; +extern PacketSerialWrapperMock *packetSerialWrapper; class OpTestTest : public ::testing::Test { protected: void SetUp() override { arduinoMock = arduinoMockInstance(); - serialMock = serialMockInstance(); - // serialCommandMock = serialCommandMockInstance(); // pointers to global instances controllerMock = controller; opKnitMock = opKnit; + packetSerialWrapperMock = packetSerialWrapper; // The global instances do not get destroyed at the end of each test. // Ordinarily the mock instance would be local and such behaviour would // cause a memory leak. We must notify the test that this is not the case. Mock::AllowLeak(controllerMock); Mock::AllowLeak(opKnitMock); + Mock::AllowLeak(packetSerialWrapperMock); beeper->init(true); } void TearDown() override { releaseArduinoMock(); - releaseSerialMock(); } ArduinoMock *arduinoMock; - SerialMock *serialMock; ControllerMock *controllerMock; OpKnitMock *opKnitMock; + PacketSerialWrapperMock *packetSerialWrapperMock; - void expect_startTest(uint32_t t) { - expect_write(false); - EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(t)); - opTest->begin(); - } - - void expect_write(bool once) { - return; - //TODO: FIXME: Mock PocketSerial, so this works again. + void expect_send(bool once) { if (once) { - EXPECT_CALL(*serialMock, write(_, _)); - EXPECT_CALL(*serialMock, write(SLIP::END)); + EXPECT_CALL(*packetSerialWrapperMock, send).Times(1); } else { - EXPECT_CALL(*serialMock, write(_, _)).Times(AtLeast(1)); - EXPECT_CALL(*serialMock, write(SLIP::END)).Times(AtLeast(1)); + EXPECT_CALL(*packetSerialWrapperMock, send).Times(AtLeast(2)); } } + void expect_startTest(uint32_t t) { + expect_send(false); + EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(t)); + opTest->begin(); + } + void expect_readEOLsensors(bool flag) { uint8_t n = flag ? 1 : 0; EXPECT_CALL(*arduinoMock, analogRead(EOL_PIN_L)).Times(n); @@ -134,89 +131,131 @@ TEST_F(OpTestTest, test_enabled) { } TEST_F(OpTestTest, test_helpCmd) { - expect_write(false); + expect_send(false); opTest->helpCmd(); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_sendCmd) { - expect_write(false); + expect_send(false); opTest->sendCmd(); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_beepCmd) { - expect_write(true); + expect_send(true); opTest->beepCmd(); EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(0U)); beeper->update(); EXPECT_CALL(*arduinoMock, analogWrite(PIEZO_PIN, BEEP_ON_DUTY)); EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(1U)); beeper->update(); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_setSingleCmd_fail1) { const uint8_t buf[] = {static_cast(API_t::setSingleCmd), 0}; - expect_write(false); + expect_send(false); opTest->setSingleCmd(buf, 2); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_setSingleCmd_fail2) { const uint8_t buf[] = {static_cast(API_t::setSingleCmd), 16, 0}; - expect_write(false); + expect_send(false); opTest->setSingleCmd(buf, 3); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_setSingleCmd_fail3) { const uint8_t buf[] = {static_cast(API_t::setSingleCmd), 15, 2}; - expect_write(false); + expect_send(false); opTest->setSingleCmd(buf, 3); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_setSingleCmd_success) { const uint8_t buf[] = {static_cast(API_t::setSingleCmd), 15, 1}; - expect_write(true); + expect_send(true); opTest->setSingleCmd(buf, 3); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_setAllCmd_fail1) { const uint8_t buf[] = {static_cast(API_t::setAllCmd), 0}; - expect_write(false); + expect_send(false); opTest->setAllCmd(buf, 2); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_setAllCmd_success) { const uint8_t buf[] = {static_cast(API_t::setAllCmd), 0xFF, 0xFF}; - expect_write(true); + expect_send(true); opTest->setAllCmd(buf, 3); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_readEOLsensorsCmd) { - expect_write(false); + expect_send(false); expect_readEOLsensors(true); opTest->readEOLsensorsCmd(); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_readEncodersCmd_low) { - expect_write(false); + expect_send(false); EXPECT_CALL(*arduinoMock, digitalRead).WillRepeatedly(Return(LOW)); opTest->readEncodersCmd(); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_readEncodersCmd_high) { - expect_write(false); + expect_send(false); EXPECT_CALL(*arduinoMock, digitalRead).WillRepeatedly(Return(HIGH)); opTest->readEncodersCmd(); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_autoReadCmd) { const uint8_t buf[] = {static_cast(API_t::autoReadCmd)}; - expect_write(true); + expect_send(true); opTest->com(buf, 1); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_autoTestCmd) { const uint8_t buf[] = {static_cast(API_t::autoTestCmd)}; - expect_write(true); + expect_send(true); opTest->com(buf, 1); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_quitCmd) { @@ -249,7 +288,6 @@ TEST_F(OpTestTest, test_autoRead) { // nothing has happened yet EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(TEST_LOOP_DELAY - 1)); EXPECT_CALL(*opKnitMock, encodePosition); - expect_write(false); expect_readEOLsensors(false); expect_readEncoders(false); opTest->update(); @@ -257,15 +295,14 @@ TEST_F(OpTestTest, test_autoRead) { // m_timerEventOdd = false EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(TEST_LOOP_DELAY)); EXPECT_CALL(*opKnitMock, encodePosition); - expect_write(true); expect_readEOLsensors(false); expect_readEncoders(false); opTest->update(); - // m_timerEventOdd = false + // m_timerEventOdd = true EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(2 * TEST_LOOP_DELAY)); EXPECT_CALL(*opKnitMock, encodePosition); - expect_write(false); + expect_send(false); expect_readEOLsensors(true); expect_readEncoders(true); opTest->update(); @@ -274,13 +311,13 @@ TEST_F(OpTestTest, test_autoRead) { opTest->stopCmd(); EXPECT_CALL(*arduinoMock, millis).Times(0); EXPECT_CALL(*opKnitMock, encodePosition).Times(0); - expect_write(false); expect_readEOLsensors(false); expect_readEncoders(false); opTest->update(); // test expectations without destroying instance ASSERT_TRUE(Mock::VerifyAndClear(opKnitMock)); + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_autoTest) { @@ -290,7 +327,6 @@ TEST_F(OpTestTest, test_autoTest) { // nothing has happened yet EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(TEST_LOOP_DELAY - 1)); EXPECT_CALL(*opKnitMock, encodePosition); - expect_write(false); EXPECT_CALL(*arduinoMock, digitalWrite(LED_PIN_A, HIGH)).Times(0); EXPECT_CALL(*arduinoMock, digitalWrite(LED_PIN_B, HIGH)).Times(0); opTest->update(); @@ -298,15 +334,15 @@ TEST_F(OpTestTest, test_autoTest) { // m_timerEventOdd = false EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(TEST_LOOP_DELAY)); EXPECT_CALL(*opKnitMock, encodePosition); - expect_write(true); + expect_send(true); EXPECT_CALL(*arduinoMock, digitalWrite(LED_PIN_A, HIGH)); EXPECT_CALL(*arduinoMock, digitalWrite(LED_PIN_B, HIGH)); opTest->update(); - // m_timerEventOdd = false + // m_timerEventOdd = true EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(2 * TEST_LOOP_DELAY)); EXPECT_CALL(*opKnitMock, encodePosition); - expect_write(false); + expect_send(true); EXPECT_CALL(*arduinoMock, digitalWrite(LED_PIN_A, LOW)); EXPECT_CALL(*arduinoMock, digitalWrite(LED_PIN_B, LOW)); opTest->update(); @@ -315,13 +351,13 @@ TEST_F(OpTestTest, test_autoTest) { opTest->stopCmd(); EXPECT_CALL(*arduinoMock, millis).Times(0); EXPECT_CALL(*opKnitMock, encodePosition).Times(0); - expect_write(false); EXPECT_CALL(*arduinoMock, digitalWrite(LED_PIN_A, _)).Times(0); EXPECT_CALL(*arduinoMock, digitalWrite(LED_PIN_B, _)).Times(0); opTest->update(); // test expectations without destroying instance ASSERT_TRUE(Mock::VerifyAndClear(opKnitMock)); + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(OpTestTest, test_startTest_success) { @@ -333,4 +369,3 @@ TEST_F(OpTestTest, test_unrecognized) { const uint8_t buffer[] = {0xFF}; opTest->com(buffer, 1); } - diff --git a/test/test_all.cpp b/test/test_all.cpp index 62ebd5162..57d3b3995 100644 --- a/test/test_all.cpp +++ b/test/test_all.cpp @@ -24,6 +24,8 @@ #include "gtest/gtest.h" #include +#include + #include #include @@ -41,6 +43,8 @@ // global definitions // references everywhere else must use `extern` AnalogReadAsyncWrapper *analogReadAsyncWrapper = new AnalogReadAsyncWrapper(); +PacketSerialWrapper *packetSerialWrapper = new PacketSerialWrapper(); + Controller *controller = new Controller(); OpKnit *opKnit = new OpKnit(); @@ -57,6 +61,8 @@ OpErrorMock *opError = new OpErrorMock(); // instantiate singleton classes with mock objects AnalogReadAsyncWrapperInterface *GlobalAnalogReadAsyncWrapper::m_instance = analogReadAsyncWrapper; +PacketSerialWrapperInterface *GlobalPacketSerialWrapper::m_instance = packetSerialWrapper; + ControllerInterface *GlobalController::m_instance = controller; OpKnitInterface *GlobalOpKnit::m_instance = opKnit; diff --git a/test/test_boards.cpp b/test/test_boards.cpp index a606bef18..104333ed0 100644 --- a/test/test_boards.cpp +++ b/test/test_boards.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -52,6 +53,7 @@ OpTest *opTest = new OpTest(); OpError *opError = new OpError(); AnalogReadAsyncWrapperMock *analogReadAsyncWrapper = new AnalogReadAsyncWrapperMock(); +PacketSerialWrapperMock *packetSerialWrapper = new PacketSerialWrapperMock(); ControllerMock *controller = new ControllerMock(); OpKnitMock *opKnit = new OpKnitMock(); @@ -68,6 +70,7 @@ OpTestInterface *GlobalOpTest::m_instance = opTest; OpErrorInterface *GlobalOpError::m_instance = opError; AnalogReadAsyncWrapperInterface *GlobalAnalogReadAsyncWrapper::m_instance = analogReadAsyncWrapper; +PacketSerialWrapperInterface *GlobalPacketSerialWrapper::m_instance = packetSerialWrapper; ControllerInterface *GlobalController::m_instance = controller; OpKnitInterface *GlobalOpKnit::m_instance = opKnit; diff --git a/test/test_com.cpp b/test/test_com.cpp index 276b4bf73..ced7c2f01 100644 --- a/test/test_com.cpp +++ b/test/test_com.cpp @@ -32,6 +32,7 @@ #include #include +#include using ::testing::_; using ::testing::AtLeast; @@ -47,22 +48,24 @@ extern OpTest *opTest; extern ControllerMock *controller; extern OpKnitMock *opKnit; +extern PacketSerialWrapperMock *packetSerialWrapper; class ComTest : public ::testing::Test { protected: void SetUp() override { arduinoMock = arduinoMockInstance(); - serialMock = serialMockInstance(); // pointer to global instance controllerMock = controller; opKnitMock = opKnit; + packetSerialWrapperMock = packetSerialWrapper; // The global instance does not get destroyed at the end of each test. // Ordinarily the mock instance would be local and such behaviour would // cause a memory leak. We must notify the test that this is not the case. Mock::AllowLeak(controllerMock); Mock::AllowLeak(opKnitMock); + Mock::AllowLeak(packetSerialWrapperMock); beeper->init(true); expect_init(); @@ -72,33 +75,28 @@ class ComTest : public ::testing::Test { void TearDown() override { releaseArduinoMock(); - releaseSerialMock(); } ArduinoMock *arduinoMock; - SerialMock *serialMock; ControllerMock *controllerMock; OpKnitMock *opKnitMock; + PacketSerialWrapperMock *packetSerialWrapperMock; void expect_init() { - //EXPECT_CALL(*serialMock, begin); + EXPECT_CALL(*packetSerialWrapperMock, begin); } - void expect_write(bool once) { + void expect_send(bool once) { if (once) { - // FIXME need to mock SerialPacket - //EXPECT_CALL(*serialMock, write(_, _)); - //EXPECT_CALL(*serialMock, write(SLIP::END)); + EXPECT_CALL(*packetSerialWrapperMock, send).Times(1); } else { - //EXPECT_CALL(*serialMock, write(_, _)).Times(AtLeast(1)); - //EXPECT_CALL(*serialMock, write(SLIP::END)).Times(AtLeast(1)); + EXPECT_CALL(*packetSerialWrapperMock, send).Times(AtLeast(2)); } } void expected_write_onPacketReceived(uint8_t *buffer, size_t size, bool once) { - expect_write(once); - //com->onPacketReceived(buffer, size); + expect_send(once); opTest->com(buffer, size); } @@ -106,7 +104,7 @@ class ComTest : public ::testing::Test { uint8_t buffer[] = {static_cast(API_t::reqInit), static_cast(machine), 0}; buffer[2] = com->CRC8(buffer, 2); EXPECT_CALL(*controllerMock, setState(opInit)); - expect_write(true); + expect_send(true); opIdle->com(buffer, sizeof(buffer)); } }; @@ -114,24 +112,33 @@ class ComTest : public ::testing::Test { TEST_F(ComTest, test_reqInit_fail1) { uint8_t buffer[] = {static_cast(API_t::reqInit), static_cast(Machine_t::Kh930)}; EXPECT_CALL(*controllerMock, setState(opInit)).Times(0); - expect_write(true); + expect_send(true); opIdle->com(buffer, sizeof(buffer)); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_reqInit_fail2) { uint8_t buffer[] = {static_cast(API_t::reqInit), static_cast(Machine_t::Kh930), 0}; buffer[2] = com->CRC8(buffer, 2) ^ 1; EXPECT_CALL(*controllerMock, setState(opInit)).Times(0); - expect_write(true); + expect_send(true); opIdle->com(buffer, sizeof(buffer)); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_reqInit_fail3) { uint8_t buffer[] = {static_cast(API_t::reqInit), static_cast(Machine_t::NoMachine), 0}; buffer[2] = com->CRC8(buffer, 2); EXPECT_CALL(*controllerMock, setState(opInit)).Times(0); - expect_write(true); + expect_send(true); opIdle->com(buffer, sizeof(buffer)); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } /* @@ -154,70 +161,84 @@ TEST_F(ComTest, test_reqtest_fail) { TEST_F(ComTest, test_reqtest) { EXPECT_CALL(*controllerMock, setState(opTest)); - expect_write(true); + expect_send(true); com->h_reqTest(); // test expectations without destroying instance ASSERT_TRUE(Mock::VerifyAndClear(controllerMock)); + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_reqstart_fail1) { // checksum wrong uint8_t buffer[] = {static_cast(API_t::reqStart), 0, 10, 1, 0x73}; EXPECT_CALL(*opKnitMock, startKnitting).Times(0); - expect_write(true); + expect_send(true); com->h_reqStart(buffer, sizeof(buffer)); // test expectations without destroying instance ASSERT_TRUE(Mock::VerifyAndClear(opKnitMock)); + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_reqstart_fail2) { // not enough bytes uint8_t buffer[] = {static_cast(API_t::reqStart), 0, 1, 0x74}; EXPECT_CALL(*opKnitMock, startKnitting).Times(0); - expect_write(true); + expect_send(true); com->h_reqStart(buffer, sizeof(buffer) - 1); // test expectations without destroying instance ASSERT_TRUE(Mock::VerifyAndClear(opKnitMock)); + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_reqstart_success_KH910) { reqInit(Machine_t::Kh910); uint8_t buffer[] = {static_cast(API_t::reqStart), 0, 10, 1, 0x36}; EXPECT_CALL(*opKnitMock, startKnitting); - expect_write(true); + expect_send(true); com->h_reqStart(buffer, sizeof(buffer)); // test expectations without destroying instance ASSERT_TRUE(Mock::VerifyAndClear(opKnitMock)); + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_reqstart_success_KH270) { reqInit(Machine_t::Kh270); uint8_t buffer[] = {static_cast(API_t::reqStart), 0, 10, 1, 0x36}; EXPECT_CALL(*opKnitMock, startKnitting); - expect_write(true); + expect_send(true); com->h_reqStart(buffer, sizeof(buffer)); // test expectations without destroying instance ASSERT_TRUE(Mock::VerifyAndClear(opKnitMock)); + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_reqinfo) { - expect_write(true); + expect_send(true); com->h_reqInfo(); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_helpCmd) { uint8_t buffer[] = {static_cast(API_t::helpCmd)}; expected_write_onPacketReceived(buffer, sizeof(buffer), false); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_sendCmd) { uint8_t buffer[] = {static_cast(API_t::sendCmd)}; expected_write_onPacketReceived(buffer, sizeof(buffer), false); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_beepCmd) { @@ -228,16 +249,25 @@ TEST_F(ComTest, test_beepCmd) { EXPECT_CALL(*arduinoMock, analogWrite(PIEZO_PIN, BEEP_ON_DUTY)); EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(1U)); beeper->update(); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_setSingleCmd) { uint8_t buffer[] = {static_cast(API_t::setSingleCmd), 0, 0}; expected_write_onPacketReceived(buffer, sizeof(buffer), true); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_setAllCmd) { uint8_t buffer[] = {static_cast(API_t::setAllCmd), 0, 0}; expected_write_onPacketReceived(buffer, sizeof(buffer), true); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_readEOLsensorsCmd) { @@ -245,6 +275,9 @@ TEST_F(ComTest, test_readEOLsensorsCmd) { EXPECT_CALL(*arduinoMock, analogRead(EOL_PIN_L)); EXPECT_CALL(*arduinoMock, analogRead(EOL_PIN_R)); expected_write_onPacketReceived(buffer, sizeof(buffer), false); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_readEncodersCmd) { @@ -253,22 +286,34 @@ TEST_F(ComTest, test_readEncodersCmd) { EXPECT_CALL(*arduinoMock, digitalRead(ENC_PIN_B)); EXPECT_CALL(*arduinoMock, digitalRead(ENC_PIN_C)); expected_write_onPacketReceived(buffer, sizeof(buffer), false); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_autoReadCmd) { uint8_t buffer[] = {static_cast(API_t::autoReadCmd)}; expected_write_onPacketReceived(buffer, sizeof(buffer), true); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_autoTestCmd) { uint8_t buffer[] = {static_cast(API_t::autoTestCmd)}; expected_write_onPacketReceived(buffer, sizeof(buffer), true); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } /* TEST_F(ComTest, test_stopCmd) { uint8_t buffer[] = {static_cast(API_t::stopCmd)}; com->onPacketReceived(buffer, sizeof(buffer)); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } */ @@ -373,25 +418,37 @@ TEST_F(ComTest, test_update) { } TEST_F(ComTest, test_send) { - expect_write(true); + expect_send(true); uint8_t p[] = {1, 2, 3}; com->send(p, 3); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_sendMsg1) { - expect_write(true); + expect_send(true); com->sendMsg(API_t::testRes, "abc"); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_sendMsg2) { char buf[] = "abc\0"; - expect_write(true); + expect_send(true); com->sendMsg(API_t::testRes, buf); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_send_reqLine) { - expect_write(true); + expect_send(true); com->send_reqLine(0); + + // test expectations without destroying instance + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); } TEST_F(ComTest, test_send_indState) { @@ -401,9 +458,10 @@ TEST_F(ComTest, test_send_indState) { EXPECT_CALL(*controllerMock, getCarriage); EXPECT_CALL(*controllerMock, getPosition); EXPECT_CALL(*controllerMock, getDirection); - expect_write(true); + expect_send(true); com->send_indState(Err_t::Success); // test expectations without destroying instance ASSERT_TRUE(Mock::VerifyAndClear(controllerMock)); + ASSERT_TRUE(Mock::VerifyAndClear(packetSerialWrapperMock)); }