From ed217387a4118afca631d85857d42eaa96006989 Mon Sep 17 00:00:00 2001 From: Richard Peters Date: Fri, 6 Dec 2024 12:42:27 +0100 Subject: [PATCH] test: add integration_test.flash_tested (#293) * Add cucumber submodule * Add integration_test/test * .github/workflows/ci.yml: Checkout submodules * Update amp-embedded-infra-lib * Update amp-embedded-infra-lib: fix: infra/util/Endian: fix comparison against C++ version * Update amp-cucumber-cpp-runner-poc * .github/workflows/ci.yml: Remove Visual Studio 2019 and gcc 7 from tested compilers since they can't handle C++20 * Do some work on integration tests * Various fixes * Fix compilation * Run clang-format * Update .github/workflows/ci.yml Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update devcontainer * Exclude gherkin libraries from all target * feat!: update MessageCommunication to Sesame * integration_test/test/FixtureEcho: Adapt for Sesame * CMakeLists: Don't set EXCLUDE_FROM_ALL on gherkin targets because otherwise they fail to install * integration_test/logic/Gpio: Differentiate between GpioTester and GpioTested's GpioChanged * integration_test/tested,tester/Main: Add tracing infrastructure * chore: add integration test board pcb (cherry picked from commit f20dc01301542bed2334d23807889cddae545de0) * integration_test/logic/Gpio: Fix order of RequestSend and setting sending * integration_test: Use UartStmDuplexDma * CMakeLists: Update amp-embedded-infralib * integration_test/{tester,tested}/Main: Add missing include * integration_test/{tester,tested}: Add tracing on ECHO calls * integration_test/test: Update and fix * Update amp-cucumber-cpp-runner-poc * Update amp-cucumber-cpp-runner * Change amp-cucumber-cpp-runner-poc to amp-cucumber-cpp-runner * Update amp-cucumber-cpp-runner * CMakeLists: Rename amp-cucumber-cpp-runner-poc to amp-cucumber-cpp-runner * launch.json: Set gdbPath to gdb-multiarch * Apply clang-format * Update amp-embedded-infralib, reset colour in GlobalTracer * integration_test: Reset tested before starting a scenario * Update amp-cucumber-cpp-runner * integration_test/test: Run tests and EventDispatcher from single thread * Remove integration_test/test/FixtureSystemChanges * Move EventDispatcherThreadAware to amp-embedded-infra-lib * integration_test: Add UART test * integration_test/test/Hooks: Get serial port to use from command line arguments * integration_test/test/FixtureEcho: Support Unix serial ports * Extract FixtureEchoSerial from FixtureEcho * integration_test/test/FixtureEcho: Refactor FixtureEchoSerial * integration_test/test/FixtureEcho: Add EchoClientWebSocket * Add integration_test/test/features/uart_duplex_dma.feature * Update amp-cucumber-cpp-runner * Rename integration_test.test to integration_test.runner * integration_test/tested: Add main for stm32wb55 * integration_test/runner/FixtureEcho: Add EchoClientTcp * integration_test: Adjust for DMA refactoring (cherry picked from commit 14689d2b08c4ba89e091c3dd0bdc9645247f100a) * .github/workflows/ci.yml: fix merge mistake * CMakeLists: Only build integration_test when building amp-hal-st standalone * test: add integration_test.flash_tested * integration_test/flash_tested/Flash: Reduce lambda context size * Enable running tests on GitHub * Update amp-embedded-infra-lib * integration_test/logic/Tester: Add Ping * Fix merge conflict * Process review comments * Update amp-embedded-infra-lib * Update amp-cucumber-cpp-runner * Update amp-cucumber-cpp-runner * Update amp-cucumber-cpp-runner * Move Flash into integration_test/logic * Update amp-cucumber-cpp-runner * Use EXPECT_TRUE around infra::WaitUntilDone and infra::WaitFor * Disable compilation for stm32wb because it doesn't have Port::F * Update amp-cucumber-cpp-runner * Update .github/workflows/ci.yml Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Temporarily add amp-embedded-infra-lib as submodule * Add integration_test/flasher * Use submodule amp-embedded-infra-lib * Fix merge mistakes * Update for merge --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Ron <45816308+rjaegers@users.noreply.github.com> --- .github/workflows/ci.yml | 28 +-- .gitmodules | 0 CMakeLists.txt | 12 ++ CMakePresets.json | 9 +- hal_st/stm32fxxx/FlashInternalStm.cpp | 2 +- hal_st/stm32fxxx/FlashInternalStm.hpp | 4 +- integration_test/CMakeLists.txt | 1 + integration_test/flasher/CMakeLists.txt | 21 ++ integration_test/flasher/Main.cpp | 130 +++++++++++++ integration_test/logic/CMakeLists.txt | 5 + integration_test/logic/Flash.cpp | 183 ++++++++++++++++++ integration_test/logic/Flash.hpp | 80 ++++++++ integration_test/logic/Flash.proto | 46 +++++ integration_test/logic/Tester.cpp | 74 +++++-- integration_test/logic/Tester.hpp | 34 +++- integration_test/logic/Testing.proto | 42 +++- integration_test/logic/test/CMakeLists.txt | 13 ++ integration_test/logic/test/TestFlash.cpp | 142 ++++++++++++++ integration_test/runner/CMakeLists.txt | 11 +- integration_test/runner/FixtureEcho.cpp | 79 -------- integration_test/runner/FixtureEcho.hpp | 84 +------- integration_test/runner/Hooks.cpp | 108 +++-------- integration_test/runner/Main.cpp | 10 + integration_test/runner/StepsGpio.cpp | 16 +- integration_test/runner/StepsUart.cpp | 22 +-- integration_test/tested/CMakeLists.txt | 2 + integration_test/tested/EchoFromTester.hpp | 2 +- integration_test/tester/CMakeLists.txt | 3 + integration_test/tester/EchoFromCloud.hpp | 7 +- .../tester/ForwardingEchoToTested.hpp | 12 +- integration_test/tester/Main.cpp | 9 +- integration_test/tester/Tester.cpp | 16 +- integration_test/tester/Tester.hpp | 51 ++++- services/st_util/CMakeLists.txt | 5 +- 34 files changed, 948 insertions(+), 315 deletions(-) create mode 100644 .gitmodules create mode 100644 integration_test/flasher/CMakeLists.txt create mode 100644 integration_test/flasher/Main.cpp create mode 100644 integration_test/logic/Flash.cpp create mode 100644 integration_test/logic/Flash.hpp create mode 100644 integration_test/logic/Flash.proto create mode 100644 integration_test/logic/test/CMakeLists.txt create mode 100644 integration_test/logic/test/TestFlash.cpp create mode 100644 integration_test/runner/Main.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98aa562d..b8680119 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,19 +27,19 @@ jobs: with: configurePreset: "host" buildPreset: "host-Debug-WithPackage" - #testPreset: "host" + testPreset: "host" configurePresetAdditionalArgs: "['-DCMAKE_C_COMPILER_LAUNCHER=sccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=sccache']" - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: hal_st path: build/host/hal_st-*-Linux.tar.gz if-no-files-found: error - #- name: Upload test logs - # if: ${{ failure() }} - # uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - # with: - # name: test-logs - # path: build/host/Testing/Temporary/ + - name: Upload test logs + if: ${{ failure() }} + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + with: + name: test-logs + path: build/host/Testing/Temporary/ host_build_test: name: Host Build & Test runs-on: ${{ matrix.os }} @@ -58,14 +58,14 @@ jobs: with: configurePreset: "host-single-Debug" buildPreset: "host-single-Debug" - #testPreset: "host-single-Debug" + testPreset: "host-single-Debug" configurePresetAdditionalArgs: "['-DCMAKE_C_COMPILER_LAUNCHER=sccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=sccache']" - #- name: Upload test logs - # if: ${{ failure() }} - # uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - # with: - # name: test-logs - # path: build/host/Testing/Temporary/ + - name: Upload test logs + if: ${{ failure() }} + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + with: + name: test-logs + path: build/host/Testing/Temporary/ embedded_build: name: Embedded Build runs-on: ubuntu-latest diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..e69de29b diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e38ea11..874d89de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,12 +5,19 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) endif() option(CMAKE_COMPILE_WARNING_AS_ERROR "Enable warnings-as-error" ON) +option(HALST_BUILD_TESTS "Enable building the tests" Off) option(HALST_INCLUDE_DEFAULT_INIT "Include default initialization code; turn off when providing custom initialization" ON) option(HALST_BUILD_EXAMPLES "Enable build of the examples" OFF) option(HALST_BUILD_EXAMPLES_FREERTOS "Enable build of the FreeRTOS example" OFF) set(HALST_XML_GPIO "" CACHE STRING "XML GPIO table") set(HALST_XML_STM32 "" CACHE STRING "XML STM32 table") +if (HALST_BUILD_TESTS) + # CTest cannot be included before the first project() statement, but amp-embedded-infa-lib + # needs to see that test utilities need to be built. + set(BUILD_TESTING On) +endif() + if (HALST_STANDALONE) set(EMIL_INCLUDE_FREERTOS ${HALST_BUILD_EXAMPLES_FREERTOS}) @@ -49,6 +56,11 @@ else() set(HALST_EXCLUDE_FROM_ALL "EXCLUDE_FROM_ALL") endif() +if (HALST_BUILD_TESTS) + include(CTest) + emil_enable_testing() +endif() + add_subdirectory(st) add_subdirectory(hal_st) add_subdirectory(hal_st_lwip) diff --git a/CMakePresets.json b/CMakePresets.json index 23b62526..18c0e5df 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -17,8 +17,7 @@ "inherits": "defaults", "cacheVariables": { "CMAKE_CONFIGURATION_TYPES": "Debug;Release;RelWithDebInfo;MinSizeRel", - "EMIL_BUILD_ECHO_COMPILERS": true, - "EMIL_FETCH_ECHO_COMPILERS": false + "HALST_BUILD_TESTS": true }, "generator": "Ninja Multi-Config" }, @@ -27,7 +26,8 @@ "displayName": "Configuration for Host Tooling and Tests, Single Config Generator, Debug", "inherits": "defaults", "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug" + "CMAKE_BUILD_TYPE": "Debug", + "HALST_BUILD_TESTS": true } }, { @@ -35,7 +35,8 @@ "displayName": "Configuration for Host Tooling and Tests, Single Config Generator, MinSizeRel", "inherits": "defaults", "cacheVariables": { - "CMAKE_BUILD_TYPE": "MinSizeRel" + "CMAKE_BUILD_TYPE": "MinSizeRel", + "HALST_BUILD_TESTS": true } }, { diff --git a/hal_st/stm32fxxx/FlashInternalStm.cpp b/hal_st/stm32fxxx/FlashInternalStm.cpp index e6321652..db113d00 100644 --- a/hal_st/stm32fxxx/FlashInternalStm.cpp +++ b/hal_st/stm32fxxx/FlashInternalStm.cpp @@ -131,7 +131,7 @@ namespace hal infra::EventDispatcher::Instance().Schedule(onDone); } - FlashInternalStm::FlashInternalStm(infra::MemoryRange sectorSizes, infra::ConstByteRange flashMemory) + FlashInternalStm::FlashInternalStm(infra::MemoryRange sectorSizes, infra::ConstByteRange flashMemory) : FlashInternalStmBase(flashMemory) , sectorSizes(sectorSizes) {} diff --git a/hal_st/stm32fxxx/FlashInternalStm.hpp b/hal_st/stm32fxxx/FlashInternalStm.hpp index e92fbf18..40c05c31 100644 --- a/hal_st/stm32fxxx/FlashInternalStm.hpp +++ b/hal_st/stm32fxxx/FlashInternalStm.hpp @@ -26,7 +26,7 @@ namespace hal : public FlashInternalStmBase { public: - FlashInternalStm(infra::MemoryRange sectorSizes, infra::ConstByteRange flashMemory); + FlashInternalStm(infra::MemoryRange sectorSizes, infra::ConstByteRange flashMemory); uint32_t NumberOfSectors() const override; uint32_t SizeOfSector(uint32_t sectorIndex) const override; @@ -34,7 +34,7 @@ namespace hal uint32_t AddressOfSector(uint32_t sectorIndex) const override; private: - infra::MemoryRange sectorSizes; + infra::MemoryRange sectorSizes; }; class FlashHomogeneousInternalStm diff --git a/integration_test/CMakeLists.txt b/integration_test/CMakeLists.txt index 4373ce9d..1fe2f3f0 100644 --- a/integration_test/CMakeLists.txt +++ b/integration_test/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory(logic) add_subdirectory(tested) add_subdirectory(tester) add_subdirectory(runner) +add_subdirectory(flasher) diff --git a/integration_test/flasher/CMakeLists.txt b/integration_test/flasher/CMakeLists.txt new file mode 100644 index 00000000..a17b6700 --- /dev/null +++ b/integration_test/flasher/CMakeLists.txt @@ -0,0 +1,21 @@ +add_executable(integration_test.flasher) +emil_build_for(integration_test.flasher HOST All) + +target_sources(integration_test.flasher PRIVATE + Main.cpp +) + +target_link_libraries(integration_test.flasher PRIVATE + args + integration_test.logic + hal.generic + services.network_instantiations +) + +if (EMIL_BUILD_WIN) + target_link_libraries(integration_test.flasher PRIVATE hal.windows) +endif() + +if (EMIL_BUILD_UNIX OR EMIL_BUILD_DARWIN) + target_link_libraries(integration_test.flasher PRIVATE hal.unix) +endif() diff --git a/integration_test/flasher/Main.cpp b/integration_test/flasher/Main.cpp new file mode 100644 index 00000000..ec5cb07e --- /dev/null +++ b/integration_test/flasher/Main.cpp @@ -0,0 +1,130 @@ +#include "args.hxx" +#include "generated/echo/Testing.pb.hpp" +#include "generated/echo/TracingFlash.pb.hpp" +#include "generated/echo/TracingTesting.pb.hpp" +#include "hal/generic/FileSystemGeneric.hpp" +#include "hal/generic/TimerServiceGeneric.hpp" +#include "integration_test/logic/Flash.hpp" +#include "services/network_instantiations/EchoInstantiation.hpp" +#include "services/network_instantiations/NetworkAdapter.hpp" +#include "services/tracer/GlobalTracer.hpp" +#include "services/tracer/TracerOnIoOutputInfrastructure.hpp" + +namespace +{ + const std::array stm32f767SectorSizes{ { 32 * 1024, + 32 * 1024, + 32 * 1024, + 32 * 1024, + 128 * 1024, + 256 * 1024, + 256 * 1024, + 256 * 1024, + 256 * 1024, + 256 * 1024, + 256 * 1024, + 256 * 1024 } }; +} + +class FirmwareSender +{ +public: + FirmwareSender(const std::vector& firmware, services::Echo& echo) + : firmware(firmware) + , flash(echo, infra::MakeRange(stm32f767SectorSizes)) + , tester(echo) + { + tester.RequestSend([this]() + { + tester.SetTestedMode(testing::TestedMode::reset); + tester.RequestSend([this]() + { + tester.SetTestedMode(testing::TestedMode::programming); + + services::GlobalTracer().Trace() << "Erasing chip..."; + flash.EraseAll([this]() + { + services::GlobalTracer().Trace() << "Writing firmware..."; + flash.WriteBuffer(infra::MakeRange(this->firmware), 0, [this]() + { + services::GlobalTracer().Trace() << "Uploading done"; + done = true; + }); + }); + }); + }); + } + + bool Done() const + { + return done; + } + +private: + std::vector firmware; + application::FlashProxy flash; + testing::TesterProxy tester; + bool done = false; + + infra::TimerSingleShot timeoutTimer{ std::chrono::minutes(2), [this]() + { + done = true; + } }; +}; + +struct FlashTracer +{ + FlashTracer(services::TracingEchoOnStreams& echoTracer) + : testerTracer(echoTracer) + , testerObserverTracer(echoTracer) + , flashTracer(echoTracer) + , flashResultTracer(echoTracer) + {} + + testing::TesterTracer testerTracer; + testing::TesterObserverTracer testerObserverTracer; + flash::FlashTracer flashTracer; + flash::FlashResultTracer flashResultTracer; +}; + +int main(int argc, char** argv) +{ + args::ArgumentParser parser("Flasher"); + args::Group positionals(parser, "Positional arguments:"); + args::Positional targetArgument(positionals, "target", "COM port or hostname", args::Options::Required); + args::Positional firmwareArgument(positionals, "firmware", "Binary firmware with which the target attached to Postmaster is upgraded"); + args::HelpFlag help(parser, "help", "display this help menu.", { 'h', "help" }); + + try + { + parser.ParseCLI(argc, argv); + + static hal::TimerServiceGeneric timerService; + static main_::TracerOnIoOutputInfrastructure tracer; + static main_::NetworkAdapter network; + static hal::FileSystemGeneric fileSystem; + + auto firmware = firmwareArgument ? fileSystem.ReadBinaryFile(args::get(firmwareArgument)) : std::vector{}; + auto [echo, echoTracer] = application::OpenTracingEcho(args::get(targetArgument), network.ConnectionFactoryWithNameResolver(), tracer.tracer); + + FlashTracer flashTracer(*echoTracer); + FirmwareSender sender(firmware, *echo); + + network.ExecuteUntil([&]() + { + return sender.Done(); + }); + } + catch (const args::Help&) + { + std::cout << parser; + return 1; + } + catch (const std::exception& ex) + { + std::cout << ex.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/integration_test/logic/CMakeLists.txt b/integration_test/logic/CMakeLists.txt index 29cc26b7..813288b6 100644 --- a/integration_test/logic/CMakeLists.txt +++ b/integration_test/logic/CMakeLists.txt @@ -5,8 +5,11 @@ target_include_directories(integration_test.logic PUBLIC ) protocol_buffer_echo_cpp(integration_test.logic Testing.proto) +protocol_buffer_echo_cpp(integration_test.logic Flash.proto) target_sources(integration_test.logic PRIVATE + Flash.cpp + Flash.hpp Gpio.cpp Gpio.hpp Peripheral.cpp @@ -23,3 +26,5 @@ target_link_libraries(integration_test.logic PUBLIC services.util protobuf.echo ) + +add_subdirectory(test) diff --git a/integration_test/logic/Flash.cpp b/integration_test/logic/Flash.cpp new file mode 100644 index 00000000..4c34fd07 --- /dev/null +++ b/integration_test/logic/Flash.cpp @@ -0,0 +1,183 @@ +#include "integration_test/logic/Flash.hpp" +#include + +namespace application +{ + Flash::Flash(services::Echo& echo, hal::Flash& flash) + : flash::Flash(echo) + , flashResult(echo) + , flash(flash) + {} + + + void Flash::Read(uint32_t address, uint32_t size) + { + flash.ReadBuffer(infra::Head(infra::MakeRange(buffer), size), address, [this, size]() + { + flashResult.RequestSend([this, size]() + { + flashResult.ReadDone(infra::Head(infra::MakeRange(buffer), size)); + MethodDone(); + }); + }); + } + + void Flash::Write(uint32_t address, infra::ConstByteRange contents) + { + flash.WriteBuffer(contents, address, [this]() + { + flashResult.RequestSend([this]() + { + flashResult.WriteDone(); + MethodDone(); + }); + }); + } + + void Flash::EraseSectors(uint32_t sector, uint32_t numberOfSectors) + { + flash.EraseSectors(sector, sector + numberOfSectors, [this]() + { + flashResult.RequestSend([this]() + { + flashResult.EraseSectorsDone(); + MethodDone(); + }); + }); + } + + FlashProxy::FlashProxy(services::Echo& echo, infra::MemoryRange sectorSizes) + : flash::FlashResult(echo) + , sectorSizes(sectorSizes) + , proxy(echo) + {} + + uint32_t FlashProxy::NumberOfSectors() const + { + return sectorSizes.size(); + } + + uint32_t FlashProxy::SizeOfSector(uint32_t sectorIndex) const + { + return sectorSizes[sectorIndex]; + } + + uint32_t FlashProxy::SectorOfAddress(uint32_t address) const + { + uint32_t totalSize = 0; + for (uint32_t sector = 0; sector != sectorSizes.size(); ++sector) + { + totalSize += sectorSizes[sector]; + if (address < totalSize) + return sector; + } + + assert(address == totalSize); + return sectorSizes.size(); + } + + uint32_t FlashProxy::AddressOfSector(uint32_t sectorIndex) const + { + uint32_t address = 0; + for (uint32_t sector = 0; sector != sectorIndex; ++sector) + address += sectorSizes[sector]; + return address; + } + + void FlashProxy::WriteBuffer(infra::ConstByteRange buffer, uint32_t address, infra::Function onDone) + { + writingBuffer = buffer; + this->onDone = onDone; + + if (!writingBuffer.empty()) + proxy.RequestSend([this, address]() + { + ++transferBuffers; + auto size = std::min(writingBuffer.size(), flash::WriteRequest::contentsSize); + proxy.Write(address, infra::Head(writingBuffer, size)); + WriteBuffer(infra::DiscardHead(writingBuffer, size), address + size, this->onDone.Clone()); + }); + } + + void FlashProxy::ReadBuffer(infra::ByteRange buffer, uint32_t address, infra::Function onDone) + { + readingBuffer = buffer; + this->onDone = onDone; + + ReadPartialBuffer(address, 0); + } + + void FlashProxy::EraseSectors(uint32_t beginIndex, uint32_t endIndex, infra::Function onDone) + { + this->onDone = onDone; + this->endIndex = endIndex; + + proxy.RequestSend([this, beginIndex]() + { + proxy.EraseSectors(beginIndex, this->endIndex - beginIndex); + }); + } + + void FlashProxy::ReadDone(infra::ConstByteRange contents) + { + infra::Copy(contents, infra::Head(readingBuffer, contents.size())); + readingBuffer = infra::DiscardHead(readingBuffer, contents.size()); + + --transferBuffers; + if (transferBuffers == 0 && readingBuffer.empty()) + onDone(); + } + + void FlashProxy::WriteDone() + { + --transferBuffers; + if (transferBuffers == 0 && writingBuffer.empty()) + onDone(); + } + + void FlashProxy::EraseSectorsDone() + { + onDone(); + } + + void FlashProxy::ReadPartialBuffer(uint32_t address, uint32_t start) + { + if (readingBuffer.size() - start > 0) + { + this->start = start; + proxy.RequestSend([this, address]() + { + ++transferBuffers; + auto size = std::min(readingBuffer.size() - this->start, flash::WriteRequest::contentsSize); + proxy.Read(address + this->start, size); + ReadPartialBuffer(address, this->start + size); + }); + } + } + + FlashHomogeneousProxy::FlashHomogeneousProxy(services::Echo& echo, uint32_t numberOfSectors, uint32_t sizeOfEachSector) + : FlashProxy(echo, {}) + , numberOfSectors(numberOfSectors) + , sizeOfEachSector(sizeOfEachSector) + {} + + uint32_t FlashHomogeneousProxy::NumberOfSectors() const + { + return numberOfSectors; + } + + uint32_t FlashHomogeneousProxy::SizeOfSector(uint32_t sectorIndex) const + { + return sizeOfEachSector; + } + + uint32_t FlashHomogeneousProxy::SectorOfAddress(uint32_t address) const + { + return address / sizeOfEachSector; + } + + uint32_t FlashHomogeneousProxy::AddressOfSector(uint32_t sectorIndex) const + { + return sectorIndex * sizeOfEachSector; + } +} diff --git a/integration_test/logic/Flash.hpp b/integration_test/logic/Flash.hpp new file mode 100644 index 00000000..ab42c49a --- /dev/null +++ b/integration_test/logic/Flash.hpp @@ -0,0 +1,80 @@ +#ifndef HAL_ST_INTEGRATION_TEST_FLASH_HPP +#define HAL_ST_INTEGRATION_TEST_FLASH_HPP + +#include "generated/echo/Flash.pb.hpp" +#include "hal/interfaces/FlashHomogeneous.hpp" +#include "infra/util/AutoResetFunction.hpp" + +namespace application +{ + class Flash + : public flash::Flash + { + public: + Flash(services::Echo& echo, hal::Flash& flash); + + // Implementation of flash::Flash + void Read(uint32_t address, uint32_t size) override; + void Write(uint32_t address, infra::ConstByteRange contents) override; + void EraseSectors(uint32_t sector, uint32_t numberOfSectors) override; + + private: + flash::FlashResultProxy flashResult; + hal::Flash& flash; + + std::array buffer; + }; + + class FlashProxy + : public hal::Flash + , private flash::FlashResult + { + public: + FlashProxy(services::Echo& echo, infra::MemoryRange sectorSizes); + + // Implementation of hal::Flash + uint32_t NumberOfSectors() const override; + uint32_t SizeOfSector(uint32_t sectorIndex) const override; + uint32_t SectorOfAddress(uint32_t address) const override; + uint32_t AddressOfSector(uint32_t sectorIndex) const override; + void WriteBuffer(infra::ConstByteRange buffer, uint32_t address, infra::Function onDone) override; + void ReadBuffer(infra::ByteRange buffer, uint32_t address, infra::Function onDone) override; + void EraseSectors(uint32_t beginIndex, uint32_t endIndex, infra::Function onDone) override; + + private: + // Implementation of flash::FlashResult + void ReadDone(infra::ConstByteRange contents) override; + void WriteDone() override; + void EraseSectorsDone() override; + + void ReadPartialBuffer(uint32_t address, uint32_t start); + + private: + infra::MemoryRange sectorSizes; + flash::FlashProxy proxy; + infra::AutoResetFunction onDone; + infra::ConstByteRange writingBuffer; + infra::ByteRange readingBuffer; + uint32_t transferBuffers = 0; + uint32_t start; + uint32_t endIndex; + }; + + class FlashHomogeneousProxy + : public FlashProxy + { + public: + FlashHomogeneousProxy(services::Echo& echo, uint32_t numberOfSectors, uint32_t sizeOfEachSector); + + uint32_t NumberOfSectors() const override; + uint32_t SizeOfSector(uint32_t sectorIndex) const override; + uint32_t SectorOfAddress(uint32_t address) const override; + uint32_t AddressOfSector(uint32_t sectorIndex) const override; + + private: + uint32_t numberOfSectors; + uint32_t sizeOfEachSector; + }; +} + +#endif diff --git a/integration_test/logic/Flash.proto b/integration_test/logic/Flash.proto new file mode 100644 index 00000000..8b315b62 --- /dev/null +++ b/integration_test/logic/Flash.proto @@ -0,0 +1,46 @@ +syntax = "proto3"; + +import "EchoAttributes.proto"; + +package flash; + +message ReadRequest +{ + uint32 address = 1; + uint32 size = 2; +} + +message ReadResponse +{ + bytes contents = 1 [(bytes_size) = 512]; +} + +message WriteRequest +{ + uint32 address = 1; + bytes contents = 2 [(bytes_size) = 512]; +} + +message EraseSectorsRequest +{ + uint32 sector = 1; + uint32 number_of_sectors = 2; +} + +service Flash +{ + option (service_id) = 50; + + rpc Read(ReadRequest) returns (Nothing) { option (method_id) = 1; } + rpc Write(WriteRequest) returns (Nothing) { option (method_id) = 2; } + rpc EraseSectors(EraseSectorsRequest) returns (Nothing) { option (method_id) = 3; } +} + +service FlashResult +{ + option (service_id) = 51; + + rpc ReadDone(ReadResponse) returns (Nothing) { option (method_id) = 1; } + rpc WriteDone(Nothing) returns (Nothing) { option (method_id) = 2; } + rpc EraseSectorsDone(Nothing) returns (Nothing) { option (method_id) = 3; } +} diff --git a/integration_test/logic/Tester.cpp b/integration_test/logic/Tester.cpp index f401086b..b8067900 100644 --- a/integration_test/logic/Tester.cpp +++ b/integration_test/logic/Tester.cpp @@ -2,24 +2,55 @@ namespace application { - Tester::Tester(services::Echo& echo, hal::GpioPin& resetTesterPin, services::EchoOnSesame& echoToTested) + Tester::Tester(services::Echo& echo, hal::GpioPin& resetTestedPin, EchoToTestedCreator& echoToTestedCreator, FlashTestedCreator& flashTestedCreator) : testing::Tester(echo) - , echoToTested(echoToTested) - , resetTester(resetTesterPin, true) + , echoToTestedCreator(echoToTestedCreator) + , resetTested(resetTestedPin, true) + , testerObserverProxy(echo) + , flashTestedCreator(flashTestedCreator) {} - void Tester::Reset() + void Tester::SetTestedMode(testing::TestedMode mode) { - resetTester.Set(false); - - Peripherals::Reset(); - echoToTested.Reset(); - - resetTimer.Start(std::chrono::milliseconds(10), [this]() - { - resetTester.Set(true); - MethodDone(); - }); + switch (mode) + { + case testing::TestedMode::reset: + resetTested.Set(false); + flash = infra::none; + Peripherals::Reset(); + echoToTested = infra::none; + testerObserverProxy.RequestSend([this]() + { + testerObserverProxy.TestedModeSet({}); + MethodDone(); + }); + break; + case testing::TestedMode::programming: + assert(!resetTested.GetOutputLatch()); + flash.Emplace(flashTestedCreator, Rpc(), [this](infra::BoundedConstString result) + { + this->result = result; + testerObserverProxy.RequestSend([this]() + { + testerObserverProxy.TestedModeSet(this->result); + MethodDone(); + }); + }); + resetTested.Set(true); + break; + case testing::TestedMode::active: + assert(!resetTested.GetOutputLatch()); + echoToTested.Emplace(echoToTestedCreator); + resetTested.Set(true); + testerObserverProxy.RequestSend([this]() + { + testerObserverProxy.TestedModeSet({}); + MethodDone(); + }); + break; + default: + std::abort(); + } } void Tester::EnablePeripheral(testing::Peripheral type) @@ -33,4 +64,19 @@ namespace application { return testing::Tester::Subject(); } + + TesterObserver::TesterObserver(services::Echo& echo) + : testing::TesterObserver(echo) + {} + + void TesterObserver::TestedModeSet(infra::BoundedConstString message) + { + receivedTestedModeSet = true; + MethodDone(); + } + + bool TesterObserver::ReceivedTestedModeSet() + { + return std::exchange(receivedTestedModeSet, false); + } } diff --git a/integration_test/logic/Tester.hpp b/integration_test/logic/Tester.hpp index 8ce40a78..c4bdddd0 100644 --- a/integration_test/logic/Tester.hpp +++ b/integration_test/logic/Tester.hpp @@ -4,6 +4,8 @@ #include "generated/echo/Testing.pb.hpp" #include "hal/interfaces/Gpio.hpp" #include "infra/timer/Timer.hpp" +#include "infra/util/ProxyCreator.hpp" +#include "integration_test/logic/Flash.hpp" #include "integration_test/logic/Peripheral.hpp" #include "services/util/EchoOnSesame.hpp" @@ -14,19 +16,41 @@ namespace application , public Peripherals { public: - Tester(services::Echo& echo, hal::GpioPin& resetTesterPin, services::EchoOnSesame& echoToTested); + using FlashTestedCreator = infra::CreatorBase& onDone)>; + using EchoToTestedCreator = infra::CreatorBase; + + Tester(services::Echo& echo, hal::GpioPin& resetTestedPin, EchoToTestedCreator& echoToTestedCreator, FlashTestedCreator& flashTestedCreator); // Implementation of Tester - void Reset() override; + void SetTestedMode(testing::TestedMode mode) override; void EnablePeripheral(testing::Peripheral type) override; // Implementation of Peripherals services::Echo& GetEcho() const override; private: - services::EchoOnSesame& echoToTested; - hal::OutputPin resetTester; - infra::TimerSingleShot resetTimer; + EchoToTestedCreator& echoToTestedCreator; + infra::Optional> echoToTested; + hal::OutputPin resetTested; + testing::TesterObserverProxy testerObserverProxy; + FlashTestedCreator& flashTestedCreator; + infra::Optional> flash; + infra::BoundedConstString result; + }; + + class TesterObserver + : public testing::TesterObserver + { + public: + TesterObserver(services::Echo& echo); + + // Implementation of TesterObserver + void TestedModeSet(infra::BoundedConstString message) override; + + bool ReceivedTestedModeSet(); + + private: + bool receivedTestedModeSet = false; }; } diff --git a/integration_test/logic/Testing.proto b/integration_test/logic/Testing.proto index 5cecadb1..20dfcc27 100644 --- a/integration_test/logic/Testing.proto +++ b/integration_test/logic/Testing.proto @@ -26,46 +26,70 @@ message PeripheralType Peripheral peripheral = 1; } +enum TestedMode +{ + reset = 0; + active = 1; + programming = 2; +} + +message TestedModeMessage +{ + TestedMode mode = 1; +} + +message StringMessage +{ + string message = 1 [(string_size) = 64]; +} + service Tester { option (service_id) = 1; - rpc Reset(Nothing) returns (Nothing) { option (method_id) = 1; } + rpc SetTestedMode(TestedModeMessage) returns (Nothing) { option (method_id) = 1; } rpc EnablePeripheral(PeripheralType) returns (Nothing) { option (method_id) = 2; } } -service Tested +service TesterObserver { option (service_id) = 2; + rpc TestedModeSet(StringMessage) returns (Nothing) { option (method_id) = 1; } +} + +service Tested +{ + option (service_id) = 3; + rpc Ping(Nothing) returns (Nothing) { option (method_id) = 1; } rpc EnablePeripheral(PeripheralType) returns (Nothing) { option (method_id) = 2; } } service TestedObserver { - option (service_id) = 3; + option (service_id) = 4; rpc Pong(Nothing) returns (Nothing) { option (method_id) = 1; } } service GpioTester { - option (service_id) = 4; + option (service_id) = 5; rpc SetGpio(GpioState) returns (Nothing) { option (method_id) = 1; } } service GpioTested { - option (service_id) = 5; + option (service_id) = 6; rpc SetGpio(GpioState) returns (Nothing) { option (method_id) = 1; } } service GpioObserver { - option (service_id) = 6; + option (service_id) = 7; rpc TesterGpioChanged(GpioState) returns (Nothing) { option (method_id) = 1; } rpc TestedGpioChanged(GpioState) returns (Nothing) { option (method_id) = 2; } @@ -73,21 +97,21 @@ service GpioObserver service UartTester { - option (service_id) = 7; + option (service_id) = 8; rpc SendData(Data) returns (Nothing) { option (method_id) = 1; } } service UartTested { - option (service_id) = 8; + option (service_id) = 9; rpc SendData(Data) returns (Nothing) { option (method_id) = 1; } } service UartObserver { - option (service_id) = 9; + option (service_id) = 10; rpc TesterReceivedData(Data) returns (Nothing) { option (method_id) = 1; } rpc TestedReceivedData(Data) returns (Nothing) { option (method_id) = 2; } diff --git a/integration_test/logic/test/CMakeLists.txt b/integration_test/logic/test/CMakeLists.txt new file mode 100644 index 00000000..d89fed10 --- /dev/null +++ b/integration_test/logic/test/CMakeLists.txt @@ -0,0 +1,13 @@ +add_executable(integration_test.logic.test) +emil_build_for(integration_test.logic.test BOOL HALST_BUILD_TESTS) +emil_add_test(integration_test.logic.test) + +target_link_libraries(integration_test.logic.test PUBLIC + gmock_main + integration_test.logic + protobuf.test_doubles +) + +target_sources(integration_test.logic.test PRIVATE + TestFlash.cpp +) diff --git a/integration_test/logic/test/TestFlash.cpp b/integration_test/logic/test/TestFlash.cpp new file mode 100644 index 00000000..6c76ad6d --- /dev/null +++ b/integration_test/logic/test/TestFlash.cpp @@ -0,0 +1,142 @@ +#include "hal/interfaces/test_doubles/FlashMock.hpp" +#include "infra/util/test_helper/MockCallback.hpp" +#include "infra/util/test_helper/MockHelpers.hpp" +#include "integration_test/logic/Flash.hpp" +#include "protobuf/echo/test_doubles/EchoMock.hpp" +#include "protobuf/echo/test_doubles/EchoSingleLoopback.hpp" +#include "gtest/gtest.h" + +namespace +{ + class FlashMock + : public flash::Flash + { + public: + using flash::Flash::Flash; + + MOCK_METHOD(void, Read, (uint32_t address, uint32_t size), (override)); + MOCK_METHOD(void, Write, (uint32_t address, infra::ConstByteRange contents), (override)); + MOCK_METHOD(void, EraseSectors, (uint32_t sector, uint32_t number_of_sectors), (override)); + }; + + class FlashResultMock + : public flash::FlashResult + { + public: + using flash::FlashResult::FlashResult; + + MOCK_METHOD(void, ReadDone, (infra::ConstByteRange contents), (override)); + MOCK_METHOD(void, WriteDone, (), (override)); + MOCK_METHOD(void, EraseSectorsDone, (), (override)); + }; +} + +class FlashTest + : public testing::Test +{ +public: + services::MethodSerializerFactory::OnHeap serializerFactory; + application::EchoSingleLoopback echo{ serializerFactory }; + testing::StrictMock delegate; + application::Flash flash{ echo, delegate }; + testing::StrictMock flashResult{ echo }; + + const std::array data{ 5, 8, 2, 3 }; + infra::Function onDone; +}; + +TEST_F(FlashTest, Read) +{ + EXPECT_CALL(delegate, ReadBuffer(testing::_, 1234, testing::_)).WillOnce(testing::Invoke([&](infra::ByteRange buffer, uint32_t address, infra::Function onReadDone) + { + infra::Copy(infra::MakeRange(data), buffer); + onDone = onReadDone; + })); + flash.Read(1234, data.size()); + + EXPECT_CALL(flashResult, ReadDone(infra::CheckByteRangeContents(infra::MakeRange(data)))); + onDone(); +} + +TEST_F(FlashTest, Write) +{ + EXPECT_CALL(delegate, WriteBuffer(infra::CheckByteRangeContents(infra::MakeRange(data)), 1234, testing::_)).WillOnce(testing::Invoke([&](infra::ConstByteRange buffer, uint32_t address, infra::Function onReadDone) + { + onDone = onReadDone; + })); + flash.Write(1234, data); + + EXPECT_CALL(flashResult, WriteDone()); + onDone(); +} + +TEST_F(FlashTest, EraseSectors) +{ + EXPECT_CALL(delegate, EraseSectors(1234, 1238, testing::_)).WillOnce(testing::SaveArg<2>(&onDone)); + flash.EraseSectors(1234, 4); + + EXPECT_CALL(flashResult, EraseSectorsDone()); + onDone(); +} + +class FlashProxyTest + : public testing::Test +{ +public: + services::MethodSerializerFactory::OnHeap serializerFactory; + application::EchoSingleLoopback echo{ serializerFactory }; + application::FlashHomogeneousProxy flashProxy{ echo, 4, 4096 }; + testing::StrictMock flash{ echo }; + flash::FlashResultProxy flashResult{ echo }; + + const std::array data{ 5, 8, 2, 3 }; + infra::Function onDone; +}; + +TEST_F(FlashProxyTest, ReadBuffer) +{ + EXPECT_CALL(flash, Read(1234, 4)).WillOnce(testing::Invoke([this](uint32_t address, uint32_t size) + { + flashResult.RequestSend([this]() + { + flashResult.ReadDone(infra::MakeRange(data)); + flash.MethodDone(); + }); + })); + + std::array buffer{ 5, 8, 2, 3 }; + flashProxy.ReadBuffer(infra::MakeRange(buffer), 1234, [&]() + { + EXPECT_TRUE(infra::ContentsEqual(infra::MakeRange(buffer), infra::MakeRange(data))); + }); +} + +TEST_F(FlashProxyTest, WriteBuffer) +{ + EXPECT_CALL(flash, Write(1234, infra::CheckByteRangeContents(infra::MakeRange(data)))).WillOnce(testing::Invoke([this](uint32_t address, infra::ConstByteRange contents) + { + flashResult.RequestSend([this]() + { + flashResult.WriteDone(); + flash.MethodDone(); + }); + })); + + infra::VerifyingFunction onDone; + flashProxy.WriteBuffer(infra::MakeRange(data), 1234, onDone); +} + +TEST_F(FlashProxyTest, EraseSectors) +{ + EXPECT_CALL(flash, EraseSectors(12, 22)).WillOnce(testing::Invoke([this](uint32_t sector, uint32_t numberOfSectors) + { + flashResult.RequestSend([this]() + { + flashResult.EraseSectorsDone(); + flash.MethodDone(); + }); + })); + + infra::VerifyingFunction onDone; + flashProxy.EraseSectors(12, 34, onDone); +} diff --git a/integration_test/runner/CMakeLists.txt b/integration_test/runner/CMakeLists.txt index ea573548..102bf8d4 100644 --- a/integration_test/runner/CMakeLists.txt +++ b/integration_test/runner/CMakeLists.txt @@ -5,6 +5,7 @@ target_sources(integration_test.runner PRIVATE FixtureEcho.cpp FixtureEcho.hpp Hooks.cpp + Main.cpp StepsGpio.cpp StepsUart.cpp Waiting.cpp @@ -13,10 +14,18 @@ target_sources(integration_test.runner PRIVATE target_link_libraries(integration_test.runner PRIVATE args - cucumber-cpp-runner + cucumber-cpp integration_test.logic hal.generic gtest gmock services.network_instantiations ) + +if (EMIL_BUILD_WIN) + target_link_libraries(integration_test.runner PRIVATE hal.windows) +endif() + +if (EMIL_BUILD_UNIX OR EMIL_BUILD_DARWIN) + target_link_libraries(integration_test.runner PRIVATE hal.unix) +endif() diff --git a/integration_test/runner/FixtureEcho.cpp b/integration_test/runner/FixtureEcho.cpp index e1b0be90..4a9cad6f 100644 --- a/integration_test/runner/FixtureEcho.cpp +++ b/integration_test/runner/FixtureEcho.cpp @@ -1,80 +1 @@ #include "integration_test/runner/FixtureEcho.hpp" - -namespace main_ -{ - EchoClientWebSocket::EchoClientWebSocket(services::ConnectionFactoryWithNameResolver& connectionFactory, - infra::BoundedString url, hal::SynchronousRandomDataGenerator& randomDataGenerator) - : url(url) - , clientConnector(connectionFactory) - , httpClientInitiationCreator( - [this](infra::Optional& value, services::WebSocketClientObserverFactory& clientObserverFactory, - services::HttpClientWebSocketInitiationResult& result, hal::SynchronousRandomDataGenerator& randomDataGenerator) - { - value.Emplace(clientObserverFactory, clientConnector, result, randomDataGenerator); - }) - , webSocketFactory(randomDataGenerator, { httpClientInitiationCreator }) - { - webSocketFactory.Connect(*this); - } - - void EchoClientWebSocket::OnDone(const OnDoneType& onDone) - { - this->onDone = onDone; - } - - infra::BoundedString EchoClientWebSocket::Url() const - { - return url; - } - - uint16_t EchoClientWebSocket::Port() const - { - return 80; - } - - void EchoClientWebSocket::ConnectionEstablished(infra::AutoResetFunction client)>&& createdClientObserver) - { - auto echoConnectionPtr = echoConnection.Emplace(serializerFactory); - createdClientObserver(echoConnectionPtr); - onDone(*echoConnectionPtr); - } - - void EchoClientWebSocket::ConnectionFailed(ConnectFailReason reason) - { - throw std::runtime_error("Creating ECHO over WebSocket failed"); - } - - EchoClientTcp::EchoClientTcp(services::ConnectionFactoryWithNameResolver& connectionFactory, infra::BoundedConstString hostname, uint16_t port) - : hostname(hostname) - , port(port) - { - connectionFactory.Connect(*this); - } - - void EchoClientTcp::OnDone(const OnDoneType& onDone) - { - this->onDone = onDone; - } - - infra::BoundedConstString EchoClientTcp::Hostname() const - { - return hostname; - } - - uint16_t EchoClientTcp::Port() const - { - return port; - } - - void EchoClientTcp::ConnectionEstablished(infra::AutoResetFunction connectionObserver)>&& createdObserver) - { - auto echoConnectionPtr = echoConnection.Emplace(serializerFactory); - createdObserver(echoConnectionPtr); - onDone(*echoConnectionPtr); - } - - void EchoClientTcp::ConnectionFailed(services::ClientConnectionObserverFactoryWithNameResolver::ConnectFailReason reason) - { - throw std::runtime_error("Creating ECHO over TCP/IP failed"); - } -} diff --git a/integration_test/runner/FixtureEcho.hpp b/integration_test/runner/FixtureEcho.hpp index 60fa358b..5126b96b 100644 --- a/integration_test/runner/FixtureEcho.hpp +++ b/integration_test/runner/FixtureEcho.hpp @@ -2,101 +2,25 @@ #define FIXTURES_ECHO_HPP #include "generated/echo/TracingTesting.pb.hpp" -#include "hal/generic/UartGeneric.hpp" -#include "services/network/EchoOnConnection.hpp" -#include "services/network/HttpClientImpl.hpp" -#include "services/network/WebSocketClientConnectionObserver.hpp" -#include "services/tracer/GlobalTracer.hpp" #include "services/tracer/TracingEchoInstantiation.hpp" namespace main_ { - struct FixtureEchoSerialBase - { - FixtureEchoSerialBase(const std::string& portName) - : serial(portName) - {} - - hal::UartGeneric serial; - services::MethodSerializerFactory::OnHeap serializerFactory; - hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<256> bufferedSerial{ serial }; - }; - - struct FixtureEchoSerial - : FixtureEchoSerialBase - { - main_::EchoOnSesame<256> echoOnSesame{ bufferedSerial, serializerFactory }; - - services::Echo& echo{ echoOnSesame.echo }; - }; + using FixtureEchoSerial = EchoOnUart<256>; struct FixtureTracingEchoSerial - : FixtureEchoSerialBase + : TracingEchoOnUart<256> { - main_::TracingEchoOnSesame<256> echoOnSesame{ bufferedSerial, serializerFactory, services::GlobalTracer() }; + using TracingEchoOnUart<256>::TracingEchoOnUart; - services::Echo& echo{ echoOnSesame.echo }; testing::TesterTracer testerTracer{ echoOnSesame.echo }; testing::TestedTracer testedTracer{ echoOnSesame.echo }; + testing::TesterObserverTracer testerObserverTracer{ echoOnSesame.echo }; testing::TestedObserverTracer testedObserverTracer{ echoOnSesame.echo }; testing::GpioTesterTracer gpioTesterTracer{ echoOnSesame.echo }; testing::GpioTestedTracer gpioTestedTracer{ echoOnSesame.echo }; testing::GpioObserverTracer gpioObserverTracer{ echoOnSesame.echo }; }; - - class EchoClientWebSocket - : private services::WebSocketClientObserverFactory - { - public: - using OnDoneType = infra::Function)>; - - EchoClientWebSocket(services::ConnectionFactoryWithNameResolver& connectionFactory, - infra::BoundedString url, hal::SynchronousRandomDataGenerator& randomDataGenerator); - - void OnDone(const OnDoneType& onDone); - - private: - infra::BoundedString Url() const override; - uint16_t Port() const override; - void ConnectionEstablished(infra::AutoResetFunction client)>&& createdClientObserver) override; - void ConnectionFailed(ConnectFailReason reason) override; - - private: - infra::BoundedString url; - services::HttpClientConnectorWithNameResolverImpl<> clientConnector; - infra::Creator httpClientInitiationCreator; - services::WebSocketClientFactorySingleConnection webSocketFactory; - - infra::SharedOptional echoConnection; - OnDoneType onDone; - services::MethodSerializerFactory::OnHeap serializerFactory; - }; - - class EchoClientTcp - : private services::ClientConnectionObserverFactoryWithNameResolver - { - public: - using OnDoneType = infra::Function)>; - - EchoClientTcp(services::ConnectionFactoryWithNameResolver& connectionFactory, infra::BoundedConstString hostname, uint16_t port); - - void OnDone(const OnDoneType& onDone); - - private: - // Implementation of ClientConnectionObserverFactoryWithNameResolver - infra::BoundedConstString Hostname() const override; - uint16_t Port() const override; - void ConnectionEstablished(infra::AutoResetFunction connectionObserver)>&& createdObserver) override; - void ConnectionFailed(services::ClientConnectionObserverFactoryWithNameResolver::ConnectFailReason reason) override; - - private: - infra::BoundedConstString hostname; - uint16_t port; - - infra::SharedOptional echoConnection; - OnDoneType onDone; - services::MethodSerializerFactory::OnHeap serializerFactory; - }; } #endif diff --git a/integration_test/runner/Hooks.cpp b/integration_test/runner/Hooks.cpp index fe9a2e2b..04896fe0 100644 --- a/integration_test/runner/Hooks.cpp +++ b/integration_test/runner/Hooks.cpp @@ -1,104 +1,60 @@ #include "cucumber-cpp/Hooks.hpp" -#include "args.hxx" #include "generated/echo/Testing.pb.hpp" -#include "hal/generic/SynchronousRandomDataGeneratorGeneric.hpp" #include "hal/generic/TimerServiceGeneric.hpp" -#include "infra/event/EventDispatcherThreadAware.hpp" +#include "infra/timer/Waiting.hpp" #include "integration_test/logic/Tested.hpp" +#include "integration_test/logic/Tester.hpp" #include "integration_test/runner/FixtureEcho.hpp" -#include "integration_test/runner/Waiting.hpp" +#include "services/network_instantiations/EchoInstantiation.hpp" #include "services/network_instantiations/NetworkAdapter.hpp" +#include "services/tracer/GlobalTracer.hpp" #include "gtest/gtest.h" HOOK_BEFORE_ALL() { - args::ArgumentParser parser("Integration test runner for amp-hal-st"); - args::Group arguments(parser, "Arguments:"); - args::Positional target(arguments, "target", "COM port or hostname (ws:///path or tcp://) of the amp-hal-st integration test board", args::Options::Required); - args::Group flags(parser, "Optional flags:"); - args::HelpFlag help(flags, "help", "Display this help menu.", { 'h', "help" }); + auto target = context.Get("target"); + auto networkAdapter = std::make_shared(); + context.SetShared(std::shared_ptr(networkAdapter, &networkAdapter->EventDispatcher())); + context.SetShared(std::shared_ptr(networkAdapter, &networkAdapter->ConnectionFactoryWithNameResolver())); + context.Emplace(); try { - const auto& args = context.Get>("args"); - std::vector stringArgs(args.begin(), args.end()); - parser.ParseArgs(stringArgs); - - auto networkAdapter = std::make_shared(); - context.SetShared(std::shared_ptr(networkAdapter, &networkAdapter->EventDispatcher())); - context.SetShared(std::shared_ptr(networkAdapter, &networkAdapter->ConnectionFactoryWithNameResolver())); - context.Emplace(); - - if (args::get(target).substr(0, 3) == "COM" || args::get(target).substr(0, 4) == "/dev") - { - auto echoFixture = std::make_shared(args::get(target)); - context.SetShared(std::shared_ptr(echoFixture, &echoFixture->echo)); - } - else if (services::SchemeFromUrl(infra::BoundedConstString(args::get(target))) == "ws") - { - if (!infra::WaitUntilDone( - context, [&](const std::function& done) - { - static hal::SynchronousRandomDataGeneratorGeneric randomDataGenerator; - - auto echoFixture = std::make_shared( - context.Get(), - args::get(target), randomDataGenerator); - echoFixture->OnDone([&, echoFixture](services::Echo& echo) - { - context.SetShared(std::shared_ptr(echoFixture, &echo)); - done(); - }); - }, - std::chrono::seconds(10))) - throw std::runtime_error("Couldn't open websocket connection"); - } - else if (services::SchemeFromUrl(infra::BoundedConstString(args::get(target))) == "tcp") - { - if (!infra::WaitUntilDone( - context, [&](const std::function& done) - { - static hal::SynchronousRandomDataGeneratorGeneric randomDataGenerator; - - auto echoFixture = std::make_shared( - context.Get(), - services::HostFromUrl(infra::BoundedConstString(args::get(target))), services::PortFromUrl(args::get(target)).ValueOr(1234)); - echoFixture->OnDone([&, echoFixture](services::Echo& echo) - { - context.SetShared(std::shared_ptr(echoFixture, &echo)); - done(); - }); - }, - std::chrono::seconds(10))) - throw std::runtime_error("Couldn't open websocket connection"); - } - else - throw std::runtime_error("Don't know how to open " + args::get(target)); - - context.Emplace(context.Get()); - context.Emplace(context.Get()); - context.Emplace(context.Get()); + context.SetShared(application::OpenEcho(target, context.Get())); } - catch (const args::Error& error) + catch (std::exception& e) { - std::ostringstream errorPlusHelp; - errorPlusHelp << error.what() << parser; - throw std::runtime_error(errorPlusHelp.str()); + services::GlobalTracer().Trace() << "Exception: " << e.what(); + throw; } + + context.Emplace(context.Get()); + context.Emplace(context.Get()); + context.Emplace(context.Get()); + context.Emplace(context.Get()); } HOOK_BEFORE_SCENARIO() { - EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + EXPECT_TRUE(infra::WaitUntilDone([&](const infra::Function& done) { context.Get().RequestSend([&]() { - context.Get().Reset(); - done(); + context.Get().SetTestedMode(testing::TestedMode::reset); + context.Get().RequestSend([&]() + { + context.Get().SetTestedMode(testing::TestedMode::active); + done(); + }); }); })); - EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + EXPECT_TRUE(infra::WaitFor([&]() + { + return context.Get().ReceivedTestedModeSet(); + })); + + EXPECT_TRUE(infra::WaitUntilDone([&](const infra::Function& done) { context.Get().RequestSend([&]() { @@ -107,7 +63,7 @@ HOOK_BEFORE_SCENARIO() }); })); - EXPECT_TRUE(infra::WaitFor(context, [&]() + EXPECT_TRUE(infra::WaitFor([&]() { return context.Get().ReceivedPong(); })); diff --git a/integration_test/runner/Main.cpp b/integration_test/runner/Main.cpp new file mode 100644 index 00000000..e32532b7 --- /dev/null +++ b/integration_test/runner/Main.cpp @@ -0,0 +1,10 @@ +#include "cucumber-cpp/Application.hpp" + +int main(int argc, char** argv) +{ + cucumber_cpp::Application application{}; + + application.CliParser().add_option("--target", *application.ProgramContext().EmplaceAt("target"), "COM port or hostname (ws:///path or tcp://) of the amp-hal-st integration test board")->required(); + + return application.Run(argc, argv); +} diff --git a/integration_test/runner/StepsGpio.cpp b/integration_test/runner/StepsGpio.cpp index 3bcfe3f5..7a683f3e 100644 --- a/integration_test/runner/StepsGpio.cpp +++ b/integration_test/runner/StepsGpio.cpp @@ -1,7 +1,7 @@ #include "cucumber-cpp/Steps.hpp" #include "generated/echo/Testing.pb.hpp" +#include "infra/timer/Waiting.hpp" #include "integration_test/logic/Tested.hpp" -#include "integration_test/runner/Waiting.hpp" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -44,7 +44,7 @@ namespace STEP("gpio peripherals are enabled") { - EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + EXPECT_TRUE(infra::WaitUntilDone([&](const infra::Function& done) { context.Emplace(context.Get()); @@ -55,7 +55,7 @@ STEP("gpio peripherals are enabled") }); })); - EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + EXPECT_TRUE(infra::WaitUntilDone([&](const infra::Function& done) { context.Get().RequestSend([&]() { @@ -68,7 +68,7 @@ STEP("gpio peripherals are enabled") }); })); - EXPECT_TRUE(infra::WaitFor(context, [&]() + EXPECT_TRUE(infra::WaitFor([&]() { return context.Get().ReceivedPong(); })); @@ -81,7 +81,7 @@ STEP("the tester sets its output pin (high|low)", (std::string state)) { context.EmplaceAt("state", ConvertPinState(state)); - EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + EXPECT_TRUE(infra::WaitUntilDone([&](const infra::Function& done) { context.Get().RequestSend([&]() { @@ -95,7 +95,7 @@ STEP("the tester sees a (high|low) value", (std::string state)) { context.EmplaceAt("state", ConvertPinState(state)); - EXPECT_TRUE(infra::WaitFor(context, [&]() + EXPECT_TRUE(infra::WaitFor([&]() { return context.Get().testerGpio == context.Get("state"); })); @@ -105,7 +105,7 @@ STEP("the tested sets its output pin (high|low)", (std::string state)) { context.EmplaceAt("state", ConvertPinState(state)); - EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + EXPECT_TRUE(infra::WaitUntilDone([&](const infra::Function& done) { context.Get().RequestSend([&]() { @@ -119,7 +119,7 @@ STEP("the tested sees a (high|low) value", (std::string state)) { context.EmplaceAt("state", ConvertPinState(state)); - EXPECT_TRUE(infra::WaitFor(context, [&]() + EXPECT_TRUE(infra::WaitFor([&]() { return context.Get().testedGpio == context.Get("state"); })); diff --git a/integration_test/runner/StepsUart.cpp b/integration_test/runner/StepsUart.cpp index 14ac869d..b02b9a4a 100644 --- a/integration_test/runner/StepsUart.cpp +++ b/integration_test/runner/StepsUart.cpp @@ -1,7 +1,7 @@ #include "cucumber-cpp/Steps.hpp" #include "generated/echo/Testing.pb.hpp" +#include "infra/timer/Waiting.hpp" #include "integration_test/logic/Tested.hpp" -#include "integration_test/runner/Waiting.hpp" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -34,7 +34,7 @@ namespace STEP("uart peripherals are enabled") { - EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + EXPECT_TRUE(infra::WaitUntilDone([&](const infra::Function& done) { context.Emplace(context.Get()); @@ -45,7 +45,7 @@ STEP("uart peripherals are enabled") }); })); - EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + EXPECT_TRUE(infra::WaitUntilDone([&](const infra::Function& done) { context.Get().RequestSend([&]() { @@ -58,7 +58,7 @@ STEP("uart peripherals are enabled") }); })); - EXPECT_TRUE(infra::WaitFor(context, [&]() + EXPECT_TRUE(infra::WaitFor([&]() { return context.Get().ReceivedPong(); })); @@ -69,7 +69,7 @@ STEP("uart peripherals are enabled") STEP("uart duplex dma peripherals are enabled") { - EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + EXPECT_TRUE(infra::WaitUntilDone([&](const infra::Function& done) { context.Emplace(context.Get()); @@ -80,7 +80,7 @@ STEP("uart duplex dma peripherals are enabled") }); })); - EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + EXPECT_TRUE(infra::WaitUntilDone([&](const infra::Function& done) { context.Get().RequestSend([&]() { @@ -93,7 +93,7 @@ STEP("uart duplex dma peripherals are enabled") }); })); - EXPECT_TRUE(infra::WaitFor(context, [&]() + EXPECT_TRUE(infra::WaitFor([&]() { return context.Get().ReceivedPong(); })); @@ -106,7 +106,7 @@ STEP("the tester sends UART data") { static const infra::BoundedVector::WithMaxSize<32> expectedData{ { 1, 2, 3, 4, 5, 6 } }; - EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + EXPECT_TRUE(infra::WaitUntilDone([&](const infra::Function& done) { context.Get().RequestSend([&]() { @@ -120,7 +120,7 @@ STEP("the tested sends UART data") { static const infra::BoundedVector::WithMaxSize<32> expectedData{ { 1, 2, 3, 4, 5, 6 } }; - EXPECT_TRUE(infra::WaitUntilDone(context, [&](const std::function& done) + EXPECT_TRUE(infra::WaitUntilDone([&](const infra::Function& done) { context.Get().RequestSend([&]() { @@ -134,7 +134,7 @@ STEP("the tester sees UART data") { static const std::vector expectedData{ 1, 2, 3, 4, 5, 6 }; - EXPECT_TRUE(infra::WaitFor(context, [&]() + EXPECT_TRUE(infra::WaitFor([&]() { return context.Get().testerData == expectedData; })); @@ -144,7 +144,7 @@ STEP("the tested sees UART data") { static const std::vector expectedData{ 1, 2, 3, 4, 5, 6 }; - EXPECT_TRUE(infra::WaitFor(context, [&]() + EXPECT_TRUE(infra::WaitFor([&]() { return context.Get().testedData == expectedData; })); diff --git a/integration_test/tested/CMakeLists.txt b/integration_test/tested/CMakeLists.txt index a10bddce..708329ab 100644 --- a/integration_test/tested/CMakeLists.txt +++ b/integration_test/tested/CMakeLists.txt @@ -14,5 +14,7 @@ target_link_libraries(integration_test.tested PRIVATE hal_st.instantiations ) +emil_generate_artifacts(TARGET integration_test.tested BIN) + halst_target_default_linker_scripts(integration_test.tested) halst_target_default_init(integration_test.tested) diff --git a/integration_test/tested/EchoFromTester.hpp b/integration_test/tested/EchoFromTester.hpp index f04d8834..1efe4a5f 100644 --- a/integration_test/tested/EchoFromTester.hpp +++ b/integration_test/tested/EchoFromTester.hpp @@ -22,7 +22,7 @@ namespace main_ hal::DmaStm::TransmitStream transmitStream; hal::DmaStm::ReceiveStream receiveStream; hal::UartStmDuplexDma::WithRxBuffer<256> echoUart{ transmitStream, receiveStream, 5, echoUartTx, echoUartRx }; - services::MethodSerializerFactory::ForServices::AndProxies serializerFactory; + services::MethodSerializerFactory::ForServices::AndProxies serializerFactory; hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<256> bufferedEchoUart{ echoUart }; main_::TracingEchoOnSesame<256> echo{ bufferedEchoUart, serializerFactory, services::GlobalTracer() }; diff --git a/integration_test/tester/CMakeLists.txt b/integration_test/tester/CMakeLists.txt index 1e069942..4213bae1 100644 --- a/integration_test/tester/CMakeLists.txt +++ b/integration_test/tester/CMakeLists.txt @@ -13,7 +13,10 @@ target_sources(integration_test.tester PRIVATE target_link_libraries(integration_test.tester PRIVATE integration_test.logic hal_st.instantiations + services.st_util ) +emil_generate_artifacts(TARGET integration_test.tester BIN) + halst_target_default_linker_scripts(integration_test.tester) halst_target_default_init(integration_test.tester) diff --git a/integration_test/tester/EchoFromCloud.hpp b/integration_test/tester/EchoFromCloud.hpp index d0406a12..b0319dbd 100644 --- a/integration_test/tester/EchoFromCloud.hpp +++ b/integration_test/tester/EchoFromCloud.hpp @@ -1,7 +1,9 @@ #ifndef HAL_ST_INTEGRATION_TEST_ECHO_FROM_CLOUD_HPP #define HAL_ST_INTEGRATION_TEST_ECHO_FROM_CLOUD_HPP +#include "generated/echo/Flash.pb.hpp" #include "generated/echo/Testing.pb.hpp" +#include "generated/echo/TracingFlash.pb.hpp" #include "generated/echo/TracingTesting.pb.hpp" #include "hal_st/stm32fxxx/UartStmDuplexDma.hpp" #include "services/tracer/GlobalTracer.hpp" @@ -22,13 +24,14 @@ namespace main_ hal::DmaStm::TransmitStream transmitStream; hal::DmaStm::ReceiveStream receiveStream; hal::UartStmDuplexDma::WithRxBuffer<256> hostUart{ transmitStream, receiveStream, 4, hostUartTxPin, hostUartRxPin }; - services::MethodSerializerFactory::ForServices::AndProxies serializerFactory; + services::MethodSerializerFactory::ForServices::AndProxies serializerFactory; hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<256> bufferedHostUart{ hostUart }; services::TracerColoured redTracer; main_::TracingEchoOnSesame<256> echo{ bufferedHostUart, serializerFactory, redTracer }; testing::TesterTracer testerTracer{ echo.echo }; testing::TestedTracer testedTracer{ echo.echo }; + testing::TesterObserverTracer testerObserverTracer{ echo.echo }; testing::TestedObserverTracer testedObserverTracer{ echo.echo }; testing::GpioTesterTracer gpioTesterTracer{ echo.echo }; testing::GpioTestedTracer gpioTestedTracer{ echo.echo }; @@ -36,6 +39,8 @@ namespace main_ testing::UartTesterTracer uartTesterTracer{ echo.echo }; testing::UartTestedTracer uartTestedTracer{ echo.echo }; testing::UartObserverTracer uartObserverTracer{ echo.echo }; + flash::FlashTracer flashTracer{ echo.echo }; + flash::FlashResultTracer flashResultTracer{ echo.echo }; }; } diff --git a/integration_test/tester/ForwardingEchoToTested.hpp b/integration_test/tester/ForwardingEchoToTested.hpp index 6feaa84f..a148fe5a 100644 --- a/integration_test/tester/ForwardingEchoToTested.hpp +++ b/integration_test/tester/ForwardingEchoToTested.hpp @@ -24,7 +24,7 @@ namespace main_ hal::DmaStm::TransmitStream transmitStream; hal::DmaStm::ReceiveStream receiveStream; hal::UartStmDuplexDma::WithRxBuffer<256> echoUart{ transmitStream, receiveStream, 5, echoUartTx, echoUartRx }; - services::MethodSerializerFactory::ForServices::AndProxies serializerFactory; + services::MethodSerializerFactory::ForServices::AndProxies serializerFactory; hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<256> bufferedEchoUart{ echoUart }; services::TracerColoured blueTracer; main_::TracingEchoOnSesame<256> echo{ bufferedEchoUart, serializerFactory, blueTracer }; @@ -41,6 +41,16 @@ namespace main_ { ForwardingEchoToTested(services::Echo& echo, hal::DmaStm& dma, services::Tracer& tracer); + operator const services::EchoOnSesame&() const + { + return echoToTested.echo.echo; + } + + operator services::EchoOnSesame&() + { + return echoToTested.echo.echo; + } + main_::EchoToTested echoToTested; services::ServiceForwarder forwardTested; services::ServiceForwarder forwardTestedObserver; diff --git a/integration_test/tester/Main.cpp b/integration_test/tester/Main.cpp index 49c578fd..f139e2b1 100644 --- a/integration_test/tester/Main.cpp +++ b/integration_test/tester/Main.cpp @@ -34,8 +34,13 @@ int main() static hal::DmaStm dma; static main_::EchoFromCloud echo(dma, tracerInfrastructure.tracer); - static main_::ForwardingEchoToTested forwarder(echo.echo, dma, tracerInfrastructure.tracer); - static main_::Tester tester(echo.echo, forwarder.echoToTested.echo.echo, dma); + static infra::Creator forwarderCreator{ + [](infra::Optional& value) + { + value.Emplace(echo.echo, dma, tracerInfrastructure.tracer); + } + }; + static main_::Tester tester(echo.echo, forwarderCreator, dma); services::GlobalTracer().Trace() << "Starting tester!"; diff --git a/integration_test/tester/Tester.cpp b/integration_test/tester/Tester.cpp index 86f6fbb1..17be104e 100644 --- a/integration_test/tester/Tester.cpp +++ b/integration_test/tester/Tester.cpp @@ -16,8 +16,20 @@ namespace main_ , receiveStream{ dma, hal::DmaChannelId{ 1, 5, 4 } } {} - Tester::Tester(services::Echo& echo, services::EchoOnSesame& echoToTested, hal::DmaStm& dma) - : tester(echo, nResetTester, echoToTested) + FlashTested::FlashTested(services::Echo& echo, hal::DmaStm& dma, const infra::Function& onDone) + : onDone(onDone) + , transmitStream{ dma, hal::DmaChannelId{ 2, 7, 5 } } + , receiveStream{ dma, hal::DmaChannelId{ 2, 1, 5 } } + , flashOverEcho(echo, flashProgrammer) + {} + + Tester::Tester(services::Echo& echo, application::Tester::EchoToTestedCreator& echoToTestedCreator, hal::DmaStm& dma) + : dma(dma) + , flashTestedCreator([this](infra::Optional& value, services::Echo& echo, const infra::Function& onDone) + { + value.Emplace(echo, this->dma, onDone); + }) + , tester(echo, nResetTested, echoToTestedCreator, flashTestedCreator) , uartDuplexDmaTester{ tester, testing::Peripheral::uartDuplexDma, dma } {} } diff --git a/integration_test/tester/Tester.hpp b/integration_test/tester/Tester.hpp index 4f485673..c02a61dd 100644 --- a/integration_test/tester/Tester.hpp +++ b/integration_test/tester/Tester.hpp @@ -5,9 +5,12 @@ #include "hal_st/stm32fxxx/GpioStm.hpp" #include "hal_st/stm32fxxx/UartStm.hpp" #include "hal_st/stm32fxxx/UartStmDuplexDma.hpp" +#include "integration_test/logic/Flash.hpp" #include "integration_test/logic/Gpio.hpp" #include "integration_test/logic/Tester.hpp" #include "integration_test/logic/Uart.hpp" +#include "services/st_util/FlashOnStBootloaderCommunicator.hpp" +#include "services/st_util/StBootloaderCommunicatorUart.hpp" namespace main_ { @@ -44,11 +47,55 @@ namespace main_ application::UartTester uartTester; }; + struct FlashTested + { + FlashTested(services::Echo& echo, hal::DmaStm& dma, const infra::Function& onDone); + + infra::Function onDone; + + hal::GpioPinStm boot0TestedPin{ hal::Port::A, 5 }; + hal::OutputPin boot0Tested{ boot0TestedPin, true }; + + hal::GpioPinStm tx{ hal::Port::G, 14 }; + hal::GpioPinStm rx{ hal::Port::G, 9 }; + hal::DmaStm::TransmitStream transmitStream; + hal::DmaStm::ReceiveStream receiveStream; + hal::UartStmDuplexDma::WithRxBuffer<256> uart{ transmitStream, receiveStream, 6, tx, rx }; + + std::array sectorSizes{ { 32 * 1024, + 32 * 1024, + 32 * 1024, + 32 * 1024, + 128 * 1024, + 256 * 1024, + 256 * 1024, + 256 * 1024, + 256 * 1024, + 256 * 1024, + 256 * 1024, + 256 * 1024 } }; + + services::StBootloaderCommunicatorUart programmer{ + uart, [this]() + { + this->onDone({}); + }, + [this](infra::BoundedConstString reason) + { + this->onDone(reason); + } + }; + services::FlashHeterogeneousOnStBootloaderCommunicator flashProgrammer{ infra::MakeRange(sectorSizes), programmer }; + application::Flash flashOverEcho; + }; + struct Tester { - Tester(services::Echo& echo, services::EchoOnSesame& echoToTested, hal::DmaStm& dma); + Tester(services::Echo& echo, application::Tester::EchoToTestedCreator& echoToTestedCreator, hal::DmaStm& dma); - hal::GpioPinStm nResetTester{ hal::Port::E, 6, hal::Drive::OpenDrain }; + hal::DmaStm& dma; + hal::GpioPinStm nResetTested{ hal::Port::E, 6, hal::Drive::OpenDrain }; + infra::Creator& onDone)> flashTestedCreator; application::Tester tester; application::Peripheral gpioTester{ tester, testing::Peripheral::gpio }; application::Peripheral uartTester{ tester, testing::Peripheral::uart }; diff --git a/services/st_util/CMakeLists.txt b/services/st_util/CMakeLists.txt index 01a7449e..423d7450 100644 --- a/services/st_util/CMakeLists.txt +++ b/services/st_util/CMakeLists.txt @@ -18,7 +18,8 @@ target_link_libraries(services.st_util PUBLIC services.util ) -if (EMIL_BUILD_TESTS) - add_subdirectory(test_doubles) +add_subdirectory(test_doubles) + +if (HALST_BUILD_TESTS) add_subdirectory(test) endif()