From 89fc176955df162f191aaf48f6cd23b514ee854a Mon Sep 17 00:00:00 2001 From: "D.R.racer" Date: Thu, 11 Aug 2022 08:03:22 +0200 Subject: [PATCH] Add basic unit test infrastructure for application + registers --- src/application.cpp | 40 ++----------- src/application.h | 3 +- src/modules/protocol.cpp | 4 -- src/modules/protocol.h | 7 --- tests/unit/CMakeLists.txt | 2 + tests/unit/application/CMakeLists.txt | 57 +++++++++++++++++++ tests/unit/application/test_application.cpp | 13 +++++ tests/unit/application/test_registers.cpp | 27 +++++++++ tests/unit/modules/protocol/test_protocol.cpp | 2 +- tests/unit/modules/stubs/stub_serial.cpp | 29 +++++++++- tests/unit/modules/stubs/stub_serial.h | 17 ++++++ 11 files changed, 150 insertions(+), 51 deletions(-) create mode 100644 tests/unit/application/CMakeLists.txt create mode 100644 tests/unit/application/test_application.cpp create mode 100644 tests/unit/application/test_registers.cpp create mode 100644 tests/unit/modules/stubs/stub_serial.h diff --git a/src/application.cpp b/src/application.cpp index f85a022..d80e07f 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -95,10 +95,8 @@ mp::ResponseCommandStatus Application::RunningCommandStatus() const { } } -static constexpr const uint8_t maxMsgLen = 10; - void Application::ReportCommandAccepted(const mp::RequestMsg &rq, mp::ResponseMsgParamCodes status) { - uint8_t tmp[maxMsgLen]; + uint8_t tmp[mp::Protocol::MaxResponseSize()]; uint8_t len = protocol.EncodeResponseCmdAR(rq, status, tmp); modules::serial::WriteToUSART(tmp, len); } @@ -153,47 +151,19 @@ void Application::ReportFINDA(const mp::RequestMsg &rq) { hu::usart1.puts(" NOT TRIGGERED\n"); } #endif //DEBUG_FINDA - uint8_t rsp[maxMsgLen]; + uint8_t rsp[mp::Protocol::MaxResponseSize()]; uint8_t len = protocol.EncodeResponseReadFINDA(rq, mf::finda.Pressed(), rsp); modules::serial::WriteToUSART(rsp, len); } -//void Application::ReportVersion(const mp::RequestMsg &rq) { -// uint8_t v = 0; - -// switch (rq.value) { -// case 0: -// v = project_version_major; -// break; -// case 1: -// v = project_version_minor; -// break; -// case 2: -// v = project_version_revision; -// break; -// case 3: -// // @@TODO may be allow reporting uint16_t number of errors, -// // but anything beyond 255 errors means there is something seriously wrong with the MMU -// v = mg::globals.DriveErrors(); -// break; -// default: -// v = 0; -// break; -// } - -// uint8_t rsp[10]; -// uint8_t len = protocol.EncodeResponseVersion(rq, v, rsp); -// modules::serial::WriteToUSART(rsp, len); -//} - void Application::ReportRunningCommand() { - uint8_t rsp[maxMsgLen]; + uint8_t rsp[mp::Protocol::MaxResponseSize()]; uint8_t len = protocol.EncodeResponseQueryOperation(currentCommandRq, RunningCommandStatus(), rsp); modules::serial::WriteToUSART(rsp, len); } void Application::ReportReadRegister(const mp::RequestMsg &rq) { - uint8_t rsp[maxMsgLen]; + uint8_t rsp[mp::Protocol::MaxResponseSize()]; uint16_t value2; bool accepted = ReadRegister(rq.value, value2); uint8_t len = protocol.EncodeResponseRead(rq, accepted, value2, rsp); @@ -201,7 +171,7 @@ void Application::ReportReadRegister(const mp::RequestMsg &rq) { } void Application::ReportWriteRegister(const mp::RequestMsg &rq) { - uint8_t rsp[maxMsgLen]; + uint8_t rsp[mp::Protocol::MaxResponseSize()]; mp::ResponseMsgParamCodes ar = WriteRegister(rq.value, rq.value2) ? mp::ResponseMsgParamCodes::Accepted : mp::ResponseMsgParamCodes::Rejected; uint8_t len = protocol.EncodeResponseCmdAR(rq, ar, rsp); modules::serial::WriteToUSART(rsp, len); diff --git a/src/application.h b/src/application.h index aba5218..a8cf10e 100644 --- a/src/application.h +++ b/src/application.h @@ -26,7 +26,9 @@ public: uint8_t CurrentProgressCode(); uint16_t CurrentErrorCode(); +#ifndef UNITTEST private: +#endif /// Checks if the MMU can enter manual mode (user can move the selector with buttons) /// The MMU enters idle mode after 5s from the last command finished and there must be no filament present in the selector. void CheckManualOperation(); @@ -40,7 +42,6 @@ private: mp::ResponseCommandStatus RunningCommandStatus() const; void ReportCommandAccepted(const mp::RequestMsg &rq, mp::ResponseMsgParamCodes status); void ReportFINDA(const mp::RequestMsg &rq); - void ReportVersion(const mp::RequestMsg &rq); void ReportRunningCommand(); void ReportReadRegister(const mp::RequestMsg &rq); void ReportWriteRegister(const mp::RequestMsg &rq); diff --git a/src/modules/protocol.cpp b/src/modules/protocol.cpp index 13fe598..d051598 100644 --- a/src/modules/protocol.cpp +++ b/src/modules/protocol.cpp @@ -273,10 +273,6 @@ uint8_t Protocol::EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaVa return EncodeResponseRead(msg, true, findaValue, txbuff); } -uint8_t Protocol::EncodeResponseVersion(const RequestMsg &msg, uint16_t value, uint8_t *txbuff) { - return EncodeResponseRead(msg, true, value, txbuff); -} - uint8_t Protocol::EncodeResponseQueryOperation(const RequestMsg &msg, ResponseCommandStatus rcs, uint8_t *txbuff) { const ResponseMsg rsp(msg, rcs.code, rcs.value); uint8_t i = BeginEncodeRequest(msg, txbuff); diff --git a/src/modules/protocol.h b/src/modules/protocol.h index e157ecd..434c5ad 100644 --- a/src/modules/protocol.h +++ b/src/modules/protocol.h @@ -180,13 +180,6 @@ public: /// @returns number of bytes written into txbuff static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff); - /// Encode response to Version query - /// @param msg source request message for this response - /// @param value version number (0-255) - /// @param txbuff where to format the message - /// @returns number of bytes written into txbuff - static uint8_t EncodeResponseVersion(const RequestMsg &msg, uint16_t value, uint8_t *txbuff); - /// Encode response to Query operation status /// @param msg source request message for this response /// @param code status of operation (Processing, Error, Finished) diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 51c5944..153b522 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -26,3 +26,5 @@ set(LOGIC_STUBS_DIR ${CMAKE_SOURCE_DIR}/tests/unit/logic/stubs) add_subdirectory(hal) add_subdirectory(logic) add_subdirectory(modules) + +add_subdirectory(application) diff --git a/tests/unit/application/CMakeLists.txt b/tests/unit/application/CMakeLists.txt new file mode 100644 index 0000000..bf16d94 --- /dev/null +++ b/tests/unit/application/CMakeLists.txt @@ -0,0 +1,57 @@ +# define the test executable +add_executable( + application_tests + ${CMAKE_SOURCE_DIR}/src/registers.cpp + ${CMAKE_SOURCE_DIR}/src/application.cpp + ${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp + ${CMAKE_SOURCE_DIR}/src/modules/leds.cpp + ${CMAKE_SOURCE_DIR}/src/modules/globals.cpp + ${CMAKE_SOURCE_DIR}/src/modules/finda.cpp + ${CMAKE_SOURCE_DIR}/src/modules/debouncer.cpp + ${CMAKE_SOURCE_DIR}/src/modules/fsensor.cpp + ${CMAKE_SOURCE_DIR}/src/modules/idler.cpp + ${CMAKE_SOURCE_DIR}/src/modules/movable_base.cpp + ${CMAKE_SOURCE_DIR}/src/modules/permanent_storage.cpp + ${CMAKE_SOURCE_DIR}/src/modules/protocol.cpp + ${CMAKE_SOURCE_DIR}/src/modules/pulley.cpp + ${CMAKE_SOURCE_DIR}/src/modules/selector.cpp + ${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp + ${CMAKE_SOURCE_DIR}/src/modules/pulse_gen.cpp + ${MODULES_STUBS_DIR}/stub_adc.cpp + ${MODULES_STUBS_DIR}/stub_cpu.cpp + ${MODULES_STUBS_DIR}/stub_eeprom.cpp + ${MODULES_STUBS_DIR}/stub_gpio.cpp + ${MODULES_STUBS_DIR}/stub_shr16.cpp + ${MODULES_STUBS_DIR}/stub_serial.cpp + ${MODULES_STUBS_DIR}/stub_timebase.cpp + ${MODULES_STUBS_DIR}/stub_tmc2130.cpp + ${LOGIC_STUBS_DIR}/homing.cpp + ${LOGIC_STUBS_DIR}/main_loop_stub.cpp + ${LOGIC_STUBS_DIR}/stub_motion.cpp + ${CMAKE_SOURCE_DIR}/src/logic/no_command.cpp + ${CMAKE_SOURCE_DIR}/src/logic/command_base.cpp + ${CMAKE_SOURCE_DIR}/src/logic/cut_filament.cpp + ${CMAKE_SOURCE_DIR}/src/logic/load_filament.cpp + ${CMAKE_SOURCE_DIR}/src/logic/move_selector.cpp + ${CMAKE_SOURCE_DIR}/src/logic/no_command.cpp + ${CMAKE_SOURCE_DIR}/src/logic/eject_filament.cpp + ${CMAKE_SOURCE_DIR}/src/logic/tool_change.cpp + ${CMAKE_SOURCE_DIR}/src/logic/unload_filament.cpp + ${CMAKE_SOURCE_DIR}/src/logic/home.cpp + ${CMAKE_SOURCE_DIR}/src/logic/set_mode.cpp + ${CMAKE_SOURCE_DIR}/src/logic/feed_to_finda.cpp + ${CMAKE_SOURCE_DIR}/src/logic/feed_to_bondtech.cpp + ${CMAKE_SOURCE_DIR}/src/logic/retract_from_finda.cpp + ${CMAKE_SOURCE_DIR}/src/logic/unload_to_finda.cpp + test_registers.cpp + test_application.cpp + ) + +# define required search paths +target_include_directories( + application_tests PUBLIC ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/modules + ${CMAKE_SOURCE_DIR}/src/hal + ) + +# tell build system about the test case +add_catch_test(application_tests) diff --git a/tests/unit/application/test_application.cpp b/tests/unit/application/test_application.cpp new file mode 100644 index 0000000..17f5997 --- /dev/null +++ b/tests/unit/application/test_application.cpp @@ -0,0 +1,13 @@ +#include "catch2/catch.hpp" +#include "application.h" +#include +#include "../modules/stubs/stub_serial.h" + +TEST_CASE("application::ReportVersion", "[application]") { + modules::serial::ClearRX(); + modules::serial::ClearTX(); + + application.ReportReadRegister(mp::RequestMsg(mp::RequestMsgCodes::Version, 0)); + + REQUIRE(modules::serial::tx == "S0 A2*54\n"); +} diff --git a/tests/unit/application/test_registers.cpp b/tests/unit/application/test_registers.cpp new file mode 100644 index 0000000..5958966 --- /dev/null +++ b/tests/unit/application/test_registers.cpp @@ -0,0 +1,27 @@ +#include "catch2/catch.hpp" +#include "registers.h" +#include "modules/globals.h" +#include "../modules/stubs/stub_eeprom.h" +#include + +TEST_CASE("registers::read", "[registers]") { + uint16_t reg; + REQUIRE(ReadRegister(0, reg)); + REQUIRE(reg == PROJECT_VERSION_MAJOR); + + REQUIRE(ReadRegister(1, reg)); + REQUIRE(reg == PROJECT_VERSION_MINOR); + + REQUIRE(ReadRegister(2, reg)); + REQUIRE(reg == PROJECT_VERSION_REV); + + REQUIRE(ReadRegister(3, reg)); + REQUIRE(reg == PROJECT_BUILD_NUMBER); + + // set some MMU errors + hal::eeprom::ClearEEPROM(); + REQUIRE(mg::globals.DriveErrors() == 0); + mg::globals.IncDriveErrors(); + REQUIRE(ReadRegister(4, reg)); + REQUIRE(reg == 1); +} diff --git a/tests/unit/modules/protocol/test_protocol.cpp b/tests/unit/modules/protocol/test_protocol.cpp index 62d2608..130db60 100644 --- a/tests/unit/modules/protocol/test_protocol.cpp +++ b/tests/unit/modules/protocol/test_protocol.cpp @@ -246,7 +246,7 @@ TEST_CASE("protocol::EncodeResponseVersion", "[protocol]") { for (uint32_t version = 0; version < 0xffff; ++version) { TXBuff txbuff; mp::ResponseMsg rsp(requestMsg, mp::ResponseMsgParamCodes::Accepted, (uint16_t)version); - uint8_t msglen = mp::Protocol::EncodeResponseVersion(requestMsg, (uint16_t)version, txbuff.data()); + uint8_t msglen = mp::Protocol::EncodeResponseRead(requestMsg, true, (uint16_t)version, txbuff.data()); REQUIRE(msglen < mp::Protocol::MaxResponseSize()); std::string crc = MakeCRC(rsp.CRC()); diff --git a/tests/unit/modules/stubs/stub_serial.cpp b/tests/unit/modules/stubs/stub_serial.cpp index c44a73b..b818c9b 100644 --- a/tests/unit/modules/stubs/stub_serial.cpp +++ b/tests/unit/modules/stubs/stub_serial.cpp @@ -1,13 +1,36 @@ #include "serial.h" +#include "stub_serial.h" namespace modules { namespace serial { -bool WriteToUSART(const uint8_t *src, uint8_t len) { return false; } +SerialBuff tx; +SerialBuff rx; -bool Available() { return false; } +bool WriteToUSART(const uint8_t *src, uint8_t len) { + std::copy(src, src + len, std::back_inserter(tx)); + return true; +} -uint8_t ConsumeByte() { return 0; } +bool Available() { + return !rx.empty(); +} + +uint8_t ConsumeByte() { + if (rx.empty()) + return 0xff; + uint8_t rv = rx.front(); + rx.erase(0); + return rv; +} + +void ClearRX() { + rx.clear(); +} + +void ClearTX() { + tx.clear(); +} } // namespace serial } // namespace modules diff --git a/tests/unit/modules/stubs/stub_serial.h b/tests/unit/modules/stubs/stub_serial.h new file mode 100644 index 0000000..97c468a --- /dev/null +++ b/tests/unit/modules/stubs/stub_serial.h @@ -0,0 +1,17 @@ +#pragma once +#include +#include + +namespace modules { +namespace serial { + +using SerialBuff = std::string; + +extern SerialBuff tx; +extern SerialBuff rx; + +void ClearRX(); +void ClearTX(); + +} // namespace serial +} // namespace modules