diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 9f37aee55..e13f58c44 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -334,7 +334,7 @@ jobs: - name: Build language bindings # NOTE: the cmake command is in a single line since Windows complains about breaking up lines with '\' run: | - cmake -S . -B target/ffi/build -DBUILD_EXAMPLES=ON -DBUILD_TESTING=ON ${{ matrix.mode.cmake-build-type }} ${{ matrix.mode.cmake-cxx-flags }} ${{ matrix.cmake-build-system-generator }} -DCMAKE_INSTALL_PREFIX=target/ffi/install -DCMAKE_PREFIX_PATH="${{ github.workspace }}/target/iceoryx/install" -DRUST_BUILD_ARTIFACT_PATH="${{ github.workspace }}/target/${{ matrix.mode.name }}" + cmake -S . -B target/ffi/build -DBUILD_EXAMPLES=ON -DBUILD_TESTING=ON -DWARNING_AS_ERROR=ON ${{ matrix.mode.cmake-build-type }} ${{ matrix.mode.cmake-cxx-flags }} ${{ matrix.cmake-build-system-generator }} -DCMAKE_INSTALL_PREFIX=target/ffi/install -DCMAKE_PREFIX_PATH="${{ github.workspace }}/target/iceoryx/install" -DRUST_BUILD_ARTIFACT_PATH="${{ github.workspace }}/target/${{ matrix.mode.name }}" cmake --build target/ffi/build ${{ matrix.mode.cmake-build-config }} cmake --install target/ffi/build ${{ matrix.mode.cmake-build-config }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 596afd26d..59d054336 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,12 @@ add_option( DEFAULT_VALUE OFF ) +add_option( + NAME WARNING_AS_ERROR + DESCRIPTION "Fails if the compiler emits a warning" + DEFAULT_VALUE OFF +) + add_param( NAME RUST_BUILD_ARTIFACT_PATH DESCRIPTION "The path to the folder with the Rust build artifacts, e.g. '/full/path/to/iceoryx2/target/release'" @@ -110,6 +116,16 @@ add_rust_feature( RUST_FEATURE "iceoryx2/logger_tracing" ) +if(WARNING_AS_ERROR) + if(WIN32) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wall -Wextra -Wpedantic") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Wpedantic") + endif() +endif() + if(SANITIZERS) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize=undefined") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize=undefined") diff --git a/examples/README.md b/examples/README.md index 26291f249..a1dbf54f2 100644 --- a/examples/README.md +++ b/examples/README.md @@ -79,7 +79,7 @@ These types are demonstrated in the complex data types example. | event | [C](c/event) [C++](cxx/event) [Rust](rust/event) | Push notifications - send event signals to wakeup processes that are waiting for them. | | event based communication | [C++](cxx/event_based_communication) [Rust](rust/event_based_communication) | Define multiple events like publisher/subscriber created or removed, send sample, received sample, deliver history etc. and react on them for a fully event driven communication setup. | | event multiplexing | [C](c/event_multiplexing) [C++](cxx/event_multiplexing) [Rust](rust/event_multiplexing) | Wait on multiple listeners or sockets with a single call. The WaitSet demultiplexes incoming events and notifies the user. | -| health monitoring | [Rust](rust/health_monitoring) | A central daemon creates the communication resources and monitors all nodes. When the central daemon crashes other nodes can take over and use the decentral API to monitor the nodes. | +| health monitoring | [C++](cxx/health_monitoring) [Rust](rust/health_monitoring) | A central daemon creates the communication resources and monitors all nodes. When the central daemon crashes other nodes can take over and use the decentral API to monitor the nodes. | | publish subscribe | [C](c/publish_subscribe) [C++](cxx/publish_subscribe) [Rust](rust/publish_subscribe) | Communication between multiple processes with a [publish subscribe messaging pattern](https://en.wikipedia.org/wiki/Publish–subscribe_pattern). | | publish subscribe dynamic data | [C++](cxx/publish_subscribe_dynamic_data) [Rust](rust/publish_subscribe_dynamic_data) | Communication between multiple processes with a [publish subscribe messaging pattern](https://en.wikipedia.org/wiki/Publish–subscribe_pattern) and payload data that has a dynamic size. | | publish subscribe with user header | [C](c/publish_subscribe_with_user_header) [C++](cxx/publish_subscribe_with_user_header) [Rust](rust/publish_subscribe_with_user_header) | Add a user header to the payload (samples) to transfer additional information. | diff --git a/examples/c/discovery/src/main.c b/examples/c/discovery/src/main.c index 81e5aacac..d84ba740a 100644 --- a/examples/c/discovery/src/main.c +++ b/examples/c/discovery/src/main.c @@ -14,6 +14,7 @@ #include iox2_callback_progression_e list_callback(const iox2_static_config_t* static_details, void* callback_context) { + (void) callback_context; printf("Found Service: %s, ServiceID: %s\n", static_details->name, static_details->id); return iox2_callback_progression_e_CONTINUE; } diff --git a/examples/c/domains/src/discovery.c b/examples/c/domains/src/discovery.c index 26e9bc1b9..8d41c7b76 100644 --- a/examples/c/domains/src/discovery.c +++ b/examples/c/domains/src/discovery.c @@ -14,6 +14,7 @@ #include iox2_callback_progression_e list_callback(const iox2_static_config_t* static_details, void* callback_context) { + (void) callback_context; printf("Found Service: %s, ServiceID: %s\n", static_details->name, static_details->id); return iox2_callback_progression_e_CONTINUE; } diff --git a/examples/c/domains/src/subscriber.c b/examples/c/domains/src/subscriber.c index d8ef93bde..70be8d78d 100644 --- a/examples/c/domains/src/subscriber.c +++ b/examples/c/domains/src/subscriber.c @@ -94,11 +94,8 @@ int main(int argc, char** argv) { goto drop_service; } - uint64_t counter = 0; printf("subscribed to: [domain: \"%s\", service: \"%s\"]\n", argv[1], argv[2]); while (iox2_node_wait(&node_handle, 1, 0) == IOX2_OK) { - counter += 1; - // receive sample iox2_sample_h sample = NULL; if (iox2_subscriber_receive(&subscriber, NULL, &sample) != IOX2_OK) { diff --git a/examples/c/event_multiplexing/src/notifier.c b/examples/c/event_multiplexing/src/notifier.c index 67ecff8ee..87fce2984 100644 --- a/examples/c/event_multiplexing/src/notifier.c +++ b/examples/c/event_multiplexing/src/notifier.c @@ -56,7 +56,7 @@ int main(int argc, char** argv) { iox2_port_factory_event_h service = NULL; if (iox2_service_builder_event_open_or_create(service_builder_event, NULL, &service) != IOX2_OK) { printf("Unable to create service!\n"); - goto drop_node; + goto drop_service_name; } // create notifier diff --git a/examples/c/publish_subscribe/src/subscriber.c b/examples/c/publish_subscribe/src/subscriber.c index 75acdc848..2707bb2fe 100644 --- a/examples/c/publish_subscribe/src/subscriber.c +++ b/examples/c/publish_subscribe/src/subscriber.c @@ -73,10 +73,7 @@ int main(void) { goto drop_service; } - uint64_t counter = 0; while (iox2_node_wait(&node_handle, 1, 0) == IOX2_OK) { - counter += 1; - // receive sample iox2_sample_h sample = NULL; if (iox2_subscriber_receive(&subscriber, NULL, &sample) != IOX2_OK) { diff --git a/examples/c/publish_subscribe_with_user_header/src/subscriber.c b/examples/c/publish_subscribe_with_user_header/src/subscriber.c index 6dad2039c..a9cde3ad6 100644 --- a/examples/c/publish_subscribe_with_user_header/src/subscriber.c +++ b/examples/c/publish_subscribe_with_user_header/src/subscriber.c @@ -86,10 +86,7 @@ int main(void) { goto drop_service; } - uint64_t counter = 0; while (iox2_node_wait(&node_handle, 1, 0) == IOX2_OK) { - counter += 1; - // receive sample iox2_sample_h sample = NULL; if (iox2_subscriber_receive(&subscriber, NULL, &sample) != IOX2_OK) { @@ -107,7 +104,7 @@ int main(void) { printf("received: %lu, user_header: version = %d, timestamp = %lu\n", (long unsigned) *payload, user_header->version, - user_header->timestamp); + (long unsigned) user_header->timestamp); iox2_sample_drop(sample); } } diff --git a/examples/cxx/CMakeLists.txt b/examples/cxx/CMakeLists.txt index 40836c68e..fa4490ff8 100644 --- a/examples/cxx/CMakeLists.txt +++ b/examples/cxx/CMakeLists.txt @@ -22,6 +22,7 @@ add_subdirectory(domains) add_subdirectory(event) add_subdirectory(event_multiplexing) add_subdirectory(event_based_communication) +add_subdirectory(health_monitoring) add_subdirectory(publish_subscribe) add_subdirectory(publish_subscribe_dynamic_data) add_subdirectory(publish_subscribe_with_user_header) diff --git a/examples/cxx/event_based_communication/src/pubsub_event.hpp b/examples/cxx/event_based_communication/src/pubsub_event.hpp index e180c1f12..8a11f4a73 100644 --- a/examples/cxx/event_based_communication/src/pubsub_event.hpp +++ b/examples/cxx/event_based_communication/src/pubsub_event.hpp @@ -26,7 +26,7 @@ enum class PubSubEvent : uint8_t { SentSample = 4, ReceivedSample = 5, SentHistory = 6, - Unknown + Unknown = 7 }; namespace iox { diff --git a/examples/cxx/event_multiplexing/src/wait.cpp b/examples/cxx/event_multiplexing/src/wait.cpp index 00b661a2e..cf25bf1f2 100644 --- a/examples/cxx/event_multiplexing/src/wait.cpp +++ b/examples/cxx/event_multiplexing/src/wait.cpp @@ -22,8 +22,6 @@ #include "iox2/service_type.hpp" #include "iox2/waitset.hpp" -constexpr iox::units::Duration CYCLE_TIME = iox::units::Duration::fromSeconds(1); - // NOLINTBEGIN struct Args { IOX_CLI_DEFINITION(Args); @@ -42,7 +40,6 @@ auto main(int argc, char** argv) -> int { using namespace iox2; auto args = Args::parse(argc, argv, "Notifier of the event multiplexing example."); - auto event_id = EventId(args.event_id()); auto service_name_1 = ServiceName::create(args.service1().c_str()).expect("valid service name"); auto service_name_2 = ServiceName::create(args.service2().c_str()).expect("valid service name"); diff --git a/examples/cxx/health_monitoring/BUILD.bazel b/examples/cxx/health_monitoring/BUILD.bazel new file mode 100644 index 000000000..b54cbadbc --- /dev/null +++ b/examples/cxx/health_monitoring/BUILD.bazel @@ -0,0 +1,61 @@ +# Copyright (c) 2024 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache Software License 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0, or the MIT license +# which is available at https://opensource.org/licenses/MIT. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT + +load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") + +cc_binary( + name = "example_cxx_health_monitoring_central_daemon", + srcs = [ + "src/central_daemon.cpp", + "src/pubsub_event.hpp" + ], + deps = [ + "@iceoryx//:iceoryx_hoofs", + "//:iceoryx2-cxx-static", + ], +) + +cc_binary( + name = "example_cxx_health_monitoring_publisher_1", + srcs = [ + "src/publisher_1.cpp", + "src/pubsub_event.hpp" + ], + deps = [ + "@iceoryx//:iceoryx_hoofs", + "//:iceoryx2-cxx-static", + ], +) + +cc_binary( + name = "example_cxx_health_monitoring_publisher_2", + srcs = [ + "src/publisher_2.cpp", + "src/pubsub_event.hpp" + ], + deps = [ + "@iceoryx//:iceoryx_hoofs", + "//:iceoryx2-cxx-static", + ], +) + +cc_binary( + name = "example_cxx_health_monitoring_subscriber", + srcs = [ + "src/subscriber.cpp", + "src/pubsub_event.hpp" + ], + deps = [ + "@iceoryx//:iceoryx_hoofs", + "//:iceoryx2-cxx-static", + ], +) diff --git a/examples/cxx/health_monitoring/CMakeLists.txt b/examples/cxx/health_monitoring/CMakeLists.txt new file mode 100644 index 000000000..22f3cc417 --- /dev/null +++ b/examples/cxx/health_monitoring/CMakeLists.txt @@ -0,0 +1,28 @@ +# Copyright (c) 2024 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache Software License 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0, or the MIT license +# which is available at https://opensource.org/licenses/MIT. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT + +cmake_minimum_required(VERSION 3.22) +project(example_cxx_health_monitoring LANGUAGES CXX) + +find_package(iceoryx2-cxx 0.4.1 REQUIRED) + +add_executable(example_cxx_health_monitoring_central_daemon src/central_daemon.cpp) +target_link_libraries(example_cxx_health_monitoring_central_daemon iceoryx2-cxx::static-lib-cxx) + +add_executable(example_cxx_health_monitoring_publisher_1 src/publisher_1.cpp) +target_link_libraries(example_cxx_health_monitoring_publisher_1 iceoryx2-cxx::static-lib-cxx) + +add_executable(example_cxx_health_monitoring_publisher_2 src/publisher_2.cpp) +target_link_libraries(example_cxx_health_monitoring_publisher_2 iceoryx2-cxx::static-lib-cxx) + +add_executable(example_cxx_health_monitoring_subscriber src/subscriber.cpp) +target_link_libraries(example_cxx_health_monitoring_subscriber iceoryx2-cxx::static-lib-cxx) diff --git a/examples/cxx/health_monitoring/README.md b/examples/cxx/health_monitoring/README.md new file mode 100644 index 000000000..66f78b039 --- /dev/null +++ b/examples/cxx/health_monitoring/README.md @@ -0,0 +1,140 @@ +# Health Monitoring + +Before proceeding, all dependencies need to be installed. You can find +instructions in the [C++ Examples Readme](../README.md). + +This example demonstrates how to create a robust system using iceoryx2. +A central daemon pre-creates all communication resources to ensure that every +required resource, such as memory, is available as soon as the application +starts. +Additionally, the subscriber is immediately informed if one of the processes +it depends on has crashed. Even if the central daemon itself crashes, +communication can continue without any restrictions. Thanks to the +decentralized API of iceoryx2, the subscriber can take over the role of the +central daemon and continue monitoring all processes. + +The communication must also be reliable, and we expect publishers to provide +updates at regular intervals. If a publisher misses a deadline, we want to be +informed immediately. This situation can occur if the system is under heavy +load or if a process has crashed. + +This example is more advanced and consists of four components: + +* `central_daemon` - Must run first. It creates all communication resources and + monitors all nodes/processes. +* `publisher_1` - Sends data at a specific frequency on `service_1`. +* `publisher_2` - Sends data at a specific frequency on `service_2`. +* `subscriber` - Connects to `service_1` and `service_2` and expects new samples + within a specific time. If no sample arrives, it proactively checks for dead + nodes. + +```ascii ++----------------+ creates ........................... +| central_daemon | ----------> : communication resources : ++----------------+ ........................... + | ^ + | opens | + | +-----------------+--------------+ + | | | | + | +-------------+ +-------------+ +------------+ + | | publisher_1 | | publisher_2 | | subscriber | + | +-------------+ +-------------+ +------------+ + | ^ ^ ^ + | monitores | | | + +-------------+-------------------+-----------------+ +``` + +## Running The Example + +> [!CAUTION] +> Every payload you transmit with iceoryx2 must be compatible with shared +> memory. Specifically, it must: +> +> * be self contained, no heap, no pointers to external sources +> * have a uniform memory representation -> `#[repr(C)]` +> * not use pointers to manage their internal structure +> +> Data types like `String` or `Vec` will cause undefined behavior and may +> result in segmentation faults. We provide alternative data types that are +> compatible with shared memory. See the +> [complex data type example](../complex_data_types) for guidance on how to +> use them. + +First you have to build the C++ examples: + +```sh +cmake -S . -B target/ffi/build -DBUILD_EXAMPLES=ON +cmake --build target/ffi/build +``` + +For this example, you need to open five separate terminals. + +## Terminal 1: Central Daemon - Create All Communication Resources + +Run the central daemon, which sets up all communication resources and monitors +processes. + +```sh +./target/ffi/build/examples/cxx/health_monitoring/example_cxx_health_monitoring_central_daemon +``` + +## Terminal 2: Publisher 1 + +Run the first publisher, which sends data on `service_1`. + +```sh +./target/ffi/build/examples/cxx/health_monitoring/example_cxx_health_monitoring_publisher_1 +``` + +## Terminal 3: Publisher 2 + +Run the second publisher, which sends data on `service_2`. + +```sh +./target/ffi/build/examples/cxx/health_monitoring/example_cxx_health_monitoring_publisher_2 +``` + +## Terminal 4: Subscriber + +Run the subscriber, which listens to both `service_1` and `service_2`. + +```sh +./target/ffi/build/examples/cxx/health_monitoring/example_cxx_health_monitoring_subscriber +``` + +## Terminal 5: Simulate Process Crashes + +Send a `SIGKILL` signal to `publisher_1` to simulate a fatal crash. This +ensures that the process is unable to clean up any resources. + +```sh +killall -9 example_cxx_health_monitoring_publisher_1 +``` + +After running this command: + +1. The `central_daemon` will detect that the process has crashed and print: + ```ascii + detected dead node: Some(NodeName { value: "publisher 1" }) + ``` + The event service is configured to emit a `PubSub::ProcessDied` event when a + process is identified as dead. + +2. On the `subscriber` side, you will see the message: + ```ascii + ServiceName { value: "service_1" }: process died! + ``` + +3. Since `publisher_1` is no longer sending messages, the subscriber will also + regularly print another message indicating that `service_1` has violated + the contract because no new samples are being received. + +Feel free to run multiple instances of publisher or subscriber processes +simultaneously to explore how iceoryx2 handles publisher-subscriber +communication efficiently. + +You may hit the maximum supported number of ports when too many publisher or +subscriber processes run. Take a look at the [iceoryx2 config](../../../config) +to set the limits globally or at the +[API of the Service builder](https://docs.rs/iceoryx2/latest/iceoryx2/service/index.html) +to set them for a single service. diff --git a/examples/cxx/health_monitoring/src/central_daemon.cpp b/examples/cxx/health_monitoring/src/central_daemon.cpp new file mode 100644 index 000000000..e90091b81 --- /dev/null +++ b/examples/cxx/health_monitoring/src/central_daemon.cpp @@ -0,0 +1,110 @@ +// Copyright (c) 2024 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache Software License 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license +// which is available at https://opensource.org/licenses/MIT. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + +#include + +#include "iox/duration.hpp" +#include "iox2/node.hpp" +#include "iox2/service_name.hpp" +#include "iox2/service_type.hpp" +#include "iox2/waitset.hpp" +#include "pubsub_event.hpp" + +using namespace iox2; + +constexpr iox::units::Duration CYCLE_TIME = iox::units::Duration::fromMilliseconds(100); + +namespace { +void find_and_cleanup_dead_nodes(); +} + +auto main() -> int { + auto service_name_1 = ServiceName::create("service_1").expect(""); + auto service_name_2 = ServiceName::create("service_2").expect(""); + + auto node = NodeBuilder() + .name(NodeName::create("central daemon").expect("")) + .create() + .expect("successful node creation"); + + // The central daemon is responsible to create all services before hand and the other processes + // just open the communication resources and start communicating. + auto service_pubsub_1 = node.service_builder(service_name_1) + .publish_subscribe() + // We use here open_or_create so that, in case of a crash of the central daemon, it can + // be restarted. + .open_or_create() + .expect("successful service creation/opening"); + + auto service_event_1 = node.service_builder(service_name_1) + .event() + // Whenever a new notifier is created the PublisherConnected event is emitted. this makes + // sense since in this example a notifier is always created after a new publisher was + // created. + // The task of the notifier/event is it to inform and wake up other processes when + // certain system event have happened. + .notifier_created_event(iox::into(PubSubEvent::PublisherConnected)) + .notifier_dropped_event(iox::into(PubSubEvent::PublisherDisconnected)) + // This event is emitted when either the central daemon or a decentralized process + // detects a dead node and cleaned up all of its stale resources succesfully. + .notifier_dead_event(iox::into(PubSubEvent::ProcessDied)) + .open_or_create() + .expect("successful service creation/opening"); + + auto service_pubsub_2 = node.service_builder(service_name_2) + .publish_subscribe() + .open_or_create() + .expect("successful service creation/opening"); + + auto service_event_2 = node.service_builder(service_name_2) + .event() + .notifier_created_event(iox::into(PubSubEvent::PublisherConnected)) + .notifier_dropped_event(iox::into(PubSubEvent::PublisherDisconnected)) + .notifier_dead_event(iox::into(PubSubEvent::ProcessDied)) + .open_or_create() + .expect("successful service creation/opening"); + + auto waitset = WaitSetBuilder().create().expect(""); + auto cycle_guard = waitset.attach_interval(CYCLE_TIME); + + std::cout << "Central daemon up and running." << std::endl; + waitset + // The only task of our central daemon is it to monitor all running nodes and cleanup their + // resources if a process has died. + // + // Since we added the notifier_dead_event to the service, all listeners, that are waiting + // on a service where one participant has died, will be woken up and they receive + // the PubSubEvent::ProcessDied + .wait_and_process([](auto) { + find_and_cleanup_dead_nodes(); + return CallbackProgression::Continue; + }) + .expect(""); + + std::cout << "exit" << std::endl; + + return 0; +} + +namespace { +void find_and_cleanup_dead_nodes() { + Node::list(Config::global_config(), [](auto node_state) { + node_state.dead([](auto view) { + std::cout << "detected dead node: "; + view.details().and_then([](const auto& details) { std::cout << details.name().to_string().c_str(); }); + std::cout << std::endl; + view.remove_stale_resources().expect(""); + }); + return CallbackProgression::Continue; + }).expect(""); +} +} // namespace diff --git a/examples/cxx/health_monitoring/src/publisher_1.cpp b/examples/cxx/health_monitoring/src/publisher_1.cpp new file mode 100644 index 000000000..cb2c46aa3 --- /dev/null +++ b/examples/cxx/health_monitoring/src/publisher_1.cpp @@ -0,0 +1,63 @@ +// Copyright (c) 2024 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache Software License 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license +// which is available at https://opensource.org/licenses/MIT. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + +#include "iox/duration.hpp" +#include "iox2/node.hpp" +#include "iox2/service_name.hpp" +#include "iox2/service_type.hpp" +#include "iox2/waitset.hpp" +#include "pubsub_event.hpp" + +#include + +constexpr iox::units::Duration CYCLE_TIME = iox::units::Duration::fromMilliseconds(1000); + +auto main() -> int { + using namespace iox2; + auto service_name = ServiceName::create("service_1").expect(""); + auto node = NodeBuilder() + .name(NodeName::create("publisher 1").expect("")) + .create() + .expect("successful node creation"); + + auto service = open_service(node, service_name); + + auto publisher = service.pubsub.publisher_builder().create().expect(""); + auto notifier = service.event + .notifier_builder() + // we only want to notify the other side explicitly when we have sent a sample + // so we can define it as default event id + .default_event_id(iox::into(PubSubEvent::SentSample)) + .create() + .expect(""); + auto counter = 0; + + auto waitset = WaitSetBuilder().create().expect(""); + + // we only want to notify the other side explicitly when we have sent a sample + // so we can define it as default event id + auto cycle_guard = waitset.attach_interval(CYCLE_TIME); + + waitset + .wait_and_process([&](auto) { + std::cout << service_name.to_string().c_str() << ": Send sample " << counter << " ..." << std::endl; + publisher.send_copy(counter).expect(""); + notifier.notify().expect(""); + counter += 1; + return CallbackProgression::Continue; + }) + .expect(""); + + std::cout << "exit" << std::endl; + + return 0; +} diff --git a/examples/cxx/health_monitoring/src/publisher_2.cpp b/examples/cxx/health_monitoring/src/publisher_2.cpp new file mode 100644 index 000000000..bbee48cb0 --- /dev/null +++ b/examples/cxx/health_monitoring/src/publisher_2.cpp @@ -0,0 +1,63 @@ +// Copyright (c) 2024 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache Software License 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license +// which is available at https://opensource.org/licenses/MIT. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + +#include "iox/duration.hpp" +#include "iox2/node.hpp" +#include "iox2/service_name.hpp" +#include "iox2/service_type.hpp" +#include "iox2/waitset.hpp" +#include "pubsub_event.hpp" + +#include + +constexpr iox::units::Duration CYCLE_TIME = iox::units::Duration::fromMilliseconds(1500); + +auto main() -> int { + using namespace iox2; + auto service_name = ServiceName::create("service_2").expect(""); + auto node = NodeBuilder() + .name(NodeName::create("publisher 2").expect("")) + .create() + .expect("successful node creation"); + + auto service = open_service(node, service_name); + + auto publisher = service.pubsub.publisher_builder().create().expect(""); + auto notifier = service.event + .notifier_builder() + // we only want to notify the other side explicitly when we have sent a sample + // so we can define it as default event id + .default_event_id(iox::into(PubSubEvent::SentSample)) + .create() + .expect(""); + auto counter = 1000000; // NOLINT, magic number is fine in an example + + auto waitset = WaitSetBuilder().create().expect(""); + + // we only want to notify the other side explicitly when we have sent a sample + // so we can define it as default event id + auto cycle_guard = waitset.attach_interval(CYCLE_TIME); + + waitset + .wait_and_process([&](auto) { + std::cout << service_name.to_string().c_str() << ": Send sample " << counter << " ..." << std::endl; + publisher.send_copy(counter).expect(""); + notifier.notify().expect(""); + counter += 1; + return CallbackProgression::Continue; + }) + .expect(""); + + std::cout << "exit" << std::endl; + + return 0; +} diff --git a/examples/cxx/health_monitoring/src/pubsub_event.hpp b/examples/cxx/health_monitoring/src/pubsub_event.hpp new file mode 100644 index 000000000..cde5ef0b7 --- /dev/null +++ b/examples/cxx/health_monitoring/src/pubsub_event.hpp @@ -0,0 +1,56 @@ +// Copyright (c) 2024 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache Software License 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license +// which is available at https://opensource.org/licenses/MIT. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + +#ifndef IOX2_EXAMPLE_HEALTH_MONITORING_PUBSUB_EVENT_HPP +#define IOX2_EXAMPLE_HEALTH_MONITORING_PUBSUB_EVENT_HPP + +#include "iox/into.hpp" +#include "iox2/event_id.hpp" +#include "iox2/node.hpp" +#include "iox2/service_name.hpp" + +#include + +enum class PubSubEvent : uint8_t { + PublisherConnected = 0, + PublisherDisconnected = 1, + SubscriberConnected = 2, + SubscriberDisconnected = 3, + SentSample = 4, + ReceivedSample = 5, + SentHistory = 6, + ProcessDied = 7, + Unknown = 8, +}; + +struct ServiceTuple { + iox2::PortFactoryEvent event; + iox2::PortFactoryPublishSubscribe pubsub; +}; + +inline auto open_service(const iox2::Node& node, const iox2::ServiceName& service_name) + -> ServiceTuple { + auto service_pubsub = node.service_builder(service_name).publish_subscribe().open().expect(""); + auto service_event = node.service_builder(service_name).event().open().expect(""); + + return { std::move(service_event), std::move(service_pubsub) }; +} + +namespace iox { +template <> +inline auto from(const PubSubEvent value) noexcept -> iox2::EventId { + return iox2::EventId(static_cast(value)); +} +} // namespace iox + + +#endif diff --git a/examples/cxx/health_monitoring/src/subscriber.cpp b/examples/cxx/health_monitoring/src/subscriber.cpp new file mode 100644 index 000000000..8d1506f9c --- /dev/null +++ b/examples/cxx/health_monitoring/src/subscriber.cpp @@ -0,0 +1,132 @@ +// Copyright (c) 2024 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache Software License 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license +// which is available at https://opensource.org/licenses/MIT. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + +#include + +#include "iox/duration.hpp" +#include "iox2/node.hpp" +#include "iox2/service_name.hpp" +#include "iox2/service_type.hpp" +#include "iox2/waitset.hpp" +#include "pubsub_event.hpp" + +using namespace iox2; + +constexpr iox::units::Duration REACTION_BUFFER = iox::units::Duration::fromMilliseconds(100); +constexpr iox::units::Duration CYCLE_TIME_1 = iox::units::Duration::fromMilliseconds(1000) + REACTION_BUFFER; +constexpr iox::units::Duration CYCLE_TIME_2 = iox::units::Duration::fromMilliseconds(1500) + REACTION_BUFFER; + +namespace { +void find_and_cleanup_dead_nodes(); +void handle_incoming_events(Listener& listener, + const Subscriber& subscriber, + const ServiceName& service_name); +} // namespace + +auto main() -> int { + auto service_name_1 = ServiceName::create("service_1").expect(""); + auto service_name_2 = ServiceName::create("service_2").expect(""); + + auto node = NodeBuilder() + .name(NodeName::create("subscruber").expect("")) + .create() + .expect("successful node creation"); + + // open a pubsub and an event service with the same name + auto service_1 = open_service(node, service_name_1); + auto service_2 = open_service(node, service_name_2); + + auto subscriber_1 = service_1.pubsub.subscriber_builder().create().expect(""); + auto subscriber_2 = service_2.pubsub.subscriber_builder().create().expect(""); + auto listener_1 = service_1.event.listener_builder().create().expect(""); + auto listener_2 = service_2.event.listener_builder().create().expect(""); + + auto waitset = WaitSetBuilder().create().expect(""); + + // we expect that the listener receive a message sent event after at most CYCLE_TIME_X + // so we add it as a deadline + auto listener_1_guard = waitset.attach_deadline(listener_1, CYCLE_TIME_1).expect(""); + auto listener_2_guard = waitset.attach_deadline(listener_2, CYCLE_TIME_2).expect(""); + + auto missed_deadline = [](const ServiceName& service_name, const iox::units::Duration& cycle_time) { + std::cout << service_name.to_string().c_str() << ": voilated contract and did not send a message after " + << cycle_time << std::endl; + }; + + auto on_event = [&](const WaitSetAttachmentId& attachment_id) { + if (attachment_id.has_missed_deadline(listener_1_guard)) { + missed_deadline(service_name_1, CYCLE_TIME_1); + // one cause of a deadline it can be a dead node. usually our "central_daemon" would + // take care of monitoring but when the node and the central daemon crashed we take + // over here and check for dead nodes + find_and_cleanup_dead_nodes(); + } + + if (attachment_id.has_missed_deadline(listener_2_guard)) { + missed_deadline(service_name_2, CYCLE_TIME_2); + find_and_cleanup_dead_nodes(); + } + + if (attachment_id.has_event_from(listener_1_guard)) { + // in this function we either print out the received sample or the event that has + // occurred like, publisher connected/disconnected or a process was identified as dead + handle_incoming_events(listener_1, subscriber_1, service_name_1); + } + + if (attachment_id.has_event_from(listener_2_guard)) { + handle_incoming_events(listener_2, subscriber_2, service_name_2); + } + + return CallbackProgression::Continue; + }; + + waitset.wait_and_process(on_event).expect(""); + + std::cout << "exit" << std::endl; + + return 0; +} + +namespace { +void handle_incoming_events(Listener& listener, + const Subscriber& subscriber, + const ServiceName& service_name) { + listener + .try_wait_all([&](auto event_id) { + if (event_id == iox::into(PubSubEvent::ProcessDied)) { + std::cout << service_name.to_string().c_str() << ": process died!" << std::endl; + } else if (event_id == iox::into(PubSubEvent::PublisherConnected)) { + std::cout << service_name.to_string().c_str() << ": publisher connected!" << std::endl; + } else if (event_id == iox::into(PubSubEvent::PublisherDisconnected)) { + std::cout << service_name.to_string().c_str() << ": publisher disconnected!" << std::endl; + } else if (event_id == iox::into(PubSubEvent::SentSample)) { + subscriber.receive().expect("").and_then([&](auto& sample) { + std::cout << service_name.to_string().c_str() << ": Received sample " << *sample << " ..." + << std::endl; + }); + } + }) + .expect(""); +} + +void find_and_cleanup_dead_nodes() { + Node::list(Config::global_config(), [](auto node_state) { + node_state.dead([](auto view) { + std::cout << "detected dead node: "; + view.details().and_then([](const auto& details) { std::cout << details.name().to_string().c_str(); }); + std::cout << std::endl; + view.remove_stale_resources().expect(""); + }); + return CallbackProgression::Continue; + }).expect(""); +} +} // namespace diff --git a/examples/rust/health_monitoring/README.md b/examples/rust/health_monitoring/README.md index 776958610..e2c5a6ede 100644 --- a/examples/rust/health_monitoring/README.md +++ b/examples/rust/health_monitoring/README.md @@ -118,3 +118,13 @@ After running this command: 3. Since `publisher_1` is no longer sending messages, the subscriber will also regularly print another message indicating that `service_1` has violated the contract because no new samples are being received. + +Feel free to run multiple instances of publisher or subscriber processes +simultaneously to explore how iceoryx2 handles publisher-subscriber +communication efficiently. + +You may hit the maximum supported number of ports when too many publisher or +subscriber processes run. Take a look at the [iceoryx2 config](../../../config) +to set the limits globally or at the +[API of the Service builder](https://docs.rs/iceoryx2/latest/iceoryx2/service/index.html) +to set them for a single service. diff --git a/examples/rust/health_monitoring/central_daemon.rs b/examples/rust/health_monitoring/central_daemon.rs index 912559ae7..14886365d 100644 --- a/examples/rust/health_monitoring/central_daemon.rs +++ b/examples/rust/health_monitoring/central_daemon.rs @@ -21,7 +21,7 @@ fn main() -> Result<(), Box> { let service_name_2 = ServiceName::new("service_2")?; let node = NodeBuilder::new() - .name(&"watchdog and resource creator".try_into()?) + .name(&"central daemon".try_into()?) .create::()?; // The central daemon is responsible to create all services before hand and the other processes diff --git a/iceoryx2-ffi/cxx/include/iox2/enum_translation.hpp b/iceoryx2-ffi/cxx/include/iox2/enum_translation.hpp index c14db3c45..6f996356b 100644 --- a/iceoryx2-ffi/cxx/include/iox2/enum_translation.hpp +++ b/iceoryx2-ffi/cxx/include/iox2/enum_translation.hpp @@ -320,7 +320,12 @@ constexpr auto from(const int value) noexcept return iox2::EventOpenOrCreateError::OpenExceedsMaxNumberOfNodes; case iox2_event_open_or_create_error_e_O_IS_MARKED_FOR_DESTRUCTION: return iox2::EventOpenOrCreateError::OpenIsMarkedForDestruction; - + case iox2_event_open_or_create_error_e_O_INCOMPATIBLE_NOTIFIER_CREATED_EVENT: + return iox2::EventOpenOrCreateError::OpenIncompatibleNotifierCreatedEvent; + case iox2_event_open_or_create_error_e_O_INCOMPATIBLE_NOTIFIER_DROPPED_EVENT: + return iox2::EventOpenOrCreateError::OpenIncompatibleNotifierDroppedEvent; + case iox2_event_open_or_create_error_e_O_INCOMPATIBLE_NOTIFIER_DEAD_EVENT: + return iox2::EventOpenOrCreateError::OpenIncompatibleNotifierDeadEvent; case iox2_event_open_or_create_error_e_C_SERVICE_IN_CORRUPTED_STATE: return iox2::EventOpenOrCreateError::CreateServiceInCorruptedState; case iox2_event_open_or_create_error_e_C_INTERNAL_FAILURE: diff --git a/iceoryx2-ffi/cxx/include/iox2/port_factory_publish_subscribe.hpp b/iceoryx2-ffi/cxx/include/iox2/port_factory_publish_subscribe.hpp index 2c51affd0..431c566de 100644 --- a/iceoryx2-ffi/cxx/include/iox2/port_factory_publish_subscribe.hpp +++ b/iceoryx2-ffi/cxx/include/iox2/port_factory_publish_subscribe.hpp @@ -151,7 +151,8 @@ inline auto PortFactoryPublishSubscribe::dynamic_config( template inline auto PortFactoryPublishSubscribe::nodes( - const iox::function)>& callback) const -> iox::expected { + [[maybe_unused]] const iox::function)>& callback) const + -> iox::expected { IOX_TODO(); } diff --git a/iceoryx2-ffi/cxx/include/iox2/service_builder_event_error.hpp b/iceoryx2-ffi/cxx/include/iox2/service_builder_event_error.hpp index 6fce97a59..30cdf0285 100644 --- a/iceoryx2-ffi/cxx/include/iox2/service_builder_event_error.hpp +++ b/iceoryx2-ffi/cxx/include/iox2/service_builder_event_error.hpp @@ -104,6 +104,15 @@ enum class EventOpenOrCreateError : uint8_t { /// The [`AttributeVerifier`] required attributes that the [`Service`] does /// not satisfy. OpenIncompatibleAttributes, + /// The event id that is emitted for a newly created [`Notifier`](crate::port::notifier::Notifier) + /// does not fit the required event id. + OpenIncompatibleNotifierCreatedEvent, + /// The event id that is emitted if a [`Notifier`](crate::port::notifier::Notifier) is dropped + /// does not fit the required event id. + OpenIncompatibleNotifierDroppedEvent, + /// The event id that is emitted if a [`Notifier`](crate::port::notifier::Notifier) is + /// identified as dead does not fit the required event id. + OpenIncompatibleNotifierDeadEvent, /// Errors that indicate either an implementation issue or a wrongly /// configured system. OpenInternalFailure, diff --git a/iceoryx2-ffi/cxx/src/messaging_pattern.cpp b/iceoryx2-ffi/cxx/src/messaging_pattern.cpp index 604c0385c..18b6177f2 100644 --- a/iceoryx2-ffi/cxx/src/messaging_pattern.cpp +++ b/iceoryx2-ffi/cxx/src/messaging_pattern.cpp @@ -16,8 +16,10 @@ auto operator<<(std::ostream& stream, const iox2::MessagingPattern& value) -> st switch (value) { case iox2::MessagingPattern::PublishSubscribe: stream << "iox2::MessagingPattern::PublishSubscribe"; + break; case iox2::MessagingPattern::Event: stream << "iox2::MessagingPattern::Event"; + break; } return stream; } diff --git a/iceoryx2-ffi/cxx/src/node_name.cpp b/iceoryx2-ffi/cxx/src/node_name.cpp index c5a88c830..6e972ea9c 100644 --- a/iceoryx2-ffi/cxx/src/node_name.cpp +++ b/iceoryx2-ffi/cxx/src/node_name.cpp @@ -91,7 +91,7 @@ auto NodeName::create_impl(const char* value, size_t value_len) -> iox::expected iox2_node_name_h handle {}; const auto ret_val = iox2_node_name_new(nullptr, value, value_len, &handle); if (ret_val == IOX2_OK) { - return iox::ok(std::move(NodeName { handle })); + return iox::ok(NodeName { handle }); } return iox::err(iox::into(ret_val)); diff --git a/iceoryx2-ffi/cxx/src/port_factory_event.cpp b/iceoryx2-ffi/cxx/src/port_factory_event.cpp index 43c9cb1f5..be7e2fd03 100644 --- a/iceoryx2-ffi/cxx/src/port_factory_event.cpp +++ b/iceoryx2-ffi/cxx/src/port_factory_event.cpp @@ -79,7 +79,7 @@ auto PortFactoryEvent::dynamic_config() const -> const DynamicConfigEvent& { } template -auto PortFactoryEvent::nodes(const iox::function)>& callback) const +auto PortFactoryEvent::nodes([[maybe_unused]] const iox::function)>& callback) const -> iox::expected { IOX_TODO(); } diff --git a/iceoryx2-ffi/cxx/src/service.cpp b/iceoryx2-ffi/cxx/src/service.cpp index 2532d5a68..9df8a59d0 100644 --- a/iceoryx2-ffi/cxx/src/service.cpp +++ b/iceoryx2-ffi/cxx/src/service.cpp @@ -38,9 +38,9 @@ auto Service::does_exist(const ServiceName& service_name, } template -auto Service::details(const ServiceName& service_name, - const ConfigView config, - const MessagingPattern messaging_pattern) +auto Service::details([[maybe_unused]] const ServiceName& service_name, + [[maybe_unused]] const ConfigView config, + [[maybe_unused]] const MessagingPattern messaging_pattern) -> iox::expected>, ServiceDetailsError> { IOX_TODO(); } diff --git a/iceoryx2-ffi/cxx/tests/src/node_state_tests.cpp b/iceoryx2-ffi/cxx/tests/src/node_state_tests.cpp index a19cca031..df8e83341 100644 --- a/iceoryx2-ffi/cxx/tests/src/node_state_tests.cpp +++ b/iceoryx2-ffi/cxx/tests/src/node_state_tests.cpp @@ -23,7 +23,7 @@ class NodeStateTest : public ::testing::Test { static constexpr ServiceType TYPE = T::TYPE; }; -TYPED_TEST_SUITE(NodeStateTest, iox2_testing::ServiceTypes); +TYPED_TEST_SUITE(NodeStateTest, iox2_testing::ServiceTypes, ); TYPED_TEST(NodeStateTest, alive_node_works) { constexpr ServiceType SERVICE_TYPE = TestFixture::TYPE; diff --git a/iceoryx2-ffi/cxx/tests/src/node_tests.cpp b/iceoryx2-ffi/cxx/tests/src/node_tests.cpp index 85d6c9c60..31b4dfcc5 100644 --- a/iceoryx2-ffi/cxx/tests/src/node_tests.cpp +++ b/iceoryx2-ffi/cxx/tests/src/node_tests.cpp @@ -26,7 +26,7 @@ class NodeTest : public ::testing::Test { static constexpr ServiceType TYPE = T::TYPE; }; -TYPED_TEST_SUITE(NodeTest, iox2_testing::ServiceTypes); +TYPED_TEST_SUITE(NodeTest, iox2_testing::ServiceTypes, ); TYPED_TEST(NodeTest, node_name_is_applied) { constexpr ServiceType SERVICE_TYPE = TestFixture::TYPE; @@ -70,7 +70,7 @@ TYPED_TEST(NodeTest, created_nodes_can_be_listed) { } uint64_t counter = 0; - auto result = Node::list(Config::global_config(), [&](const auto& node_state) { + auto result = Node::list(Config::global_config(), [&](const auto&) { counter++; return CallbackProgression::Continue; }); diff --git a/iceoryx2-ffi/cxx/tests/src/service_event_tests.cpp b/iceoryx2-ffi/cxx/tests/src/service_event_tests.cpp index 3a4d0f722..5d364e739 100644 --- a/iceoryx2-ffi/cxx/tests/src/service_event_tests.cpp +++ b/iceoryx2-ffi/cxx/tests/src/service_event_tests.cpp @@ -51,7 +51,7 @@ struct ServiceEventTest : public ::testing::Test { template std::atomic ServiceEventTest::event_id_counter { 0 }; -TYPED_TEST_SUITE(ServiceEventTest, iox2_testing::ServiceTypes); +TYPED_TEST_SUITE(ServiceEventTest, iox2_testing::ServiceTypes, ); TYPED_TEST(ServiceEventTest, created_service_does_exist) { constexpr ServiceType SERVICE_TYPE = TestFixture::TYPE; @@ -414,7 +414,6 @@ TYPED_TEST(ServiceEventTest, service_can_be_opened_when_there_is_a_listener) { TYPED_TEST(ServiceEventTest, create_with_attributes_sets_attributes) { constexpr ServiceType SERVICE_TYPE = TestFixture::TYPE; - constexpr uint64_t NUMBER_OF_SUBSCRIBERS = 12; auto key = Attribute::Key("want to make your machine run faster:"); auto value = Attribute::Value("sudo rm -rf /"); @@ -443,7 +442,6 @@ TYPED_TEST(ServiceEventTest, create_with_attributes_sets_attributes) { TYPED_TEST(ServiceEventTest, open_fails_when_attributes_are_incompatible) { constexpr ServiceType SERVICE_TYPE = TestFixture::TYPE; - constexpr uint64_t NUMBER_OF_SUBSCRIBERS = 12; auto key = Attribute::Key("whats hypnotoad doing these days?"); auto value = Attribute::Value("eating hypnoflies?"); diff --git a/iceoryx2-ffi/cxx/tests/src/service_publish_subscribe_tests.cpp b/iceoryx2-ffi/cxx/tests/src/service_publish_subscribe_tests.cpp index bff645705..a4ce6247d 100644 --- a/iceoryx2-ffi/cxx/tests/src/service_publish_subscribe_tests.cpp +++ b/iceoryx2-ffi/cxx/tests/src/service_publish_subscribe_tests.cpp @@ -31,7 +31,7 @@ class ServicePublishSubscribeTest : public ::testing::Test { static constexpr ServiceType TYPE = T::TYPE; }; -TYPED_TEST_SUITE(ServicePublishSubscribeTest, iox2_testing::ServiceTypes); +TYPED_TEST_SUITE(ServicePublishSubscribeTest, iox2_testing::ServiceTypes, ); TYPED_TEST(ServicePublishSubscribeTest, created_service_does_exist) { constexpr ServiceType SERVICE_TYPE = TestFixture::TYPE; @@ -819,7 +819,6 @@ TYPED_TEST(ServicePublishSubscribeTest, publisher_does_not_reallocate_when_alloc TYPED_TEST(ServicePublishSubscribeTest, create_with_attributes_sets_attributes) { constexpr ServiceType SERVICE_TYPE = TestFixture::TYPE; - constexpr uint64_t NUMBER_OF_SUBSCRIBERS = 12; auto key = Attribute::Key("want to make your machine run faster:"); auto value = Attribute::Value("sudo rm -rf /"); @@ -848,7 +847,6 @@ TYPED_TEST(ServicePublishSubscribeTest, create_with_attributes_sets_attributes) TYPED_TEST(ServicePublishSubscribeTest, open_fails_when_attributes_are_incompatible) { constexpr ServiceType SERVICE_TYPE = TestFixture::TYPE; - constexpr uint64_t NUMBER_OF_SUBSCRIBERS = 12; auto key = Attribute::Key("whats hypnotoad doing these days?"); auto value = Attribute::Value("eating hypnoflies?"); diff --git a/iceoryx2-ffi/cxx/tests/src/unique_port_id_tests.cpp b/iceoryx2-ffi/cxx/tests/src/unique_port_id_tests.cpp index 8a318d8ff..aca298736 100644 --- a/iceoryx2-ffi/cxx/tests/src/unique_port_id_tests.cpp +++ b/iceoryx2-ffi/cxx/tests/src/unique_port_id_tests.cpp @@ -63,7 +63,7 @@ struct UniquePortIdTest : public ::testing::Test { // NOLINTEND(misc-non-private-member-variables-in-classes) }; -TYPED_TEST_SUITE(UniquePortIdTest, iox2_testing::ServiceTypes); +TYPED_TEST_SUITE(UniquePortIdTest, iox2_testing::ServiceTypes, ); TYPED_TEST(UniquePortIdTest, unique_port_id_value) { auto null_id = iox::vector { iox2::UNIQUE_PORT_ID_LENGTH, 0 }; diff --git a/iceoryx2-ffi/cxx/tests/src/waitset_tests.cpp b/iceoryx2-ffi/cxx/tests/src/waitset_tests.cpp index fabed1ff1..2bd024426 100644 --- a/iceoryx2-ffi/cxx/tests/src/waitset_tests.cpp +++ b/iceoryx2-ffi/cxx/tests/src/waitset_tests.cpp @@ -58,7 +58,7 @@ struct WaitSetTest : public ::testing::Test { // NOLINTEND(misc-non-private-member-variables-in-classes) }; -TYPED_TEST_SUITE(WaitSetTest, iox2_testing::ServiceTypes); +TYPED_TEST_SUITE(WaitSetTest, iox2_testing::ServiceTypes, ); TYPED_TEST(WaitSetTest, newly_created_waitset_is_empty) { auto sut = this->create_sut(); @@ -197,7 +197,7 @@ TYPED_TEST(WaitSetTest, does_not_block_longer_than_provided_timeout) { auto callback_called = false; auto result = sut.wait_and_process_once_with_timeout( - [&](auto attachment_id) -> CallbackProgression { + [&](auto) -> CallbackProgression { callback_called = true; return CallbackProgression::Stop; }, @@ -217,7 +217,7 @@ TYPED_TEST(WaitSetTest, blocks_until_interval_when_user_timeout_is_larger) { auto guard = sut.attach_interval(TIMEOUT).expect(""); auto callback_called = false; - auto result = sut.wait_and_process_once([&](auto attachment_id) -> CallbackProgression { + auto result = sut.wait_and_process_once([&](auto) -> CallbackProgression { callback_called = true; return CallbackProgression::Stop; }); @@ -284,6 +284,8 @@ TYPED_TEST(WaitSetTest, triggering_everything_works) { std::vector> listeners; std::vector> guards; + guards.reserve(NUMBER_OF_INTERVALS + NUMBER_OF_NOTIFICATIONS + NUMBER_OF_DEADLINES); + listeners.reserve(NUMBER_OF_NOTIFICATIONS + NUMBER_OF_DEADLINES); for (uint64_t idx = 0; idx < NUMBER_OF_INTERVALS; ++idx) { guards.emplace_back(sut.attach_interval(Duration::fromNanoseconds(1)).expect(""));