diff --git a/score/mw/com/test/common_test_resources/proxy_container.h b/score/mw/com/test/common_test_resources/proxy_container.h index 62665117c..0ec493cf1 100644 --- a/score/mw/com/test/common_test_resources/proxy_container.h +++ b/score/mw/com/test/common_test_resources/proxy_container.h @@ -13,15 +13,19 @@ #ifndef SCORE_MW_COM_TEST_METHODS_METHODS_TEST_RESOURCES_PROXY_CONTAINER_H #define SCORE_MW_COM_TEST_METHODS_METHODS_TEST_RESOURCES_PROXY_CONTAINER_H +#include "score/concurrency/notification.h" #include "score/mw/com/test/common_test_resources/fail_test.h" #include "score/mw/com/types.h" #include #include +#include #include #include #include +#include #include +#include namespace score::mw::com::test { @@ -39,6 +43,13 @@ class ProxyContainer return *proxy_; } + Proxy&& Extract() + { + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE(proxy_ != nullptr, + "Proxy was not successfully created! Cannot extract it!"); + return std::move(*proxy_); + } + private: std::unique_ptr handle_{nullptr}; std::mutex proxy_creation_mutex_{}; @@ -47,6 +58,131 @@ class ProxyContainer std::unique_ptr proxy_{nullptr}; }; +template +class ProxyStateChangeNotifier +{ + public: + explicit ProxyStateChangeNotifier(ProxyEventType& proxy_event) : proxy_event_{proxy_event} + { + auto state_change_handler = [this](const SubscriptionState new_state) -> bool { + std::cout << "Service state changed, new state: " << static_cast(new_state) << std::endl; + std::lock_guard lock(mutex_); + last_seen_state_ = new_state; + condition_variable_.notify_all(); + return true; + }; + proxy_event_.SetSubscriptionStateChangeHandler(state_change_handler); + } + + ~ProxyStateChangeNotifier() + { + proxy_event_.UnsetSubscriptionStateChangeHandler(); + } + + ProxyStateChangeNotifier(const ProxyStateChangeNotifier&) = delete; + ProxyStateChangeNotifier& operator=(const ProxyStateChangeNotifier&) = delete; + ProxyStateChangeNotifier(const ProxyStateChangeNotifier&&) = delete; + ProxyStateChangeNotifier& operator=(const ProxyStateChangeNotifier&&) = delete; + + bool WaitForStateChange(const score::cpp::stop_token& stop_token, SubscriptionState desired_state) + { + std::unique_lock lock(mutex_); + return condition_variable_.wait(lock, stop_token, [this, desired_state]() { + return last_seen_state_.has_value() && last_seen_state_.value() == desired_state; + }); + } + + private: + std::mutex mutex_{}; + concurrency::InterruptibleConditionalVariable condition_variable_{}; + std::optional last_seen_state_{}; + ProxyEventType& proxy_event_; +}; + +template +class ProxyEventReceiver +{ + public: + ProxyEventReceiver(ProxyEventType& proxy_event, std::string failure_message_prefix) + : failure_message_prefix_{std::move(failure_message_prefix)}, proxy_event_{proxy_event} + { + auto receive_handler = [&received_sample_notification = received_sample_notification_]() { + std::cout << "Received event notification" << std::endl; + received_sample_notification.notify(); + }; + proxy_event_.SetReceiveHandler(receive_handler); + } + + ~ProxyEventReceiver() + { + proxy_event_.UnsetReceiveHandler(); + } + + ProxyEventReceiver(const ProxyEventReceiver&) = delete; + ProxyEventReceiver& operator=(const ProxyEventReceiver&) = delete; + ProxyEventReceiver(const ProxyEventReceiver&&) = delete; + ProxyEventReceiver& operator=(const ProxyEventReceiver&&) = delete; + + void WaitForSamples(const score::cpp::stop_token& stop_token, const std::size_t num_samples_to_receive) + { + std::size_t received_count{0U}; + while (!stop_token.stop_requested()) + { + auto get_samples_result = proxy_event_.GetNewSamples( + [this](SamplePtr sample) { + GetNewSamplesCallback(std::move(sample)); + }, + num_samples_to_receive); + if (!get_samples_result.has_value()) + { + FailTest(failure_message_prefix_, " GetNewSamples failed: ", get_samples_result.error()); + } + + received_count += get_samples_result.value(); + std::cout << "Received " << get_samples_result.value() << " samples. " << received_count + << " samples so far" << std::endl; + + if (received_count == num_samples_to_receive) + { + break; + } + + const auto notification_received = received_sample_notification_.waitWithAbort(stop_token); + if (!notification_received) + { + continue; + } + + received_sample_notification_.reset(); + } + std::cout << "\nConsumer: Done receiving samples, received " << received_count << " samples in total\n"; + } + + private: + void GetNewSamplesCallback(SamplePtr sample) + { + if (sample == nullptr) + { + FailTest(failure_message_prefix_, " received null sample"); + } + const SampleType expected_value = latest_value_.has_value() ? latest_value_.value() + 1U : 1U; + if (*sample != expected_value) + { + FailTest(failure_message_prefix_, + " received value ", + *sample, + " does not match expected value ", + expected_value); + } + latest_value_ = *sample; + } + + std::string failure_message_prefix_; + concurrency::Notification received_sample_notification_{}; + std::optional latest_value_{}; + ProxyEventType& proxy_event_; +}; + template void ProxyContainer::CreateProxy(InstanceSpecifier instance_specifier, const std::string& failure_message_prefix) { diff --git a/score/mw/com/test/move_semantics/proxy_event/BUILD b/score/mw/com/test/move_semantics/proxy_event/BUILD new file mode 100644 index 000000000..14c60f7a6 --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/BUILD @@ -0,0 +1,167 @@ +# ******************************************************************************* +# Copyright (c) 2026 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 License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") +load("@score_baselibs//score/language/safecpp:toolchain_features.bzl", "COMPILER_WARNING_FEATURES") +load("//bazel/tools:json_schema_validator.bzl", "validate_json_schema_test") +load("//score/mw/com/test:pkg_application.bzl", "pkg_application") + +validate_json_schema_test( + name = "validate_config_schema", + json = "config/mw_com_config.json", + schema = "//score/mw/com:config_schema", + tags = ["lint"], +) + +cc_library( + name = "test_event_datatype", + srcs = ["test_event_datatype.cpp"], + hdrs = ["test_event_datatype.h"], + features = COMPILER_WARNING_FEATURES, + deps = [ + "//score/mw/com", + ], +) + +cc_library( + name = "test_parameters", + srcs = ["test_parameters.cpp"], + hdrs = ["test_parameters.h"], + features = COMPILER_WARNING_FEATURES, + deps = [ + "//score/mw/com", + "//score/mw/com/test/common_test_resources:command_line_parser", + "//score/mw/com/test/common_test_resources:fail_test", + ], +) + +cc_library( + name = "provider", + srcs = ["provider.cpp"], + hdrs = ["provider.h"], + features = COMPILER_WARNING_FEATURES, + deps = [ + ":test_event_datatype", + ":test_parameters", + "//score/mw/com", + "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:skeleton_container", + "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", + ], +) + +cc_library( + name = "consumer", + srcs = ["consumer.cpp"], + hdrs = ["consumer.h"], + features = COMPILER_WARNING_FEATURES, + deps = [ + ":test_event_datatype", + ":test_parameters", + "//score/mw/com", + "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:proxy_container", + "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", + ], +) + +cc_binary( + name = "main_provider", + srcs = ["main_provider.cpp"], + data = ["config/mw_com_config.json"], + features = COMPILER_WARNING_FEATURES + [ + "aborts_upon_exception", + ], + deps = [ + ":provider", + ":test_parameters", + "//score/mw/com", + "//score/mw/com/test/common_test_resources:assert_handler", + "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:stop_token_sig_term_handler", + ], +) + +cc_binary( + name = "main_consumer", + srcs = ["main_consumer.cpp"], + data = ["config/mw_com_config.json"], + features = COMPILER_WARNING_FEATURES + [ + "aborts_upon_exception", + ], + deps = [ + ":consumer", + ":test_parameters", + "//score/mw/com", + "//score/mw/com/test/common_test_resources:assert_handler", + "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:stop_token_sig_term_handler", + ], +) + +cc_binary( + name = "main_consumer_and_provider", + srcs = ["main_consumer_and_provider.cpp"], + data = ["config/mw_com_config.json"], + features = COMPILER_WARNING_FEATURES + [ + "aborts_upon_exception", + ], + deps = [ + ":consumer", + ":provider", + ":test_parameters", + "//score/mw/com", + "//score/mw/com/test/common_test_resources:assert_handler", + "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:stop_token_sig_term_handler", + ], +) + +pkg_application( + name = "main_provider-pkg", + app_name = "MainProviderApp", + bin = [":main_provider"], + etc = [ + "config/mw_com_config.json", + "config/logging.json", + ], + visibility = [ + "//score/mw/com/test/move_semantics/proxy_event:__subpackages__", + ], +) + +pkg_application( + name = "main_consumer-pkg", + app_name = "MainConsumerApp", + bin = [":main_consumer"], + etc = [ + "config/mw_com_config.json", + "config/logging.json", + ], + visibility = [ + "//score/mw/com/test/move_semantics/proxy_event:__subpackages__", + ], +) + +pkg_application( + name = "main_consumer_and_provider-pkg", + app_name = "MainConsumerAndProviderApp", + bin = [":main_consumer_and_provider"], + etc = [ + "config/mw_com_config.json", + "config/logging.json", + ], + visibility = [ + "//score/mw/com/test/move_semantics/proxy_event:__subpackages__", + ], +) diff --git a/score/mw/com/test/move_semantics/proxy_event/config/logging.json b/score/mw/com/test/move_semantics/proxy_event/config/logging.json new file mode 100644 index 000000000..b60fbd04b --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/config/logging.json @@ -0,0 +1,7 @@ +{ + "appId": "PRMS", + "appDesc": "proxy_event_move_semantics", + "logLevel": "kDebug", + "logLevelThresholdConsole": "kDebug", + "logMode": "kRemote|kConsole" +} diff --git a/score/mw/com/test/move_semantics/proxy_event/config/mw_com_config.json b/score/mw/com/test/move_semantics/proxy_event/config/mw_com_config.json new file mode 100644 index 000000000..51baa228c --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/config/mw_com_config.json @@ -0,0 +1,67 @@ +{ + "serviceTypes": [ + { + "serviceTypeName": "/test/move_semantics/proxy_event/MoveEventInterface", + "version": { + "major": 1, + "minor": 0 + }, + "bindings": [ + { + "binding": "SHM", + "serviceId": 2110, + "events": [ + { + "eventName": "moved_event", + "eventId": 1 + } + ] + } + ] + } + ], + "serviceInstances": [ + { + "instanceSpecifier": "test/move_semantics/proxy_event/MoveEventInterface", + "serviceTypeName": "/test/move_semantics/proxy_event/MoveEventInterface", + "version": { + "major": 1, + "minor": 0 + }, + "instances": [ + { + "instanceId": 1, + "asil-level": "QM", + "binding": "SHM", + "events": [ + { + "eventName": "moved_event", + "numberOfSampleSlots": 15, + "maxSubscribers": 1 + } + ], + "allowedConsumer": { + "QM": [ + 0 + ], + "B": [ + 0 + ] + }, + "allowedProvider": { + "QM": [ + 0 + ], + "B": [ + 0 + ] + } + } + ] + } + ], + "global": { + "asil-level": "QM", + "applicationID": 4011 + } +} diff --git a/score/mw/com/test/move_semantics/proxy_event/consumer.cpp b/score/mw/com/test/move_semantics/proxy_event/consumer.cpp new file mode 100644 index 000000000..92f8ff288 --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/consumer.cpp @@ -0,0 +1,105 @@ +/******************************************************************************** + * Copyright (c) 2026 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 License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/com/test/move_semantics/proxy_event/consumer.h" + +#include "score/mw/com/test/common_test_resources/fail_test.h" +#include "score/mw/com/test/common_test_resources/proxy_container.h" +#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" +#include "score/mw/com/test/move_semantics/proxy_event/test_event_datatype.h" +#include "score/mw/com/types.h" + +#include + +namespace score::mw::com::test +{ +namespace +{ + +const std::string kInterprocessNotificationShmPath{"/proxy_event_move_semantics_interprocess_notification"}; + +void RunConsumerMoveConstructProxyBeforeSubscribe(const InstanceSpecifier& instance_specifier, + const std::size_t num_samples_to_receive, + const std::size_t num_send_iterations, + const score::cpp::stop_token& stop_token) +{ + const auto name = filesystem::Path{instance_specifier.ToString()}.Filename().Native(); + auto process_synchronizer_result = + ProcessSynchronizer::Create(kInterprocessNotificationShmPath + std::string{name}); + if (!process_synchronizer_result.has_value()) + { + FailTest("proxy_event_move_semantics consumer failed: could not create ready synchronizer"); + } + + ExitFunctionGuard done_guard{[&process_synchronizer_result]() { + process_synchronizer_result->Notify(); + }}; + + ProxyContainer proxy_container{}; + + // Step 1. Find service and create proxy + std::cout << "\nConsumer: Step 1 - Find service and create proxy" << std::endl; + proxy_container.CreateProxy(kInstanceSpecifierMovedTo, "proxy_event_move_semantics"); + + // Step 2. Move construct proxy before subscribe + std::cout << "\nConsumer: Step 2 - Move construct proxy before subscribe" << std::endl; + auto moved_proxy = proxy_container.Extract(); + + // Step 3. Register receive handler + std::cout << "\nConsumer: Step 3 - Register receive handler" << std::endl; + ProxyEventReceiver proxy_event_receiver{moved_proxy.moved_event_, "proxy_event_move_semantics consumer failed:"}; + + // Step 4. Register state change handler + std::cout << "\nConsumer: Step 4 - Register state change handler" << std::endl; + ProxyStateChangeNotifier proxy_state_change_notifier{moved_proxy.moved_event_}; + + // Step 5. Subscribe + std::cout << "\nConsumer: Step 5 - Subscribe" << std::endl; + auto subscribe_result = moved_proxy.moved_event_.Subscribe(num_samples_to_receive); + if (!subscribe_result.has_value()) + { + FailTest("proxy_event_move_semantics consumer failed: Subscribe failed: ", subscribe_result.error()); + } + + // Step 6. Wait for provider to send values and notify + std::cout << "\nConsumer: Step 6 - Wait for provider to send values and notify" << std::endl; + for (std::size_t iteration = 0U; iteration < num_send_iterations; ++iteration) + { + std::cout << "\nConsumer: Iteration " << (iteration + 1U) << " of " << num_send_iterations << std::endl; + proxy_state_change_notifier.WaitForStateChange(stop_token, SubscriptionState::kSubscribed); + + proxy_event_receiver.WaitForSamples(stop_token, num_samples_to_receive); + process_synchronizer_result->Notify(); + } + + std::cout << "Consumer: Done with all iterations, exiting" << std::endl; +} + +} // namespace + +void RunConsumer(const ProxyMoveScenario& scenario, + const InstanceSpecifier& instance_specifier, + const std::size_t num_samples_to_receive, + const std::size_t num_send_iterations, + const score::cpp::stop_token& stop_token) +{ + if (scenario == ProxyMoveScenario::kMoveConstructBeforeSubscribe) + { + RunConsumerMoveConstructProxyBeforeSubscribe( + instance_specifier, num_samples_to_receive, num_send_iterations, stop_token); + return; + } + + FailTest("Unknown proxy move scenario in consumer"); +} + +} // namespace score::mw::com::test diff --git a/score/mw/com/test/move_semantics/proxy_event/consumer.h b/score/mw/com/test/move_semantics/proxy_event/consumer.h new file mode 100644 index 000000000..367f98f54 --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/consumer.h @@ -0,0 +1,32 @@ +/******************************************************************************** + * Copyright (c) 2026 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 License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef SCORE_MW_COM_TEST_PROXY_EVENT_MOVE_SEMANTICS_CONSUMER_H +#define SCORE_MW_COM_TEST_PROXY_EVENT_MOVE_SEMANTICS_CONSUMER_H + +#include "score/mw/com/test/move_semantics/proxy_event/test_parameters.h" +#include "score/mw/com/types.h" + +#include + +namespace score::mw::com::test +{ + +void RunConsumer(const ProxyMoveScenario& scenario, + const InstanceSpecifier& instance_specifier, + const std::size_t num_samples_to_receive, + const std::size_t num_send_iterations, + const score::cpp::stop_token& stop_token); + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_PROXY_EVENT_MOVE_SEMANTICS_CONSUMER_H diff --git a/score/mw/com/test/move_semantics/proxy_event/integration_test/BUILD b/score/mw/com/test/move_semantics/proxy_event/integration_test/BUILD new file mode 100644 index 000000000..baa8ecbc7 --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/integration_test/BUILD @@ -0,0 +1,41 @@ +# ******************************************************************************* +# Copyright (c) 2026 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 License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("@rules_pkg//pkg:mappings.bzl", "pkg_filegroup") +load("//quality/integration_testing:integration_testing.bzl", "integration_test") + +integration_test( + name = "move_construct_before_subscribe_proxy_same_process_test", + srcs = [ + "move_construct_before_subscribe_proxy_same_process_test.py", + "test_fixture.py", + ], + filesystem = "//score/mw/com/test/move_semantics/proxy_event:main_consumer_and_provider-pkg", +) + +pkg_filegroup( + name = "different_processes_filesystem", + srcs = [ + "//score/mw/com/test/move_semantics/proxy_event:main_consumer-pkg", + "//score/mw/com/test/move_semantics/proxy_event:main_provider-pkg", + ], +) + +integration_test( + name = "move_construct_before_subscribe_proxy_different_process_test", + srcs = [ + "move_construct_before_subscribe_proxy_different_process_test.py", + "test_fixture.py", + ], + filesystem = ":different_processes_filesystem", +) diff --git a/score/mw/com/test/move_semantics/proxy_event/integration_test/move_construct_before_subscribe_proxy_different_process_test.py b/score/mw/com/test/move_semantics/proxy_event/integration_test/move_construct_before_subscribe_proxy_different_process_test.py new file mode 100644 index 000000000..3b2281d18 --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/integration_test/move_construct_before_subscribe_proxy_different_process_test.py @@ -0,0 +1,19 @@ +# ******************************************************************************* +# Copyright (c) 2026 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 License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +from test_fixture import consumer, provider, ProxyMoveScenario + + +def test_move_construct_before_subscribe_proxy_different_process(target): + with consumer(target, ProxyMoveScenario.MOVE_CONSTRUCT_BEFORE_SUBSCRIBE): + with provider(target, ProxyMoveScenario.MOVE_CONSTRUCT_BEFORE_SUBSCRIBE): + pass diff --git a/score/mw/com/test/move_semantics/proxy_event/integration_test/move_construct_before_subscribe_proxy_same_process_test.py b/score/mw/com/test/move_semantics/proxy_event/integration_test/move_construct_before_subscribe_proxy_same_process_test.py new file mode 100644 index 000000000..127f30e69 --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/integration_test/move_construct_before_subscribe_proxy_same_process_test.py @@ -0,0 +1,18 @@ +# ******************************************************************************* +# Copyright (c) 2026 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 License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +from test_fixture import consumer_and_provider, ProxyMoveScenario + + +def test_move_construct_before_subscribe_proxy_same_process(target): + with consumer_and_provider(target, ProxyMoveScenario.MOVE_CONSTRUCT_BEFORE_SUBSCRIBE): + pass diff --git a/score/mw/com/test/move_semantics/proxy_event/integration_test/test_fixture.py b/score/mw/com/test/move_semantics/proxy_event/integration_test/test_fixture.py new file mode 100644 index 000000000..c0bdc7de5 --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/integration_test/test_fixture.py @@ -0,0 +1,34 @@ +# ******************************************************************************* +# Copyright (c) 2026 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 License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +from enum import IntEnum + + +class ProxyMoveScenario(IntEnum): + MOVE_CONSTRUCT_BEFORE_SUBSCRIBE = 0 + + +def consumer_and_provider(target, scenario, **kwargs): + args = ["--scenario", str(int(scenario)), "--service-instance-manifest", "./etc/mw_com_config.json"] + return target.wrap_exec( + "bin/main_consumer_and_provider", args, cwd="/opt/MainConsumerAndProviderApp", wait_on_exit=True, **kwargs + ) + + +def consumer(target, scenario, **kwargs): + args = ["--scenario", str(int(scenario)), "--service-instance-manifest", "./etc/mw_com_config.json"] + return target.wrap_exec("bin/main_consumer", args, cwd="/opt/MainConsumerApp", wait_on_exit=True, **kwargs) + + +def provider(target, scenario, **kwargs): + args = ["--scenario", str(int(scenario)), "--service-instance-manifest", "./etc/mw_com_config.json"] + return target.wrap_exec("bin/main_provider", args, cwd="/opt/MainProviderApp", wait_on_exit=True, **kwargs) diff --git a/score/mw/com/test/move_semantics/proxy_event/main_consumer.cpp b/score/mw/com/test/move_semantics/proxy_event/main_consumer.cpp new file mode 100644 index 000000000..7b369ed4f --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/main_consumer.cpp @@ -0,0 +1,47 @@ +/******************************************************************************** + * Copyright (c) 2026 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 License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/com/runtime.h" + +#include "score/mw/com/test/common_test_resources/assert_handler.h" +#include "score/mw/com/test/common_test_resources/stop_token_sig_term_handler.h" +#include "score/mw/com/test/move_semantics/proxy_event/consumer.h" +#include "score/mw/com/test/move_semantics/proxy_event/test_parameters.h" + +int main(int argc, const char** argv) +{ + auto test_configuration{score::mw::com::test::ReadCommandLineArguments(argc, argv)}; + + score::mw::com::test::SetupAssertHandler(); + score::mw::com::runtime::InitializeRuntime(argc, argv); + + score::cpp::stop_source stop_source{}; + const bool sig_term_handler_setup_success = score::mw::com::SetupStopTokenSigTermHandler(stop_source); + if (!sig_term_handler_setup_success) + { + std::cerr << "Unable to set signal handler for SIGINT and/or SIGTERM, cautiously continuing" << std::endl; + } + + const auto num_send_iterations = score::mw::com::test::GetNumberOfSendIterations(test_configuration.scenario); + + std::cout << "Starting consumer with scenario " << static_cast(test_configuration.scenario) + << ", number of samples to receive per iteration " << score::mw::com::test::kNumberOfSamplesToSendPerOffer + << " and number of send iterations " << num_send_iterations << std::endl; + + score::mw::com::test::RunConsumer(test_configuration.scenario, + score::mw::com::test::kInstanceSpecifierMovedTo, + score::mw::com::test::kNumberOfSamplesToSendPerOffer, + num_send_iterations, + stop_source.get_token()); + + return EXIT_SUCCESS; +} diff --git a/score/mw/com/test/move_semantics/proxy_event/main_consumer_and_provider.cpp b/score/mw/com/test/move_semantics/proxy_event/main_consumer_and_provider.cpp new file mode 100644 index 000000000..1145e5f59 --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/main_consumer_and_provider.cpp @@ -0,0 +1,57 @@ +/******************************************************************************** + * Copyright (c) 2026 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 License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/com/runtime.h" + +#include "score/mw/com/test/common_test_resources/assert_handler.h" +#include "score/mw/com/test/common_test_resources/stop_token_sig_term_handler.h" +#include "score/mw/com/test/move_semantics/proxy_event/consumer.h" +#include "score/mw/com/test/move_semantics/proxy_event/provider.h" +#include "score/mw/com/test/move_semantics/proxy_event/test_parameters.h" + +int main(int argc, const char** argv) +{ + auto test_configuration{score::mw::com::test::ReadCommandLineArguments(argc, argv)}; + + score::mw::com::test::SetupAssertHandler(); + score::mw::com::runtime::InitializeRuntime(argc, argv); + + score::cpp::stop_source stop_source{}; + const bool sig_term_handler_setup_success = score::mw::com::SetupStopTokenSigTermHandler(stop_source); + if (!sig_term_handler_setup_success) + { + std::cerr << "Unable to set signal handler for SIGINT and/or SIGTERM, cautiously continuing" << std::endl; + } + + const auto num_send_iterations = score::mw::com::test::GetNumberOfSendIterations(test_configuration.scenario); + + std::cout << "Starting provider and consumer with scenario " + << static_cast(test_configuration.scenario) << ", number of samples to send per offer " + << score::mw::com::test::kNumberOfSamplesToSendPerOffer << " and number of send iterations " + << num_send_iterations << std::endl; + + auto provider_future = std::async(score::mw::com::test::RunProvider, + test_configuration.scenario, + score::mw::com::test::kNumberOfSamplesToSendPerOffer, + stop_source.get_token()); + auto consumer_future = std::async(score::mw::com::test::RunConsumer, + test_configuration.scenario, + score::mw::com::test::kInstanceSpecifierMovedTo, + score::mw::com::test::kNumberOfSamplesToSendPerOffer, + num_send_iterations, + stop_source.get_token()); + + provider_future.get(); + consumer_future.get(); + + return EXIT_SUCCESS; +} diff --git a/score/mw/com/test/move_semantics/proxy_event/main_provider.cpp b/score/mw/com/test/move_semantics/proxy_event/main_provider.cpp new file mode 100644 index 000000000..b7c842a2b --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/main_provider.cpp @@ -0,0 +1,44 @@ +/******************************************************************************** + * Copyright (c) 2026 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 License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/com/runtime.h" + +#include "score/mw/com/test/common_test_resources/assert_handler.h" +#include "score/mw/com/test/common_test_resources/stop_token_sig_term_handler.h" +#include "score/mw/com/test/move_semantics/proxy_event/provider.h" +#include "score/mw/com/test/move_semantics/proxy_event/test_parameters.h" + +int main(int argc, const char** argv) +{ + auto test_configuration{score::mw::com::test::ReadCommandLineArguments(argc, argv)}; + + score::mw::com::test::SetupAssertHandler(); + score::mw::com::runtime::InitializeRuntime(argc, argv); + + score::cpp::stop_source stop_source{}; + const bool sig_term_handler_setup_success = score::mw::com::SetupStopTokenSigTermHandler(stop_source); + if (!sig_term_handler_setup_success) + { + std::cerr << "Unable to set signal handler for SIGINT and/or SIGTERM, cautiously continuing" << std::endl; + } + + const auto num_send_iterations = score::mw::com::test::GetNumberOfSendIterations(test_configuration.scenario); + + std::cout << "Starting provider with scenario " << static_cast(test_configuration.scenario) + << ", number of samples to send per offer " << score::mw::com::test::kNumberOfSamplesToSendPerOffer + << " and number of send iterations " << num_send_iterations << std::endl; + + score::mw::com::test::RunProvider( + test_configuration.scenario, score::mw::com::test::kNumberOfSamplesToSendPerOffer, stop_source.get_token()); + + return EXIT_SUCCESS; +} diff --git a/score/mw/com/test/move_semantics/proxy_event/provider.cpp b/score/mw/com/test/move_semantics/proxy_event/provider.cpp new file mode 100644 index 000000000..11131243c --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/provider.cpp @@ -0,0 +1,103 @@ +/******************************************************************************** + * Copyright (c) 2026 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 License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/com/test/move_semantics/proxy_event/provider.h" + +#include "score/mw/com/test/common_test_resources/fail_test.h" +#include "score/mw/com/test/common_test_resources/skeleton_container.h" +#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" +#include "score/mw/com/test/move_semantics/proxy_event/test_event_datatype.h" + +#include + +namespace score::mw::com::test +{ +namespace +{ + +const std::string kInterprocessNotificationShmPath{"/proxy_event_move_semantics_interprocess_notification"}; + +void SendSamples(ProxyMoveSemanticsSkeleton& skeleton, + const std::size_t number_of_samples_to_send_per_offer, + const std::uint32_t initial_value) +{ + std::cout << "\nProvider: Sending " << number_of_samples_to_send_per_offer << " samples" << std::endl; + for (std::uint32_t i = 0; i < number_of_samples_to_send_per_offer; ++i) + { + auto send_result = skeleton.moved_event_.Send(i + initial_value); + if (!send_result.has_value()) + { + FailTest("Provider: Send failed: ", send_result.error()); + } + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } +} + +void RunProviderMoveConstructProxyBeforeSubscribe(const score::cpp::stop_token& stop_token, + const std::size_t number_of_samples_to_send_per_offer, + ProcessSynchronizer& proxy_done_synchronizer) +{ + // Step 1. Create skeleton and offer service + std::cout << "\nProvider: Step 1 - Create and offer skeleton" << std::endl; + SkeletonContainer skeleton_container{}; + skeleton_container.CreateSkeleton(kInstanceSpecifierMovedTo, "proxy_event_move_semantics"); + skeleton_container.OfferService("proxy_event_move_semantics"); + + // Step 2. Send first n values + std::cout << "\nProvider: Step 2 - Send " << number_of_samples_to_send_per_offer << " samples" << std::endl; + SendSamples(skeleton_container.GetSkeleton(), number_of_samples_to_send_per_offer, 1U); + + // Step 3. Wait for consumer to notify that it received the first n values + if (!proxy_done_synchronizer.WaitWithAbort(stop_token)) + { + FailTest("proxy_event_move_semantics provider failed: waiting for consumer done was aborted"); + } + proxy_done_synchronizer.Reset(); + + // Step 4. Stop and re-offer to exercise subscription continuity on moved proxy + std::cout << "\nProvider: Step 4 - Stop and re-offer skeleton" << std::endl; + skeleton_container.GetSkeleton().StopOfferService(); + skeleton_container.OfferService("proxy_event_move_semantics"); + + // Step 5. Send second n values + std::cout << "\nProvider: Step 5 - Send " << number_of_samples_to_send_per_offer + << " samples again after re-offering" << std::endl; + SendSamples(skeleton_container.GetSkeleton(), + number_of_samples_to_send_per_offer, + number_of_samples_to_send_per_offer + 1U); + + // Step 6. Wait for consumer to notify that it received the second n values + if (!proxy_done_synchronizer.WaitWithAbort(stop_token)) + { + FailTest("proxy_event_move_semantics provider failed: waiting for consumer done was aborted"); + } +} + +} // namespace + +void RunProvider(const ProxyMoveScenario& scenario, + const std::size_t num_samples_to_send, + const score::cpp::stop_token& stop_token) +{ + auto process_synchronizer_result = + ProcessSynchronizer::CreateUniquePtr(kInterprocessNotificationShmPath + std::string{"MoveEventInterface"}); + + if (scenario == ProxyMoveScenario::kMoveConstructBeforeSubscribe) + { + RunProviderMoveConstructProxyBeforeSubscribe(stop_token, num_samples_to_send, *process_synchronizer_result); + return; + } + + FailTest("Unknown proxy move scenario in provider"); +} + +} // namespace score::mw::com::test diff --git a/score/mw/com/test/move_semantics/proxy_event/provider.h b/score/mw/com/test/move_semantics/proxy_event/provider.h new file mode 100644 index 000000000..cdda2c791 --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/provider.h @@ -0,0 +1,29 @@ +/******************************************************************************** + * Copyright (c) 2026 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 License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef SCORE_MW_COM_TEST_PROXY_EVENT_MOVE_SEMANTICS_PROVIDER_H +#define SCORE_MW_COM_TEST_PROXY_EVENT_MOVE_SEMANTICS_PROVIDER_H + +#include "score/mw/com/test/move_semantics/proxy_event/test_parameters.h" + +#include + +namespace score::mw::com::test +{ + +void RunProvider(const ProxyMoveScenario& scenario, + const std::size_t num_samples_to_send, + const score::cpp::stop_token& stop_token); + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_PROXY_EVENT_MOVE_SEMANTICS_PROVIDER_H diff --git a/score/mw/com/test/move_semantics/proxy_event/test_event_datatype.cpp b/score/mw/com/test/move_semantics/proxy_event/test_event_datatype.cpp new file mode 100644 index 000000000..acb283fe4 --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/test_event_datatype.cpp @@ -0,0 +1,13 @@ +/******************************************************************************** + * Copyright (c) 2026 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 License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/com/test/move_semantics/proxy_event/test_event_datatype.h" diff --git a/score/mw/com/test/move_semantics/proxy_event/test_event_datatype.h b/score/mw/com/test/move_semantics/proxy_event/test_event_datatype.h new file mode 100644 index 000000000..45c2e1fdf --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/test_event_datatype.h @@ -0,0 +1,37 @@ +/******************************************************************************** + * Copyright (c) 2026 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 License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef SCORE_MW_COM_TEST_PROXY_EVENT_MOVE_SEMANTICS_TEST_EVENT_DATATYPE_H +#define SCORE_MW_COM_TEST_PROXY_EVENT_MOVE_SEMANTICS_TEST_EVENT_DATATYPE_H + +#include "score/mw/com/types.h" + +#include + +namespace score::mw::com::test +{ + +template +class ProxyMoveSemanticsInterface : public T::Base +{ + public: + using T::Base::Base; + + typename T::template Event moved_event_{*this, "moved_event"}; +}; + +using ProxyMoveSemanticsProxy = score::mw::com::AsProxy; +using ProxyMoveSemanticsSkeleton = score::mw::com::AsSkeleton; + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_PROXY_EVENT_MOVE_SEMANTICS_TEST_EVENT_DATATYPE_H diff --git a/score/mw/com/test/move_semantics/proxy_event/test_parameters.cpp b/score/mw/com/test/move_semantics/proxy_event/test_parameters.cpp new file mode 100644 index 000000000..5ad1cc1c7 --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/test_parameters.cpp @@ -0,0 +1,60 @@ +/******************************************************************************** + * Copyright (c) 2026 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 License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/com/test/move_semantics/proxy_event/test_parameters.h" + +#include "score/mw/com/test/common_test_resources/command_line_parser.h" +#include "score/mw/com/test/common_test_resources/fail_test.h" + +namespace score::mw::com::test +{ + +CombinedTestConfiguration ReadCommandLineArguments(int argc, const char** argv) +{ + auto args = ParseCommandLineArguments(argc, argv, {{kScenario, ""}, {kServiceInstanceManifest, ""}}); + + const auto scenario_index = GetValue(args, kScenario); + if (scenario_index >= static_cast(ProxyMoveScenario::kNumberOfScenarios)) + { + FailTest("Consumer: ", + kScenario, + " value ", + scenario_index, + " is out of range. Valid values are between 0 and ", + static_cast(ProxyMoveScenario::kNumberOfScenarios) - 1, + "."); + } + const auto scenario = static_cast(scenario_index); + + auto service_instance_manifest = GetValue(args, kServiceInstanceManifest); + + return {scenario, service_instance_manifest}; +} + +std::size_t GetNumberOfSendIterations(const ProxyMoveScenario scenario) +{ + if (scenario == ProxyMoveScenario::kMoveConstructBeforeSubscribe) + { + // In this scenario, the consumer will: + // - Find service and create proxy + // - move construct the proxy before subscribe + // - subscribe and receive samples + // - continue receiving samples after provider re-offers + // The receiver therefore expects two receive iterations. + return 2U; + } + + FailTest("Unknown scenario, cannot determine number of send iterations"); + return 0U; +} + +} // namespace score::mw::com::test diff --git a/score/mw/com/test/move_semantics/proxy_event/test_parameters.h b/score/mw/com/test/move_semantics/proxy_event/test_parameters.h new file mode 100644 index 000000000..3fcb40b11 --- /dev/null +++ b/score/mw/com/test/move_semantics/proxy_event/test_parameters.h @@ -0,0 +1,49 @@ +/******************************************************************************** + * Copyright (c) 2026 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 License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef SCORE_MW_COM_TEST_PROXY_EVENT_MOVE_SEMANTICS_TEST_PARAMETERS_H +#define SCORE_MW_COM_TEST_PROXY_EVENT_MOVE_SEMANTICS_TEST_PARAMETERS_H + +#include "score/mw/com/types.h" + +#include +#include + +namespace score::mw::com::test +{ + +const std::string kScenario{"scenario"}; +const std::string kServiceInstanceManifest{"service-instance-manifest"}; + +constexpr std::size_t kNumberOfSamplesToSendPerOffer{10U}; + +const InstanceSpecifier kInstanceSpecifierMovedTo = + InstanceSpecifier::Create(std::string{"test/move_semantics/proxy_event/MoveEventInterface"}).value(); + +enum class ProxyMoveScenario : std::uint8_t +{ + kMoveConstructBeforeSubscribe, + kNumberOfScenarios +}; + +struct CombinedTestConfiguration +{ + ProxyMoveScenario scenario; + std::string service_instance_manifest; +}; + +CombinedTestConfiguration ReadCommandLineArguments(int argc, const char** argv); +std::size_t GetNumberOfSendIterations(ProxyMoveScenario scenario); + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_PROXY_EVENT_MOVE_SEMANTICS_TEST_PARAMETERS_H diff --git a/score/mw/com/test/move_semantics/skeleton_event/consumer.cpp b/score/mw/com/test/move_semantics/skeleton_event/consumer.cpp index 5494f42c3..897fb0bb9 100644 --- a/score/mw/com/test/move_semantics/skeleton_event/consumer.cpp +++ b/score/mw/com/test/move_semantics/skeleton_event/consumer.cpp @@ -27,133 +27,6 @@ namespace const std::string kInterprocessNotificationShmPath{"/skeleton_event_move_semantics_interprocess_notification"}; -template -class ProxyStateChangeNotifier -{ - public: - explicit ProxyStateChangeNotifier(ProxyEventType& proxy_event) : proxy_event_{proxy_event} - { - auto state_change_handler = [this](const SubscriptionState new_state) -> bool { - std::cout << "Service state changed, new state: " << static_cast(new_state) << std::endl; - std::lock_guard lock(mutex_); - last_seen_state_ = new_state; - condition_variable_.notify_all(); - return true; - }; - proxy_event_.SetSubscriptionStateChangeHandler(state_change_handler); - } - - ~ProxyStateChangeNotifier() - { - proxy_event_.UnsetSubscriptionStateChangeHandler(); - } - - ProxyStateChangeNotifier(const ProxyStateChangeNotifier&) = delete; - ProxyStateChangeNotifier& operator=(const ProxyStateChangeNotifier&) = delete; - ProxyStateChangeNotifier(const ProxyStateChangeNotifier&&) = delete; - ProxyStateChangeNotifier& operator=(const ProxyStateChangeNotifier&&) = delete; - - bool WaitForStateChange(const score::cpp::stop_token& stop_token, SubscriptionState desired_state) - { - std::unique_lock lock(mutex_); - return condition_variable_.wait(lock, stop_token, [this, desired_state]() { - return last_seen_state_.has_value() && last_seen_state_.value() == desired_state; - }); - } - - private: - std::mutex mutex_{}; - concurrency::InterruptibleConditionalVariable condition_variable_{}; - std::optional last_seen_state_{}; - ProxyEventType& proxy_event_; -}; - -template -class ProxyEventReceiver -{ - public: - explicit ProxyEventReceiver(ProxyEventType& proxy_event) : proxy_event_{proxy_event} - { - auto receive_handler = [&received_sample_notification = received_sample_notification_]() { - std::cout << "Received event notification" << std::endl; - received_sample_notification.notify(); - }; - proxy_event_.SetReceiveHandler(receive_handler); - } - - ~ProxyEventReceiver() - { - proxy_event_.UnsetReceiveHandler(); - } - - ProxyEventReceiver(const ProxyEventReceiver&) = delete; - ProxyEventReceiver& operator=(const ProxyEventReceiver&) = delete; - ProxyEventReceiver(const ProxyEventReceiver&&) = delete; - ProxyEventReceiver& operator=(const ProxyEventReceiver&&) = delete; - - void WaitForSamples(const score::cpp::stop_token& stop_token, const std::size_t num_samples_to_receive) - { - std::size_t received_count{0U}; - while (!stop_token.stop_requested()) - { - auto get_samples_result = proxy_event_.GetNewSamples( - [this](SamplePtr sample) { - GetNewSamplesCallback(std::move(sample)); - }, - num_samples_to_receive); - if (!get_samples_result.has_value()) - { - FailTest("skeleton_event_move_semantics consumer failed: GetNewSamples failed: ", - get_samples_result.error()); - } - - received_count += get_samples_result.value(); - std::cout << "Received " << get_samples_result.value() << " samples. " << received_count - << " samples so far" << std::endl; - - if (received_count == num_samples_to_receive) - { - break; - } - - const auto notification_received = received_sample_notification_.waitWithAbort(stop_token); - if (!notification_received) - { - // spurious wake-up or stop requested, either way we should check the stop token and exit if stop was - // requested - continue; - } - - received_sample_notification_.reset(); - } - std::cout << "\nConsumer: Done receiving samples, received " << received_count << " samples in total\n"; - } - - private: - void GetNewSamplesCallback(SamplePtr sample) - { - if (sample == nullptr) - { - FailTest("skeleton_event_move_semantics consumer failed: received null sample"); - } - const std::uint32_t expected_value = latest_value_.has_value() ? latest_value_.value() + 1U : 1U; - if (*sample != expected_value) - { - FailTest("skeleton_event_move_semantics consumer failed: received value ", - *sample, - " does not match expected value ", - expected_value); - } - latest_value_ = *sample; - } - - score::concurrency::Notification received_sample_notification_{}; - std::mutex mutex_{}; - concurrency::InterruptibleConditionalVariable condition_variable_{}; - std::optional latest_value_{}; - ProxyEventType& proxy_event_; -}; - } // namespace void RunConsumer(const InstanceSpecifier& instance_specifier, @@ -182,7 +55,7 @@ void RunConsumer(const InstanceSpecifier& instance_specifier, // Step 2. Register receive handler std::cout << "\nConsumer: Step 2 - Register receive handler" << std::endl; - ProxyEventReceiver proxy_event_receiver{proxy.moved_event_}; + ProxyEventReceiver proxy_event_receiver{proxy.moved_event_, "skeleton_event_move_semantics consumer failed:"}; // Step 3. Register state change handler std::cout << "\nConsumer: Step 3 - Register state change handler" << std::endl;