Add minimal integration test
This commit is contained in:
parent
2a55b5562a
commit
1948a4a3d2
@ -15,7 +15,6 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
set(BOOST_ROOT /usr/local)
|
|
||||||
find_package(Boost REQUIRED COMPONENTS system json)
|
find_package(Boost REQUIRED COMPONENTS system json)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
@ -25,7 +24,9 @@ function(create_boost_header_only_target target_name)
|
|||||||
set(interface_target ${target_key}_interface)
|
set(interface_target ${target_key}_interface)
|
||||||
set(header_subdir ${target_key})
|
set(header_subdir ${target_key})
|
||||||
|
|
||||||
if(NOT TARGET Boost::${target_name})
|
set(target_name_full Boost::${target_name})
|
||||||
|
|
||||||
|
if(NOT TARGET ${target_name_full})
|
||||||
message(STATUS "Creating Boost::${target_name} as header-only interface target")
|
message(STATUS "Creating Boost::${target_name} as header-only interface target")
|
||||||
|
|
||||||
add_library(${interface_target} INTERFACE)
|
add_library(${interface_target} INTERFACE)
|
||||||
@ -43,9 +44,9 @@ function(create_boost_header_only_target target_name)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Create alias for consistency with imported targets
|
# Create alias for consistency with imported targets
|
||||||
add_library(Boost::${target_name} ALIAS ${interface_target})
|
add_library(${target_name_full} ALIAS ${interface_target})
|
||||||
else()
|
else()
|
||||||
message(STATUS "Boost::${target_name} already exists")
|
message(STATUS "${target_name_full} already exists")
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ add_subdirectory(
|
|||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
asyncmqtt5
|
asyncmqtt5
|
||||||
GIT_REPOSITORY https://github.com/mireo/async-mqtt5
|
GIT_REPOSITORY https://github.com/boostorg/mqtt5
|
||||||
GIT_TAG master
|
GIT_TAG master
|
||||||
GIT_SHALLOW TRUE
|
GIT_SHALLOW TRUE
|
||||||
)
|
)
|
||||||
|
|||||||
15
docker/Dockerfile.baseimage
Normal file
15
docker/Dockerfile.baseimage
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
FROM ubuntu:24.04
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
|
libboost-json1.83.0 \
|
||||||
|
libboost-system1.83.0 \
|
||||||
|
liburing2 \
|
||||||
|
python3 python3-pip \
|
||||||
|
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install Python test deps globally
|
||||||
|
#RUN pip3 install pytest paho-mqtt
|
||||||
|
RUN pip3 install --break-system-packages pytest paho-mqtt
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
@ -13,7 +13,6 @@ target_include_directories(ranczo-io_utils
|
|||||||
target_link_libraries(ranczo-io_utils
|
target_link_libraries(ranczo-io_utils
|
||||||
PUBLIC
|
PUBLIC
|
||||||
Boost::mqtt5
|
Boost::mqtt5
|
||||||
Boost::system
|
|
||||||
Boost::json
|
Boost::json
|
||||||
spdlog::spdlog
|
spdlog::spdlog
|
||||||
)
|
)
|
||||||
|
|||||||
@ -220,7 +220,7 @@ struct AsyncMqttClient::AsyncMqttClientImpl {
|
|||||||
AsyncMqttClient::AsyncMqttClient(const boost::asio::any_io_executor & executor)
|
AsyncMqttClient::AsyncMqttClient(const boost::asio::any_io_executor & executor)
|
||||||
: _impl{std::make_unique< AsyncMqttClient::AsyncMqttClientImpl >(executor)} {}
|
: _impl{std::make_unique< AsyncMqttClient::AsyncMqttClientImpl >(executor)} {}
|
||||||
|
|
||||||
awaitable_expected<void> AsyncMqttClient::subscribe(std::string_view topic, std::function< awaitable_expected< void >(const boost::json::value &) > cb) noexcept {
|
awaitable_expected<void> AsyncMqttClient::subscribe(std::string_view topic, callback_t&& cb) noexcept {
|
||||||
BOOST_ASSERT(_impl);
|
BOOST_ASSERT(_impl);
|
||||||
BOOST_ASSERT(not topic.empty());
|
BOOST_ASSERT(not topic.empty());
|
||||||
BOOST_ASSERT(cb);
|
BOOST_ASSERT(cb);
|
||||||
|
|||||||
@ -31,6 +31,8 @@ class AsyncMqttClient {
|
|||||||
const boost::json::value & value;
|
const boost::json::value & value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using callback_t = std::function< awaitable_expected< void >(const boost::json::value & value) >;
|
||||||
|
|
||||||
struct AsyncMqttClientImpl;
|
struct AsyncMqttClientImpl;
|
||||||
std::unique_ptr< AsyncMqttClientImpl > _impl;
|
std::unique_ptr< AsyncMqttClientImpl > _impl;
|
||||||
|
|
||||||
@ -38,8 +40,7 @@ class AsyncMqttClient {
|
|||||||
~AsyncMqttClient();
|
~AsyncMqttClient();
|
||||||
|
|
||||||
/* subscribes to a topic, topic can contain wildcards */
|
/* subscribes to a topic, topic can contain wildcards */
|
||||||
awaitable_expected< void > subscribe(std::string_view topic,
|
awaitable_expected< void > subscribe(std::string_view topic, callback_t &&cb) noexcept;
|
||||||
std::function< awaitable_expected< void >(const boost::json::value & value) >) noexcept;
|
|
||||||
|
|
||||||
awaitable_expected< const boost::json::value & > request(std::string_view topic, const boost::json::value & value) noexcept;
|
awaitable_expected< const boost::json::value & > request(std::string_view topic, const boost::json::value & value) noexcept;
|
||||||
awaitable_expected< void > publish(std::string_view topic, const boost::json::value & value) noexcept;
|
awaitable_expected< void > publish(std::string_view topic, const boost::json::value & value) noexcept;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
add_executable(ranczo-io_floorheating
|
add_executable(ranczo-io_floorheating
|
||||||
main.cpp
|
main.cpp
|
||||||
heater._controller.cpp
|
heater_controller.cpp
|
||||||
relay.cpp
|
relay.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,3 +17,15 @@ install(
|
|||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
add_test(NAME ranczo_io_floorheating_integration
|
||||||
|
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/integration_tests/run_docker_integration_tests.sh
|
||||||
|
)
|
||||||
|
|
||||||
|
set_tests_properties(ranczo_io_floorheating_integration PROPERTIES
|
||||||
|
ENVIRONMENT INSTALL_DIR=${CMAKE_BINARY_DIR}/install
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/integration_tests
|
||||||
|
TIMEOUT 120
|
||||||
|
)
|
||||||
|
|||||||
6
services/floorheat_svc/integration_tests/Dockerfile
Normal file
6
services/floorheat_svc/integration_tests/Dockerfile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
FROM ranczo-io_baseimage:latest
|
||||||
|
|
||||||
|
# Copy tests into /tests
|
||||||
|
COPY . /tests/
|
||||||
|
WORKDIR /tests
|
||||||
|
CMD ["pytest", "-v"]
|
||||||
28
services/floorheat_svc/integration_tests/docker-compose.yml
Normal file
28
services/floorheat_svc/integration_tests/docker-compose.yml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
mqtt:
|
||||||
|
image: eclipse-mosquitto
|
||||||
|
ports:
|
||||||
|
- "1883:1883"
|
||||||
|
|
||||||
|
floorheating_svc:
|
||||||
|
image: ranczo-io_baseimage:latest
|
||||||
|
volumes:
|
||||||
|
- ${INSTALL_DIR}/:/app
|
||||||
|
# - ${INSTALL_DIR}/etc/ranczo-io_config:/app/ig:ro # optional
|
||||||
|
working_dir: /app
|
||||||
|
command: ["./bin/ranczo-io_floorheating"]
|
||||||
|
depends_on:
|
||||||
|
- mqtt
|
||||||
|
|
||||||
|
tests:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
# volumes:
|
||||||
|
# - ../../../build/install/:/install:ro # expose binaries if needed
|
||||||
|
depends_on:
|
||||||
|
- mqtt
|
||||||
|
- floorheating_svc
|
||||||
|
|
||||||
21
services/floorheat_svc/integration_tests/run_docker_integration_tests.sh
Executable file
21
services/floorheat_svc/integration_tests/run_docker_integration_tests.sh
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Allow overriding from env
|
||||||
|
INSTALL_DIR="${INSTALL_DIR:-${CMAKE_BINARY_DIR}/install}"
|
||||||
|
BUILD_DIR="$(dirname "$INSTALL_DIR")"
|
||||||
|
|
||||||
|
echo "[INFO] Using INSTALL_DIR=$INSTALL_DIR"
|
||||||
|
echo "[INFO] Inferred BUILD_DIR=$BUILD_DIR"
|
||||||
|
|
||||||
|
# 1. Build the project first
|
||||||
|
echo "[INFO] Building project..."
|
||||||
|
cmake --build "$BUILD_DIR"
|
||||||
|
|
||||||
|
# 2. Then install to INSTALL_DIR
|
||||||
|
echo "[INFO] Installing to $INSTALL_DIR..."
|
||||||
|
cmake --install "$BUILD_DIR" --prefix "$INSTALL_DIR"
|
||||||
|
|
||||||
|
# 3. Run docker-compose tests
|
||||||
|
echo "[INFO] Running docker compose integration tests..."
|
||||||
|
docker compose -f docker-compose.yml up --build --abort-on-container-exit
|
||||||
6
services/floorheat_svc/integration_tests/test_ok.py
Normal file
6
services/floorheat_svc/integration_tests/test_ok.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
def test_assert():
|
||||||
|
assert True
|
||||||
|
|
||||||
@ -14,6 +14,7 @@
|
|||||||
#include <ranczo-io/utils/timer.hpp>
|
#include <ranczo-io/utils/timer.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <csignal>
|
||||||
|
|
||||||
namespace ranczo {
|
namespace ranczo {
|
||||||
|
|
||||||
@ -30,12 +31,28 @@ namespace ranczo {
|
|||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
using namespace std::string_view_literals;
|
using namespace std::string_view_literals;
|
||||||
|
|
||||||
|
std::atomic<bool> running = true;
|
||||||
|
boost::asio::io_context* g_io = nullptr;
|
||||||
|
|
||||||
|
void signal_handler(int signum) {
|
||||||
|
spdlog::warn("Signal received: {}, stopping io_context...", signum);
|
||||||
|
running = false;
|
||||||
|
if (g_io) {
|
||||||
|
g_io->stop(); // <--- This stops io_context.run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
spdlog::set_level(spdlog::level::trace);
|
spdlog::set_level(spdlog::level::trace);
|
||||||
|
|
||||||
std::vector< std::shared_ptr< ranczo::IHeater > > _heaters;
|
std::vector< std::shared_ptr< ranczo::IHeater > > _heaters;
|
||||||
|
|
||||||
boost::asio::io_context io_context;
|
boost::asio::io_context io_context;
|
||||||
|
g_io = &io_context;
|
||||||
|
|
||||||
|
// Register signal handler
|
||||||
|
spdlog::info("Registering signal handlers");
|
||||||
|
std::signal(SIGINT, signal_handler);
|
||||||
|
std::signal(SIGTERM, signal_handler);
|
||||||
|
|
||||||
boost::asio::any_io_executor io_executor = io_context.get_executor();
|
boost::asio::any_io_executor io_executor = io_context.get_executor();
|
||||||
// PARTER
|
// PARTER
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user