diff --git a/.travis.yml b/.travis.yml index 099073b46..099782b16 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,9 +7,10 @@ matrix: sources: - ubuntu-toolchain-r-test packages: - - g++ + - g++-9 + - gcc-9 env: - - MATRIX_EVAL="CC=gcc-7 && CXX=g++-7" + - MATRIX_EVAL="CC=gcc-9 && CXX=g++-9" before_install: - eval "${MATRIX_EVAL}" - pip install gcovr diff --git a/src/ayab/global_hw_test.cpp b/src/ayab/global_hw_test.cpp new file mode 100644 index 000000000..dfdc6be90 --- /dev/null +++ b/src/ayab/global_hw_test.cpp @@ -0,0 +1,87 @@ +/*! + * \file global_hw_test.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 Sturla Lange, Tom Price + * http://ayab-knitting.com + */ + +#include "hw_test.h" + +// static member functions + +void GlobalHardwareTest::helpCmd() { + m_instance->helpCmd(); +} + +void GlobalHardwareTest::sendCmd() { + m_instance->sendCmd(); +} + +void GlobalHardwareTest::beepCmd() { + m_instance->beepCmd(); +} + +void GlobalHardwareTest::setSingleCmd() { + m_instance->setSingleCmd(); +} + +void GlobalHardwareTest::setAllCmd() { + m_instance->setAllCmd(); +} + +void GlobalHardwareTest::readEOLsensorsCmd() { + m_instance->readEOLsensorsCmd(); +} + +void GlobalHardwareTest::readEncodersCmd() { + m_instance->readEncodersCmd(); +} + +void GlobalHardwareTest::autoReadCmd() { + m_instance->autoReadCmd(); +} + +void GlobalHardwareTest::autoTestCmd() { + m_instance->autoTestCmd(); +} + +void GlobalHardwareTest::stopCmd() { + m_instance->stopCmd(); +} + +void GlobalHardwareTest::quitCmd() { + m_instance->quitCmd(); +} + +void GlobalHardwareTest::unrecognizedCmd(const char *buffer) { + m_instance->unrecognizedCmd(buffer); +} + +void GlobalHardwareTest::setUp() { + m_instance->setUp(); +} + +void GlobalHardwareTest::loop() { + m_instance->loop(); +} + +#ifndef AYAB_TESTS +void GlobalHardwareTest::encoderAChange() { + m_instance->encoderAChange(); +} +#endif // AYAB_TESTS diff --git a/src/ayab/hw_test.cpp b/src/ayab/hw_test.cpp index 6d1738883..6aab23995 100644 --- a/src/ayab/hw_test.cpp +++ b/src/ayab/hw_test.cpp @@ -25,16 +25,11 @@ #include "hw_test.h" #include "knitter.h" -extern Knitter *knitter; - -// initialise static members -SerialCommand HardwareTest::m_sCmd = SerialCommand(); -bool HardwareTest::m_autoReadOn = false; -bool HardwareTest::m_autoTestOn = false; -bool HardwareTest::m_timerEvent = false; -bool HardwareTest::m_timerEventOdd = false; -unsigned long HardwareTest::m_lastTime = 0U; +// public interface +/*! + * \brief Help command handler. + */ void HardwareTest::helpCmd() { Serial.println("The following commands are available:"); Serial.println("setSingle [0..15] [1/0]"); @@ -50,6 +45,9 @@ void HardwareTest::helpCmd() { Serial.println("help"); } +/*! + * \brief Send command handler. + */ void HardwareTest::sendCmd() { Serial.println("Called send"); uint8_t p[] = {1, 2, 3}; @@ -57,10 +55,6 @@ void HardwareTest::sendCmd() { Serial.print("\n"); } -void HardwareTest::beep() { - knitter->m_beeper.ready(); -} - /*! * \brief Beep command handler. */ @@ -117,13 +111,6 @@ void HardwareTest::setAllCmd() { knitter->setSolenoids(solenoidState); } -void HardwareTest::readEOLsensors() { - Serial.print(" EOL_L: "); - Serial.print(analogRead(EOL_PIN_L)); - Serial.print(" EOL_R: "); - Serial.print(analogRead(EOL_PIN_R)); -} - /*! * \brief Read EOL sensors command handler. */ @@ -133,18 +120,6 @@ void HardwareTest::readEOLsensorsCmd() { Serial.print("\n"); } -void HardwareTest::readEncoders() { - Serial.print(" ENC_A: "); - bool state = digitalRead(ENC_PIN_A); - Serial.print(state ? "HIGH" : "LOW"); - Serial.print(" ENC_B: "); - state = digitalRead(ENC_PIN_B); - Serial.print(state ? "HIGH" : "LOW"); - Serial.print(" ENC_C: "); - state = digitalRead(ENC_PIN_C); - Serial.print(state ? "HIGH" : "LOW"); -} - /*! * \brief Read encoders command handler. */ @@ -154,13 +129,6 @@ void HardwareTest::readEncodersCmd() { Serial.print("\n"); } -void HardwareTest::autoRead() { - Serial.print("\n"); - readEOLsensors(); - readEncoders(); - Serial.print("\n"); -} - /*! * \brief Auto read command handler. */ @@ -169,20 +137,6 @@ void HardwareTest::autoReadCmd() { m_autoReadOn = true; } -void HardwareTest::autoTestEven() { - Serial.println("Set even solenoids"); - digitalWrite(LED_PIN_A, 1); - digitalWrite(LED_PIN_B, 1); - knitter->setSolenoids(0xAAAA); -} - -void HardwareTest::autoTestOdd() { - Serial.println("Set odd solenoids"); - digitalWrite(LED_PIN_A, 0); - digitalWrite(LED_PIN_B, 0); - knitter->setSolenoids(0x5555); -} - /*! * \brief Auto test command handler. */ @@ -191,11 +145,17 @@ void HardwareTest::autoTestCmd() { m_autoTestOn = true; } +/*! + * \brief Stop command handler. + */ void HardwareTest::stopCmd() { m_autoReadOn = false; m_autoTestOn = false; } +/*! + * \brief Quit command handler. + */ void HardwareTest::quitCmd() { knitter->setQuitFlag(true); knitter->setUpInterrupt(); @@ -215,25 +175,23 @@ void HardwareTest::unrecognizedCmd(const char *buffer) { helpCmd(); } -// Member functions - /*! - * \brief Setup for hw tests. + * \brief Setup for hardware tests. */ void HardwareTest::setUp() { // set up callbacks for SerialCommand commands - m_sCmd.addCommand("setSingle", HardwareTest::setSingleCmd); - m_sCmd.addCommand("setAll", HardwareTest::setAllCmd); - m_sCmd.addCommand("readEOLsensors", HardwareTest::readEOLsensorsCmd); - m_sCmd.addCommand("readEncoders", HardwareTest::readEncodersCmd); - m_sCmd.addCommand("beep", HardwareTest::beepCmd); - m_sCmd.addCommand("autoRead", HardwareTest::autoReadCmd); - m_sCmd.addCommand("autoTest", HardwareTest::autoTestCmd); - m_sCmd.addCommand("send", HardwareTest::sendCmd); - m_sCmd.addCommand("stop", HardwareTest::stopCmd); - m_sCmd.addCommand("quit", HardwareTest::quitCmd); - m_sCmd.addCommand("help", HardwareTest::helpCmd); - m_sCmd.setDefaultHandler(HardwareTest::unrecognizedCmd); + m_sCmd.addCommand("setSingle", GlobalHardwareTest::setSingleCmd); + m_sCmd.addCommand("setAll", GlobalHardwareTest::setAllCmd); + m_sCmd.addCommand("readEOLsensors", GlobalHardwareTest::readEOLsensorsCmd); + m_sCmd.addCommand("readEncoders", GlobalHardwareTest::readEncodersCmd); + m_sCmd.addCommand("beep", GlobalHardwareTest::beepCmd); + m_sCmd.addCommand("autoRead", GlobalHardwareTest::autoReadCmd); + m_sCmd.addCommand("autoTest", GlobalHardwareTest::autoTestCmd); + m_sCmd.addCommand("send", GlobalHardwareTest::sendCmd); + m_sCmd.addCommand("stop", GlobalHardwareTest::stopCmd); + m_sCmd.addCommand("quit", GlobalHardwareTest::quitCmd); + m_sCmd.addCommand("help", GlobalHardwareTest::helpCmd); + m_sCmd.setDefaultHandler(GlobalHardwareTest::unrecognizedCmd); // Print welcome message Serial.print("AYAB Hardware Test, Firmware v"); @@ -248,25 +206,16 @@ void HardwareTest::setUp() { // attach interrupt for ENC_PIN_A(=2), interrupt #0 detachInterrupt(0); #ifndef AYAB_TESTS - attachInterrupt(0, encoderAChange, RISING); + attachInterrupt(0, GlobalHardwareTest::encoderAChange, RISING); +#endif // AYAB_TESTS m_lastTime = millis(); -#endif // AYAB_TESTS m_autoReadOn = false; m_autoTestOn = false; m_timerEventOdd = false; knitter->setQuitFlag(false); } -#ifndef AYAB_TESTS -/*! - * \brief Interrupt service routine for encoder A. - */ -void HardwareTest::encoderAChange() { - beep(); -} -#endif // AYAB_TESTS - /*! * \brief Main loop for hardware tests. */ @@ -278,6 +227,61 @@ void HardwareTest::loop() { } } +// Private member functions + +void HardwareTest::beep() { + knitter->m_beeper.ready(); +} + +void HardwareTest::readEncoders() { + Serial.print(" ENC_A: "); + bool state = digitalRead(ENC_PIN_A); + Serial.print(state ? "HIGH" : "LOW"); + Serial.print(" ENC_B: "); + state = digitalRead(ENC_PIN_B); + Serial.print(state ? "HIGH" : "LOW"); + Serial.print(" ENC_C: "); + state = digitalRead(ENC_PIN_C); + Serial.print(state ? "HIGH" : "LOW"); +} + +void HardwareTest::readEOLsensors() { + Serial.print(" EOL_L: "); + Serial.print(analogRead(EOL_PIN_L)); + Serial.print(" EOL_R: "); + Serial.print(analogRead(EOL_PIN_R)); +} + +void HardwareTest::autoRead() { + Serial.print("\n"); + readEOLsensors(); + readEncoders(); + Serial.print("\n"); +} + +void HardwareTest::autoTestEven() { + Serial.println("Set even solenoids"); + digitalWrite(LED_PIN_A, 1); + digitalWrite(LED_PIN_B, 1); + knitter->setSolenoids(0xAAAA); +} + +void HardwareTest::autoTestOdd() { + Serial.println("Set odd solenoids"); + digitalWrite(LED_PIN_A, 0); + digitalWrite(LED_PIN_B, 0); + knitter->setSolenoids(0x5555); +} + +/*! + * \brief Interrupt service routine for encoder A. + */ +#ifndef AYAB_TESTS +void HardwareTest::encoderAChange() { + beep(); +} +#endif // AYAB_TESTS + /*! * \brief Timer event every 500ms to handle auto functions. */ diff --git a/src/ayab/hw_test.h b/src/ayab/hw_test.h index 9183c741a..b96fbff13 100644 --- a/src/ayab/hw_test.h +++ b/src/ayab/hw_test.h @@ -28,7 +28,31 @@ #include "beeper.h" -class HardwareTest { +class HardwareTestInterface { +public: + virtual ~HardwareTestInterface(){}; + + virtual void helpCmd() = 0; + virtual void sendCmd() = 0; + virtual void beepCmd() = 0; + virtual void setSingleCmd() = 0; + virtual void setAllCmd() = 0; + virtual void readEOLsensorsCmd() = 0; + virtual void readEncodersCmd() = 0; + virtual void autoReadCmd() = 0; + virtual void autoTestCmd() = 0; + virtual void stopCmd() = 0; + virtual void quitCmd() = 0; + virtual void unrecognizedCmd(const char *buffer) = 0; + + virtual void setUp() = 0; + virtual void loop() = 0; +#ifndef AYAB_TESTS + virtual void encoderAChange() = 0; +#endif +}; + +class HardwareTest : public HardwareTestInterface { #if AYAB_TESTS FRIEND_TEST(HardwareTestTest, test_setUp); FRIEND_TEST(HardwareTestTest, test_loop_default); @@ -37,6 +61,46 @@ class HardwareTest { FRIEND_TEST(HardwareTestTest, test_loop_autoTestOdd); friend class HardwareTestTest; #endif + +public: + void helpCmd(); + void sendCmd(); + void beepCmd(); + void setSingleCmd(); + void setAllCmd(); + void readEOLsensorsCmd(); + void readEncodersCmd(); + void autoReadCmd(); + void autoTestCmd(); + void stopCmd(); + void quitCmd(); + void unrecognizedCmd(const char *buffer); + + void setUp(); + void loop(); +#ifndef AYAB_TESTS + void encoderAChange(); +#endif + +private: + void beep(); + void readEOLsensors(); + void readEncoders(); + void autoRead(); + void autoTestEven(); + void autoTestOdd(); + void handleTimerEvent(); + + SerialCommand m_sCmd = SerialCommand(); + + bool m_autoReadOn = false; + bool m_autoTestOn = false; + + unsigned long m_lastTime = 0U; + bool m_timerEventOdd = false; +}; + +class GlobalHardwareTest { public: static void helpCmd(); static void sendCmd(); @@ -53,30 +117,13 @@ class HardwareTest { static void setUp(); static void loop(); - - static SerialCommand m_sCmd; - /* static bool m_quitFlag; */ - -private: - static void beep(); - static void readEOLsensors(); - static void readEncoders(); - static void autoRead(); - static void autoTestEven(); - static void autoTestOdd(); - static void handleTimerEvent(); - #ifndef AYAB_TESTS static void encoderAChange(); #endif - static bool m_autoReadOn; - static bool m_autoTestOn; - - static unsigned long m_lastTime; - static bool m_timerEventOdd; + static HardwareTestInterface *m_instance; }; -extern HardwareTest *hwTest; +extern GlobalHardwareTest *hwTest; #endif // HW_TEST_H_ diff --git a/src/ayab/knitter.cpp b/src/ayab/knitter.cpp index fa30fa2e8..35eec65a5 100644 --- a/src/ayab/knitter.cpp +++ b/src/ayab/knitter.cpp @@ -35,7 +35,6 @@ constexpr uint16_t UINT16_MAX = 0xFFFFU; #endif extern Knitter *knitter; -extern HardwareTest *hwTest; #ifndef AYAB_TESTS /*! @@ -185,7 +184,7 @@ bool Knitter::startTest(Machine_t machineType) { if (s_init == m_opState || s_ready == m_opState) { m_opState = s_test; m_machineType = machineType; - HardwareTest::setUp(); + GlobalHardwareTest::setUp(); success = true; } return success; @@ -344,7 +343,7 @@ void Knitter::state_test() { calculatePixelAndSolenoid(); indState(); } - HardwareTest::loop(); + GlobalHardwareTest::loop(); if (m_quitFlag) { m_opState = s_ready; } diff --git a/src/ayab/main.cpp b/src/ayab/main.cpp index ff0125be3..3fb1cccfb 100644 --- a/src/ayab/main.cpp +++ b/src/ayab/main.cpp @@ -27,17 +27,18 @@ #include "hw_test.h" #include "knitter.h" -// global definitions +// global definition // references everywhere else must use `extern` Knitter *knitter; -HardwareTest *hwTest; + +// initialize static member +HardwareTestInterface *GlobalHardwareTest::m_instance = new HardwareTest(); /*! * Setup - steps to take before going to the main loop. */ void setup() { knitter = new Knitter(); - hwTest = new HardwareTest(); } /*! diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2ac2ce66e..0ac32270b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -53,6 +53,7 @@ set(COMMON_SOURCES ${PROJECT_SOURCE_DIR}/test_serial_encoding.cpp ${SOURCE_DIRECTORY}/hw_test.cpp + ${SOURCE_DIRECTORY}/global_hw_test.cpp ${PROJECT_SOURCE_DIR}/test_hw_test.cpp ${PROJECT_SOURCE_DIR}/mocks/SerialCommand_mock.cpp @@ -68,7 +69,12 @@ set(COMMON_FLAGS -Wall -Wextra -Wpedantic -Wno-vla -Werror - -fprofile-arcs -ftest-coverage + -fprofile-arcs -ftest-coverage + + # exclude global_hw_test.cpp from profile analysis + # to avoid tedious mocking of these simple functions + -fprofile-exclude-files=global_hw_test.cpp + -g -Og ) set(COMMON_LINKER_FLAGS @@ -133,6 +139,7 @@ add_board(Mega) add_executable(${PROJECT_NAME}_knitter ${PROJECT_SOURCE_DIR}/test_all.cpp ${SOURCE_DIRECTORY}/knitter.cpp + ${SOURCE_DIRECTORY}/global_hw_test.cpp ${PROJECT_SOURCE_DIR}/mocks/solenoids_mock.cpp ${PROJECT_SOURCE_DIR}/mocks/encoders_mock.cpp ${PROJECT_SOURCE_DIR}/mocks/beeper_mock.cpp diff --git a/test/mocks/hw_test_mock.cpp b/test/mocks/hw_test_mock.cpp index e25cfb5a6..c82c498ab 100644 --- a/test/mocks/hw_test_mock.cpp +++ b/test/mocks/hw_test_mock.cpp @@ -24,7 +24,8 @@ #include static HardwareTestMock *gHardwareTestMock = NULL; -HardwareTestMock *hardwareTestMockInstance() { + +HardwareTestMock *hwTestMockInstance() { if (!gHardwareTestMock) { gHardwareTestMock = new HardwareTestMock(); } diff --git a/test/mocks/hw_test_mock.h b/test/mocks/hw_test_mock.h index f317c991d..d8e60f372 100644 --- a/test/mocks/hw_test_mock.h +++ b/test/mocks/hw_test_mock.h @@ -27,7 +27,7 @@ #include #include -class HardwareTestMock { +class HardwareTestMock : public HardwareTestInterface { public: MOCK_METHOD0(helpCmd, void()); MOCK_METHOD0(sendCmd, void()); @@ -45,7 +45,7 @@ class HardwareTestMock { MOCK_METHOD0(loop, void()); }; -HardwareTestMock *hardwareTestMockInstance(); +HardwareTestMock *hwTestMockInstance(); void releaseHardwareTestMock(); #endif // HW_TEST_MOCK_H_ diff --git a/test/test_hw_test.cpp b/test/test_hw_test.cpp index 026c2800a..0f6f41bcf 100644 --- a/test/test_hw_test.cpp +++ b/test/test_hw_test.cpp @@ -34,6 +34,9 @@ static char zero[2] = {48, 0}; // "0" static char two[2] = {50, 0}; // "2" static char twenty[3] = {50, 48, 0}; // "20" +// initialize static member +HardwareTestInterface *GlobalHardwareTest::m_instance = new HardwareTest(); + class HardwareTestTest : public ::testing::Test { protected: void SetUp() override { @@ -41,6 +44,7 @@ class HardwareTestTest : public ::testing::Test { serialMock = serialMockInstance(); serialCommandMock = serialCommandMockInstance(); knitterMock = knitterMockInstance(); + h = new HardwareTest(); } void TearDown() override { @@ -54,151 +58,149 @@ class HardwareTestTest : public ::testing::Test { SerialMock *serialMock; SerialCommandMock *serialCommandMock; KnitterMock *knitterMock; - - void expect_test() { - } + HardwareTest *h; }; TEST_F(HardwareTestTest, test_setUp) { EXPECT_CALL(*knitterMock, setQuitFlag); - ASSERT_FALSE(HardwareTest::m_autoReadOn); - ASSERT_FALSE(HardwareTest::m_autoTestOn); - ASSERT_FALSE(HardwareTest::m_timerEvent); - ASSERT_FALSE(HardwareTest::m_timerEventOdd); - HardwareTest::setUp(); + EXPECT_CALL(*arduinoMock, millis); + h->setUp(); + ASSERT_FALSE(h->m_autoReadOn); + ASSERT_FALSE(h->m_autoTestOn); + ASSERT_FALSE(h->m_timerEventOdd); } TEST_F(HardwareTestTest, test_helpCmd) { - HardwareTest::helpCmd(); + h->helpCmd(); } TEST_F(HardwareTestTest, test_sendCmd) { EXPECT_CALL(*knitterMock, send); - HardwareTest::sendCmd(); + h->sendCmd(); } TEST_F(HardwareTestTest, test_beepCmd) { EXPECT_CALL(*arduinoMock, analogWrite).Times(AtLeast(1)); EXPECT_CALL(*arduinoMock, delay).Times(AtLeast(1)); - HardwareTest::beepCmd(); + h->beepCmd(); } TEST_F(HardwareTestTest, test_setSingleCmd_fail1) { EXPECT_CALL(*serialCommandMock, next).WillOnce(Return(nullptr)); - HardwareTest::setSingleCmd(); + h->setSingleCmd(); } TEST_F(HardwareTestTest, test_setSingleCmd_fail2) { EXPECT_CALL(*serialCommandMock, next).WillOnce(Return(twenty)); - HardwareTest::setSingleCmd(); + h->setSingleCmd(); } TEST_F(HardwareTestTest, test_setSingleCmd_fail3) { EXPECT_CALL(*serialCommandMock, next) .WillOnce(Return(zero)) .WillOnce(Return(nullptr)); - HardwareTest::setSingleCmd(); + h->setSingleCmd(); } TEST_F(HardwareTestTest, test_setSingleCmd_fail4) { EXPECT_CALL(*serialCommandMock, next) .WillOnce(Return(zero)) .WillOnce(Return(two)); - HardwareTest::setSingleCmd(); + h->setSingleCmd(); } TEST_F(HardwareTestTest, test_setSingleCmd_success) { EXPECT_CALL(*serialCommandMock, next).WillRepeatedly(Return(zero)); EXPECT_CALL(*knitterMock, setSolenoid); - HardwareTest::setSingleCmd(); + h->setSingleCmd(); } TEST_F(HardwareTestTest, test_setAllCmd_fail1) { EXPECT_CALL(*serialCommandMock, next).WillOnce(Return(nullptr)); - HardwareTest::setAllCmd(); + h->setAllCmd(); } TEST_F(HardwareTestTest, test_setAllCmd_fail2) { EXPECT_CALL(*serialCommandMock, next) .WillOnce(Return(zero)) .WillOnce(Return(nullptr)); - HardwareTest::setAllCmd(); + h->setAllCmd(); } TEST_F(HardwareTestTest, test_setAllCmd_success) { EXPECT_CALL(*serialCommandMock, next).WillRepeatedly(Return(zero)); EXPECT_CALL(*knitterMock, setSolenoids); - HardwareTest::setAllCmd(); + h->setAllCmd(); } TEST_F(HardwareTestTest, test_readEOLsensorsCmd) { - HardwareTest::readEOLsensorsCmd(); + h->readEOLsensorsCmd(); } TEST_F(HardwareTestTest, test_readEncodersCmd) { // low EXPECT_CALL(*arduinoMock, digitalRead).WillRepeatedly(Return(0)); - HardwareTest::readEncodersCmd(); + h->readEncodersCmd(); // high EXPECT_CALL(*arduinoMock, digitalRead).WillRepeatedly(Return(1)); - HardwareTest::readEncodersCmd(); + h->readEncodersCmd(); } TEST_F(HardwareTestTest, test_autoReadCmd) { - HardwareTest::autoReadCmd(); + h->autoReadCmd(); } TEST_F(HardwareTestTest, test_autoTestCmd) { - HardwareTest::autoTestCmd(); + h->autoTestCmd(); } TEST_F(HardwareTestTest, test_stopCmd) { - HardwareTest::stopCmd(); + h->stopCmd(); } TEST_F(HardwareTestTest, test_quitCmd) { EXPECT_CALL(*knitterMock, setQuitFlag); - HardwareTest::quitCmd(); + h->quitCmd(); } TEST_F(HardwareTestTest, test_unrecognizedCmd) { const char buffer[1] = {1}; - HardwareTest::unrecognizedCmd(buffer); + h->unrecognizedCmd(buffer); } TEST_F(HardwareTestTest, test_loop_default) { - HardwareTest::m_lastTime = 0; + h->m_lastTime = 0; EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(499)); - HardwareTest::loop(); + h->loop(); } -TEST_F(HardwareTestTest, test_loop_autoRead) { - HardwareTest::m_lastTime = 0; +TEST_F(HardwareTestTest, test_nullTimerEvent) { + h->m_lastTime = 0; EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(500)); - HardwareTest::m_timerEventOdd = true; - HardwareTest::m_autoReadOn = true; - EXPECT_CALL(*arduinoMock, analogRead).Times(2); - EXPECT_CALL(*arduinoMock, digitalRead).Times(3); - HardwareTest::loop(); + h->m_autoReadOn = false; + h->m_autoTestOn = false; + h->loop(); } TEST_F(HardwareTestTest, test_loop_autoTestEven) { - HardwareTest::m_lastTime = 0; + h->m_lastTime = 0; EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(500)); - HardwareTest::m_timerEventOdd = false; - HardwareTest::m_autoTestOn = true; + h->m_timerEventOdd = false; + h->m_autoReadOn = true; + h->m_autoTestOn = true; EXPECT_CALL(*arduinoMock, digitalWrite).Times(2); EXPECT_CALL(*knitterMock, setSolenoids); - HardwareTest::loop(); + h->loop(); } TEST_F(HardwareTestTest, test_loop_autoTestOdd) { - HardwareTest::m_lastTime = 0; + h->m_lastTime = 0; EXPECT_CALL(*arduinoMock, millis).WillOnce(Return(500)); - HardwareTest::m_timerEventOdd = true; - HardwareTest::m_autoTestOn = true; + h->m_timerEventOdd = true; + h->m_autoReadOn = true; + h->m_autoTestOn = true; EXPECT_CALL(*arduinoMock, digitalWrite).Times(2); EXPECT_CALL(*knitterMock, setSolenoids); - HardwareTest::loop(); + h->loop(); } diff --git a/test/test_knitter.cpp b/test/test_knitter.cpp index 5e6dfae54..644fad2b1 100644 --- a/test/test_knitter.cpp +++ b/test/test_knitter.cpp @@ -33,12 +33,15 @@ using ::testing::_; using ::testing::AtLeast; +using ::testing::Mock; using ::testing::Return; // global definitions // references everywhere else must use `extern` Knitter *knitter; -HardwareTest *hwTest; + +// initialize static member +HardwareTestInterface *GlobalHardwareTest::m_instance = new HardwareTestMock(); void onPacketReceived(const uint8_t *buffer, size_t size) { (void)buffer; @@ -53,7 +56,9 @@ class KnitterTest : public ::testing::Test { solenoidsMock = solenoidsMockInstance(); encodersMock = encodersMockInstance(); serialEncodingMock = serialEncodingMockInstance(); - hwTestMock = hardwareTestMockInstance(); + hwTestMock = + static_cast(GlobalHardwareTest::m_instance); + Mock::AllowLeak(hwTestMock); // because it does not get destructed expect_constructor(); k = new Knitter(); } @@ -73,7 +78,8 @@ class KnitterTest : public ::testing::Test { EncodersMock *encodersMock; SerialEncodingMock *serialEncodingMock; HardwareTestMock *hwTestMock; - Knitter *&k = knitter; // `k` is alias of global `knitter` + HardwareTestMock *dummy; + Knitter *&k = knitter; // alias of global `knitter` void expect_constructor() { EXPECT_CALL(*arduinoMock, pinMode(ENC_PIN_A, INPUT)); @@ -182,6 +188,7 @@ class KnitterTest : public ::testing::Test { expect_indState(); EXPECT_CALL(*hwTestMock, loop); expected_fsm(); + ASSERT_TRUE(Mock::VerifyAndClear(hwTestMock)); } void expected_set_machine(Machine_t machineType) { @@ -303,6 +310,8 @@ TEST_F(KnitterTest, test_fsm_test) { expect_indState<0>(); EXPECT_CALL(*hwTestMock, loop); expected_fsm(); + + ASSERT_TRUE(Mock::VerifyAndClear(hwTestMock)); } /*! @@ -373,6 +382,7 @@ TEST_F(KnitterTest, test_startTest) { EXPECT_CALL(*hwTestMock, setUp); ASSERT_EQ(k->startTest(Kh910), true); ASSERT_EQ(k->getState(), s_test); + ASSERT_TRUE(Mock::VerifyAndClear(hwTestMock)); } /*! @@ -684,6 +694,8 @@ TEST_F(KnitterTest, test_calculatePixelAndSolenoid) { // K carriage direction right expected_isr(END_RIGHT[Kh270], Right, Left, Regular, Knit); expected_test(); + + ASSERT_TRUE(Mock::VerifyAndClear(hwTestMock)); } /*! @@ -724,6 +736,7 @@ TEST_F(KnitterTest, test_quit_hw_test) { EXPECT_CALL(*hwTestMock, loop); k->state_test(); ASSERT_EQ(k->getState(), s_ready); + ASSERT_TRUE(Mock::VerifyAndClear(hwTestMock)); } /*!