From 0fd7094d6aef5d356efe9c26c599d51ff7329016 Mon Sep 17 00:00:00 2001 From: tejveerpratap Date: Tue, 7 Jul 2026 13:02:31 +0530 Subject: [PATCH 1/3] test(mw/com): Add interface, parameters and build config --- .../test/move_semantics/skeleton_method/BUILD | 169 ++++++++++++++++++ .../skeleton_method/config/logging.json | 7 + .../skeleton_method/config/mw_com_config.json | 99 ++++++++++ .../skeleton_method/test_method_datatype.cpp | 13 ++ .../skeleton_method/test_method_datatype.h | 37 ++++ .../skeleton_method/test_parameters.cpp | 139 ++++++++++++++ .../skeleton_method/test_parameters.h | 69 +++++++ 7 files changed, 533 insertions(+) create mode 100644 score/mw/com/test/move_semantics/skeleton_method/BUILD create mode 100644 score/mw/com/test/move_semantics/skeleton_method/config/logging.json create mode 100644 score/mw/com/test/move_semantics/skeleton_method/config/mw_com_config.json create mode 100644 score/mw/com/test/move_semantics/skeleton_method/test_method_datatype.cpp create mode 100644 score/mw/com/test/move_semantics/skeleton_method/test_method_datatype.h create mode 100644 score/mw/com/test/move_semantics/skeleton_method/test_parameters.cpp create mode 100644 score/mw/com/test/move_semantics/skeleton_method/test_parameters.h diff --git a/score/mw/com/test/move_semantics/skeleton_method/BUILD b/score/mw/com/test/move_semantics/skeleton_method/BUILD new file mode 100644 index 000000000..4fe07048b --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/BUILD @@ -0,0 +1,169 @@ +# ******************************************************************************* +# 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_method_datatype", + srcs = ["test_method_datatype.cpp"], + hdrs = ["test_method_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_method_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", + "@score_baselibs//score/language/futurecpp", + ], +) + +cc_library( + name = "consumer", + srcs = ["consumer.cpp"], + hdrs = ["consumer.h"], + features = COMPILER_WARNING_FEATURES, + deps = [ + ":test_method_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", + "@score_baselibs//score/language/futurecpp", + ], +) + +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/skeleton_method:__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/skeleton_method:__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/skeleton_method:__subpackages__", + ], +) diff --git a/score/mw/com/test/move_semantics/skeleton_method/config/logging.json b/score/mw/com/test/move_semantics/skeleton_method/config/logging.json new file mode 100644 index 000000000..dfd173549 --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/config/logging.json @@ -0,0 +1,7 @@ +{ + "appId": "SMMS", + "appDesc": "skeleton_method_move_semantics", + "logLevel": "kDebug", + "logLevelThresholdConsole": "kDebug", + "logMode": "kRemote|kConsole" +} diff --git a/score/mw/com/test/move_semantics/skeleton_method/config/mw_com_config.json b/score/mw/com/test/move_semantics/skeleton_method/config/mw_com_config.json new file mode 100644 index 000000000..764fbbd5a --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/config/mw_com_config.json @@ -0,0 +1,99 @@ +{ + "serviceTypes": [ + { + "serviceTypeName": "/test/move_semantics/skeleton_method/SkeletonMethodMoveInterface", + "version": { + "major": 1, + "minor": 0 + }, + "bindings": [ + { + "binding": "SHM", + "serviceId": 2200, + "methods": [ + { + "methodName": "moved_method", + "methodId": 1 + } + ] + } + ] + } + ], + "serviceInstances": [ + { + "instanceSpecifier": "test/move_semantics/skeleton_method/SkeletonMethodMoveInterfaceMovedTo", + "serviceTypeName": "/test/move_semantics/skeleton_method/SkeletonMethodMoveInterface", + "version": { + "major": 1, + "minor": 0 + }, + "instances": [ + { + "instanceId": 1, + "asil-level": "QM", + "binding": "SHM", + "methods": [ + { + "methodName": "moved_method", + "queueSize": 1 + } + ], + "allowedConsumer": { + "QM": [ + 0 + ], + "B": [ + 0 + ] + }, + "allowedProvider": { + "QM": [ + 0 + ], + "B": [ + 0 + ] + } + } + ] + }, + { + "instanceSpecifier": "test/move_semantics/skeleton_method/SkeletonMethodMoveInterfaceMovedFrom", + "serviceTypeName": "/test/move_semantics/skeleton_method/SkeletonMethodMoveInterface", + "version": { + "major": 1, + "minor": 0 + }, + "instances": [ + { + "instanceId": 2, + "asil-level": "QM", + "binding": "SHM", + "methods": [ + { + "methodName": "moved_method", + "queueSize": 1 + } + ], + "allowedConsumer": { + "QM": [ + 0 + ], + "B": [ + 0 + ] + }, + "allowedProvider": { + "QM": [ + 0 + ], + "B": [ + 0 + ] + } + } + ] + } + ] +} diff --git a/score/mw/com/test/move_semantics/skeleton_method/test_method_datatype.cpp b/score/mw/com/test/move_semantics/skeleton_method/test_method_datatype.cpp new file mode 100644 index 000000000..7364c70a0 --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/test_method_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/skeleton_method/test_method_datatype.h" diff --git a/score/mw/com/test/move_semantics/skeleton_method/test_method_datatype.h b/score/mw/com/test/move_semantics/skeleton_method/test_method_datatype.h new file mode 100644 index 000000000..49bb20e03 --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/test_method_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_MOVE_SEMANTICS_SKELETON_METHOD_TEST_METHOD_DATATYPE_H +#define SCORE_MW_COM_TEST_MOVE_SEMANTICS_SKELETON_METHOD_TEST_METHOD_DATATYPE_H + +#include "score/mw/com/types.h" + +#include + +namespace score::mw::com::test +{ + +template +class SkeletonMethodMoveInterface : public T::Base +{ + public: + using T::Base::Base; + + typename T::template Method moved_method_{*this, "moved_method"}; +}; + +using SkeletonMethodMoveProxy = score::mw::com::AsProxy; +using SkeletonMethodMoveSkeleton = score::mw::com::AsSkeleton; + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_MOVE_SEMANTICS_SKELETON_METHOD_TEST_METHOD_DATATYPE_H diff --git a/score/mw/com/test/move_semantics/skeleton_method/test_parameters.cpp b/score/mw/com/test/move_semantics/skeleton_method/test_parameters.cpp new file mode 100644 index 000000000..db9af6aa6 --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/test_parameters.cpp @@ -0,0 +1,139 @@ +/******************************************************************************** + * 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/skeleton_method/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(SkeletonMoveScenario::kNumberOfScenarios)) + { + FailTest("skeleton_method_move_semantics: ", + kScenario, + " value ", + scenario_index, + " is out of range. Valid values are between 0 and ", + static_cast(SkeletonMoveScenario::kNumberOfScenarios) - 1, + "."); + } + const auto scenario = static_cast(scenario_index); + + auto service_instance_manifest = GetValue(args, kServiceInstanceManifest); + + return {scenario, service_instance_manifest}; +} + +bool IsAfterOffered(const SkeletonMoveScenario scenario) +{ + return (scenario == SkeletonMoveScenario::kMoveConstructAfterOffered) || + (scenario == SkeletonMoveScenario::kMoveAssignAfterOffered); +} + +std::size_t GetNumberOfCallIterations(const SkeletonMoveScenario scenario) +{ + if (scenario == SkeletonMoveScenario::kMoveConstructBeforeOffered) + { + // In this scenario, the provider will: + // - Create Skeleton A + // - Register Handler A on Skeleton A + // - Move construct: Skeleton B = std::move(Skeleton A) [before OfferService] + // - Offer Skeleton B + // - Wait for consumer to call Handler A via proxy + // The consumer therefore expects one call iteration (Handler A: a + b = 15). + return 1U; + } + else if (scenario == SkeletonMoveScenario::kMoveConstructAfterOffered) + { + // In this scenario, the provider will: + // - Create Skeleton A + // - Register Handler A on Skeleton A + // - Offer Skeleton A + // - Wait for consumer proxy to be created (SHM now exists) + // - Move construct: Skeleton B = std::move(Skeleton A) [after SHM exists] + // - Signal consumer: move done + // - Wait for consumer to call Handler A via proxy + // - Register Handler B on Skeleton B + // - Signal consumer: Handler B registered + // - Wait for consumer to call Handler B via proxy + // The consumer therefore expects two call iterations: + // iter 0: Handler A (a + b = 15), iter 1: Handler B (a * b = 50). + return 2U; + } + else if (scenario == SkeletonMoveScenario::kMoveAssignBeforeOffered) + { + // In this scenario, the provider will: + // - Create Skeleton A (kMovedTo identity) and Skeleton B (kMovedFrom identity) + // - Register Handler A on Skeleton A + // - Move assign: Skeleton B = std::move(Skeleton A) [before OfferService] + // Skeleton B now holds kMovedTo identity + Handler A + // - Offer Skeleton B + // - Wait for consumer to call Handler A via proxy + // The consumer therefore expects one call iteration (Handler A: a + b = 15). + return 1U; + } + else if (scenario == SkeletonMoveScenario::kMoveAssignAfterOffered) + { + // In this scenario, the provider will: + // - Create Skeleton A (kMovedTo identity) and Skeleton B (kMovedFrom identity) + // - Register Handler A on Skeleton A, Handler B on Skeleton B + // - Offer both skeletons + // - Wait for consumer to create both proxies (single notify) + // - Move assign: Skeleton B = std::move(Skeleton A) [after SHM exists for both] + // Skeleton B now holds kMovedTo identity + Handler A + // - Signal consumer: move done + // - Wait for consumer to call Handler A via kMovedTo proxy + // - Register Handler C on Skeleton B (which internally stores Skeleton A's handle) + // - Signal consumer: Handler C registered + // - Wait for consumer to call Handler C via kMovedTo proxy + // The consumer therefore expects two call iterations: + // iter 0: Handler A (a + b = 15), iter 1: Handler C (a - b = 5). + return 2U; + } + + FailTest("GetNumberOfCallIterations: Unknown scenario"); + return 0U; +} + +std::int32_t GetExpectedResult(const SkeletonMoveScenario scenario, const std::size_t iteration) +{ + switch (scenario) + { + case SkeletonMoveScenario::kMoveConstructBeforeOffered: + case SkeletonMoveScenario::kMoveAssignBeforeOffered: + // Only 1 iteration, always Handler A (a + b) + return kTestArgA + kTestArgB; + + case SkeletonMoveScenario::kMoveConstructAfterOffered: + // iter 0: Handler A (a + b), iter 1: Handler B (a * b) + return (iteration == 0U) ? kTestArgA + kTestArgB : kTestArgA * kTestArgB; + + case SkeletonMoveScenario::kMoveAssignAfterOffered: + // iter 0: Handler A (a + b), iter 1: Handler C (a - b) + return (iteration == 0U) ? kTestArgA + kTestArgB : kTestArgA - kTestArgB; + + case SkeletonMoveScenario::kNumberOfScenarios: + [[fallthrough]]; + default: + FailTest("GetExpectedResult: Unknown scenario or iteration"); + return 0; + } +} + +} // namespace score::mw::com::test diff --git a/score/mw/com/test/move_semantics/skeleton_method/test_parameters.h b/score/mw/com/test/move_semantics/skeleton_method/test_parameters.h new file mode 100644 index 000000000..182e439bb --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/test_parameters.h @@ -0,0 +1,69 @@ +/******************************************************************************** + * 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_MOVE_SEMANTICS_SKELETON_METHOD_TEST_PARAMETERS_H +#define SCORE_MW_COM_TEST_MOVE_SEMANTICS_SKELETON_METHOD_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::int32_t kTestArgA{10}; +constexpr std::int32_t kTestArgB{5}; + +const InstanceSpecifier kInstanceSpecifierMovedTo = + InstanceSpecifier::Create(std::string{"test/move_semantics/skeleton_method/SkeletonMethodMoveInterfaceMovedTo"}) + .value(); +const InstanceSpecifier kInstanceSpecifierMovedFrom = + InstanceSpecifier::Create(std::string{"test/move_semantics/skeleton_method/SkeletonMethodMoveInterfaceMovedFrom"}) + .value(); + +enum class SkeletonMoveScenario : std::uint8_t +{ + kMoveConstructBeforeOffered = 0, + kMoveConstructAfterOffered = 1, + kMoveAssignBeforeOffered = 2, + kMoveAssignAfterOffered = 3, + kNumberOfScenarios +}; + +struct CombinedTestConfiguration +{ + SkeletonMoveScenario scenario; + std::string service_instance_manifest; +}; + +CombinedTestConfiguration ReadCommandLineArguments(int argc, const char** argv); + +/// \brief Returns true for scenarios where the skeleton is already offered before the move occurs. +bool IsAfterOffered(SkeletonMoveScenario scenario); + +/// \brief Returns the number of method call iterations the consumer performs for the given scenario. +std::size_t GetNumberOfCallIterations(SkeletonMoveScenario scenario); + +/// \brief Returns the expected return value of moved_method_(kTestArgA, kTestArgB) for the given +/// scenario and call iteration index. +/// iter 0: Handler A (a+b = 15) for all scenarios +/// iter 1: Handler B (a*b = 50) for kMoveConstructAfterOffered +/// Handler C (a-b = 5) for kMoveAssignAfterOffered +std::int32_t GetExpectedResult(SkeletonMoveScenario scenario, std::size_t iteration); + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_MOVE_SEMANTICS_SKELETON_METHOD_TEST_PARAMETERS_H From 966428414e431b0a07c48d762f287d7a9d30cda4 Mon Sep 17 00:00:00 2001 From: tejveerpratap Date: Tue, 7 Jul 2026 13:02:43 +0530 Subject: [PATCH 2/3] test(mw/com): Add provider and consumer implementation --- .../skeleton_method/consumer.cpp | 120 +++++++ .../move_semantics/skeleton_method/consumer.h | 27 ++ .../skeleton_method/main_consumer.cpp | 42 +++ .../main_consumer_and_provider.cpp | 51 +++ .../skeleton_method/main_provider.cpp | 42 +++ .../skeleton_method/provider.cpp | 328 ++++++++++++++++++ .../move_semantics/skeleton_method/provider.h | 27 ++ 7 files changed, 637 insertions(+) create mode 100644 score/mw/com/test/move_semantics/skeleton_method/consumer.cpp create mode 100644 score/mw/com/test/move_semantics/skeleton_method/consumer.h create mode 100644 score/mw/com/test/move_semantics/skeleton_method/main_consumer.cpp create mode 100644 score/mw/com/test/move_semantics/skeleton_method/main_consumer_and_provider.cpp create mode 100644 score/mw/com/test/move_semantics/skeleton_method/main_provider.cpp create mode 100644 score/mw/com/test/move_semantics/skeleton_method/provider.cpp create mode 100644 score/mw/com/test/move_semantics/skeleton_method/provider.h diff --git a/score/mw/com/test/move_semantics/skeleton_method/consumer.cpp b/score/mw/com/test/move_semantics/skeleton_method/consumer.cpp new file mode 100644 index 000000000..12a17e0f0 --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/consumer.cpp @@ -0,0 +1,120 @@ +/******************************************************************************** + * 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/skeleton_method/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/skeleton_method/test_method_datatype.h" +#include "score/mw/com/test/move_semantics/skeleton_method/test_parameters.h" + +#include + +#include + +namespace score::mw::com::test +{ +namespace +{ + +const std::string kProxyDoneShmPath{"/skeleton_method_move_semantics_proxy_done_sync"}; +const std::string kSkeletonReadyShmPath{"/skeleton_method_move_semantics_skeleton_ready_sync"}; + +} // namespace + +void RunConsumer(const SkeletonMoveScenario& scenario, const score::cpp::stop_token& stop_token) +{ + auto proxy_done_sync = ProcessSynchronizer::Create(kProxyDoneShmPath); + if (!proxy_done_sync.has_value()) + { + FailTest("Consumer: Failed to create proxy_done ProcessSynchronizer"); + } + + // Safety guard: always notify provider on exit so it does not wait indefinitely on failure + ExitFunctionGuard done_guard{[&proxy_done_sync]() { + proxy_done_sync->Notify(); + }}; + + // Step 1. Create proxy for kInstanceSpecifierMovedTo + std::cout << "\nConsumer: Step 1 - Create proxy (kMovedTo)" << std::endl; + ProxyContainer proxy_moved_to_container{}; + proxy_moved_to_container.CreateProxy(kInstanceSpecifierMovedTo, "skeleton_method_move_semantics"); + auto& proxy_moved_to = proxy_moved_to_container.GetProxy(); + + // Step 2. For kMoveAssignAfterOffered: also create proxy for kInstanceSpecifierMovedFrom + // (both skeletons are offered; creating the proxy confirms SHM exists for both) + std::optional> proxy_moved_from_container{}; + if (scenario == SkeletonMoveScenario::kMoveAssignAfterOffered) + { + std::cout << "\nConsumer: Step 2 - Create proxy (kMovedFrom)" << std::endl; + proxy_moved_from_container.emplace(); + proxy_moved_from_container->CreateProxy(kInstanceSpecifierMovedFrom, "skeleton_method_move_semantics"); + } + + // Step 3. For after-offered scenarios: signal provider that proxy/proxies are created + if (IsAfterOffered(scenario)) + { + std::cout << "\nConsumer: Step 3 - Notify provider: proxy/proxies created" << std::endl; + proxy_done_sync->Notify(); + } + + // Step 4. Create skeleton_ready synchronizer for after-offered scenarios + std::unique_ptr skeleton_ready_sync{}; + if (IsAfterOffered(scenario)) + { + skeleton_ready_sync = ProcessSynchronizer::CreateUniquePtr(kSkeletonReadyShmPath); + } + + // Step 5. Call loop: one iteration for before-offered, two for after-offered + const std::size_t num_iterations = GetNumberOfCallIterations(scenario); + for (std::size_t iteration = 0U; iteration < num_iterations; ++iteration) + { + std::cout << "\nConsumer: Iteration " << (iteration + 1U) << " of " << num_iterations << std::endl; + + // For after-offered scenarios: wait for provider to signal ready + // iter 0 → move complete; iter 1 → next handler registered + if (IsAfterOffered(scenario)) + { + std::cout << "\nConsumer: Wait for skeleton_ready signal" << std::endl; + if (!skeleton_ready_sync->WaitWithAbort(stop_token)) + { + FailTest("Consumer: skeleton_ready WaitWithAbort was stopped by stop_token"); + } + skeleton_ready_sync->Reset(); + } + + // Call the method + std::cout << "\nConsumer: Calling moved_method_(" << kTestArgA << ", " << kTestArgB << ")" << std::endl; + auto result = proxy_moved_to.moved_method_(kTestArgA, kTestArgB); + if (!result.has_value()) + { + FailTest("Consumer: moved_method_ call failed: ", result.error()); + } + const std::int32_t actual = *(result.value()); + + // Verify result. + const std::int32_t expected = GetExpectedResult(scenario, iteration); + if (actual != expected) + { + FailTest("Consumer: iteration ", iteration, " expected ", expected, " but got ", actual); + } + std::cout << "\nConsumer: Iteration " << (iteration + 1U) << " passed (result=" << actual << ")" << std::endl; + + // Notify provider: call done + proxy_done_sync->Notify(); + } + + std::cout << "\nConsumer: All iterations done" << std::endl; +} + +} // namespace score::mw::com::test diff --git a/score/mw/com/test/move_semantics/skeleton_method/consumer.h b/score/mw/com/test/move_semantics/skeleton_method/consumer.h new file mode 100644 index 000000000..5740fb5be --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/consumer.h @@ -0,0 +1,27 @@ +/******************************************************************************** + * 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_MOVE_SEMANTICS_SKELETON_METHOD_CONSUMER_H +#define SCORE_MW_COM_TEST_MOVE_SEMANTICS_SKELETON_METHOD_CONSUMER_H + +#include "score/mw/com/test/move_semantics/skeleton_method/test_parameters.h" + +#include + +namespace score::mw::com::test +{ + +void RunConsumer(const SkeletonMoveScenario& scenario, const score::cpp::stop_token& stop_token); + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_MOVE_SEMANTICS_SKELETON_METHOD_CONSUMER_H diff --git a/score/mw/com/test/move_semantics/skeleton_method/main_consumer.cpp b/score/mw/com/test/move_semantics/skeleton_method/main_consumer.cpp new file mode 100644 index 000000000..5b8e1ee0d --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/main_consumer.cpp @@ -0,0 +1,42 @@ +/******************************************************************************** + * 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/skeleton_method/consumer.h" +#include "score/mw/com/test/move_semantics/skeleton_method/test_parameters.h" + +#include + +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; + } + + std::cout << "Starting consumer with scenario " << static_cast(test_configuration.scenario) + << std::endl; + + score::mw::com::test::RunConsumer(test_configuration.scenario, stop_source.get_token()); + + return EXIT_SUCCESS; +} diff --git a/score/mw/com/test/move_semantics/skeleton_method/main_consumer_and_provider.cpp b/score/mw/com/test/move_semantics/skeleton_method/main_consumer_and_provider.cpp new file mode 100644 index 000000000..99a531b01 --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/main_consumer_and_provider.cpp @@ -0,0 +1,51 @@ +/******************************************************************************** + * 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/skeleton_method/consumer.h" +#include "score/mw/com/test/move_semantics/skeleton_method/provider.h" +#include "score/mw/com/test/move_semantics/skeleton_method/test_parameters.h" + +#include +#include + +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; + } + + std::cout << "Starting consumer and provider with scenario " + << static_cast(test_configuration.scenario) << std::endl; + + auto provider_future = + std::async(score::mw::com::test::RunProvider, test_configuration.scenario, stop_source.get_token()); + + auto consumer_future = + std::async(score::mw::com::test::RunConsumer, test_configuration.scenario, stop_source.get_token()); + + provider_future.get(); + consumer_future.get(); + + return EXIT_SUCCESS; +} diff --git a/score/mw/com/test/move_semantics/skeleton_method/main_provider.cpp b/score/mw/com/test/move_semantics/skeleton_method/main_provider.cpp new file mode 100644 index 000000000..a53b76f4b --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/main_provider.cpp @@ -0,0 +1,42 @@ +/******************************************************************************** + * 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/skeleton_method/provider.h" +#include "score/mw/com/test/move_semantics/skeleton_method/test_parameters.h" + +#include + +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; + } + + std::cout << "Starting provider with scenario " << static_cast(test_configuration.scenario) + << std::endl; + + score::mw::com::test::RunProvider(test_configuration.scenario, stop_source.get_token()); + + return EXIT_SUCCESS; +} diff --git a/score/mw/com/test/move_semantics/skeleton_method/provider.cpp b/score/mw/com/test/move_semantics/skeleton_method/provider.cpp new file mode 100644 index 000000000..dc5db173e --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/provider.cpp @@ -0,0 +1,328 @@ +/******************************************************************************** + * 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/skeleton_method/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/skeleton_method/test_method_datatype.h" +#include "score/mw/com/test/move_semantics/skeleton_method/test_parameters.h" + +#include + +#include +#include + +namespace score::mw::com::test +{ +namespace +{ + +const std::string kProxyDoneShmPath{"/skeleton_method_move_semantics_proxy_done_sync"}; +const std::string kSkeletonReadyShmPath{"/skeleton_method_move_semantics_skeleton_ready_sync"}; + +void RunProviderMoveConstructBeforeOffered(const score::cpp::stop_token& stop_token, + ProcessSynchronizer& proxy_done_sync) +{ + // Step 1. Create Skeleton A + std::cout << "\nProvider: Step 1 - Create Skeleton A" << std::endl; + SkeletonContainer skeleton_container{}; + skeleton_container.CreateSkeleton(kInstanceSpecifierMovedTo, "skeleton_method_move_semantics"); + auto skeleton_a = skeleton_container.Extract(); + + // Step 2. Register Handler A on Skeleton A + std::cout << "\nProvider: Step 2 - Register Handler A (a + b)" << std::endl; + const auto register_result = skeleton_a.moved_method_.RegisterHandler( + [](std::int32_t& result, const std::int32_t& a, const std::int32_t& b) { + result = a + b; + }); + if (!register_result.has_value()) + { + FailTest("Provider: Failed to register Handler A: ", register_result.error()); + } + + // Step 3. Move construct: Skeleton B = std::move(Skeleton A) [before OfferService] + std::cout << "\nProvider: Step 3 - Move construct Skeleton B = std::move(Skeleton A)" << std::endl; + auto skeleton_b = std::move(skeleton_a); + + // Step 4. Offer Skeleton B + std::cout << "\nProvider: Step 4 - Offer Skeleton B" << std::endl; + const auto offer_result = skeleton_b.OfferService(); + if (!offer_result.has_value()) + { + FailTest("Provider: OfferService failed: ", offer_result.error()); + } + + // Step 5. Wait for consumer to call Handler A and notify done + std::cout << "\nProvider: Step 5 - Wait for consumer to call Handler A" << std::endl; + if (!proxy_done_sync.WaitWithAbort(stop_token)) + { + FailTest("Provider: WaitWithAbort was stopped by stop_token"); + } +} + +void RunProviderMoveConstructAfterOffered(const score::cpp::stop_token& stop_token, + ProcessSynchronizer& proxy_done_sync, + ProcessSynchronizer& skeleton_ready_sync) +{ + // Step 1. Create Skeleton A + std::cout << "\nProvider: Step 1 - Create Skeleton A" << std::endl; + SkeletonContainer skeleton_container{}; + skeleton_container.CreateSkeleton(kInstanceSpecifierMovedTo, "skeleton_method_move_semantics"); + + // Step 2. Register Handler A on Skeleton A + std::cout << "\nProvider: Step 2 - Register Handler A (a + b)" << std::endl; + const auto register_a_result = skeleton_container.GetSkeleton().moved_method_.RegisterHandler( + [](std::int32_t& result, const std::int32_t& a, const std::int32_t& b) { + result = a + b; + }); + if (!register_a_result.has_value()) + { + FailTest("Provider: Failed to register Handler A: ", register_a_result.error()); + } + + // Step 3. Offer Skeleton A + std::cout << "\nProvider: Step 3 - Offer Skeleton A" << std::endl; + skeleton_container.OfferService("skeleton_method_move_semantics"); + + // Step 4. Wait for proxy to be created (shared memory now exists) + std::cout << "\nProvider: Step 4 - Wait for proxy created signal" << std::endl; + if (!proxy_done_sync.WaitWithAbort(stop_token)) + { + FailTest("Provider: WaitWithAbort (proxy created) was stopped by stop_token"); + } + proxy_done_sync.Reset(); + + // Step 5. Move construct: Skeleton B = std::move(Skeleton A) [after SHM exists] + std::cout << "\nProvider: Step 5 - Move construct Skeleton B = std::move(Skeleton A)" << std::endl; + auto skeleton_b = std::move(skeleton_container.GetSkeleton()); + + // Step 6. Signal consumer: move done, call Handler A + std::cout << "\nProvider: Step 6 - Notify consumer: move done" << std::endl; + skeleton_ready_sync.Notify(); + + // Step 7. Wait for consumer to call Handler A + std::cout << "\nProvider: Step 7 - Wait for Handler A call" << std::endl; + if (!proxy_done_sync.WaitWithAbort(stop_token)) + { + FailTest("Provider: WaitWithAbort (Handler A) was stopped by stop_token"); + } + proxy_done_sync.Reset(); + + // Step 8. Register Handler B on Skeleton B + std::cout << "\nProvider: Step 8 - Register Handler B (a * b) on Skeleton B" << std::endl; + const auto register_b_result = skeleton_b.moved_method_.RegisterHandler( + [](std::int32_t& result, const std::int32_t& a, const std::int32_t& b) { + result = a * b; + }); + if (!register_b_result.has_value()) + { + FailTest("Provider: Failed to register Handler B: ", register_b_result.error()); + } + + // Step 9. Signal consumer: Handler B registered + std::cout << "\nProvider: Step 9 - Notify consumer: Handler B registered" << std::endl; + skeleton_ready_sync.Notify(); + + // Step 10. Wait for consumer to call Handler B + std::cout << "\nProvider: Step 10 - Wait for Handler B call" << std::endl; + if (!proxy_done_sync.WaitWithAbort(stop_token)) + { + FailTest("Provider: WaitWithAbort (Handler B) was stopped by stop_token"); + } +} + +void RunProviderMoveAssignBeforeOffered(const score::cpp::stop_token& stop_token, ProcessSynchronizer& proxy_done_sync) +{ + // Step 1. Create moved_from_skeleton (kMovedTo identity) and moved_to_skeleton (kMovedFrom identity) + std::cout << "\nProvider: Step 1 - Create two skeletons" << std::endl; + SkeletonContainer moved_from_container{}; + moved_from_container.CreateSkeleton(kInstanceSpecifierMovedTo, "skeleton_method_move_semantics"); + auto moved_from_skeleton = moved_from_container.Extract(); + + SkeletonContainer moved_to_container{}; + moved_to_container.CreateSkeleton(kInstanceSpecifierMovedFrom, "skeleton_method_move_semantics"); + auto moved_to_skeleton = moved_to_container.Extract(); + + // Step 2. Register Handler A on moved_from_skeleton + std::cout << "\nProvider: Step 2 - Register Handler A (a + b) on moved_from_skeleton" << std::endl; + const auto register_result = moved_from_skeleton.moved_method_.RegisterHandler( + [](std::int32_t& result, const std::int32_t& a, const std::int32_t& b) { + result = a + b; + }); + if (!register_result.has_value()) + { + FailTest("Provider: Failed to register Handler A: ", register_result.error()); + } + + // Step 3. Move assign: moved_to_skeleton = std::move(moved_from_skeleton) + // moved_to_skeleton now has kMovedTo identity + Handler A + std::cout << "\nProvider: Step 3 - Move assign moved_to = std::move(moved_from)" << std::endl; + moved_to_skeleton = std::move(moved_from_skeleton); + + // Step 4. Offer moved_to_skeleton + std::cout << "\nProvider: Step 4 - Offer moved_to_skeleton" << std::endl; + const auto offer_result = moved_to_skeleton.OfferService(); + if (!offer_result.has_value()) + { + FailTest("Provider: OfferService failed: ", offer_result.error()); + } + + // Step 5. Wait for consumer to call Handler A and notify done + std::cout << "\nProvider: Step 5 - Wait for consumer to call Handler A" << std::endl; + if (!proxy_done_sync.WaitWithAbort(stop_token)) + { + FailTest("Provider: WaitWithAbort was stopped by stop_token"); + } +} + +void RunProviderMoveAssignAfterOffered(const score::cpp::stop_token& stop_token, + ProcessSynchronizer& proxy_done_sync, + ProcessSynchronizer& skeleton_ready_sync) +{ + // Step 1. Create two skeletons + std::cout << "\nProvider: Step 1 - Create two skeletons" << std::endl; + SkeletonContainer moved_from_container{}; + moved_from_container.CreateSkeleton(kInstanceSpecifierMovedTo, "skeleton_method_move_semantics"); + + SkeletonContainer moved_to_container{}; + moved_to_container.CreateSkeleton(kInstanceSpecifierMovedFrom, "skeleton_method_move_semantics"); + + // Step 2. Register Handler A on moved_from, Handler B on moved_to + std::cout << "\nProvider: Step 2 - Register Handler A (a + b) and Handler B (a * b)" << std::endl; + const auto register_a_result = moved_from_container.GetSkeleton().moved_method_.RegisterHandler( + [](std::int32_t& result, const std::int32_t& a, const std::int32_t& b) { + result = a + b; + }); + if (!register_a_result.has_value()) + { + FailTest("Provider: Failed to register Handler A: ", register_a_result.error()); + } + + const auto register_b_result = moved_to_container.GetSkeleton().moved_method_.RegisterHandler( + [](std::int32_t& result, const std::int32_t& a, const std::int32_t& b) { + result = a * b; + }); + if (!register_b_result.has_value()) + { + FailTest("Provider: Failed to register Handler B: ", register_b_result.error()); + } + + // Step 3. Offer both skeletons + std::cout << "\nProvider: Step 3 - Offer both skeletons" << std::endl; + moved_from_container.OfferService("skeleton_method_move_semantics"); + moved_to_container.OfferService("skeleton_method_move_semantics"); + + // Step 4. Wait for both proxies to be created (single notify from consumer) + std::cout << "\nProvider: Step 4 - Wait for both proxies created signal" << std::endl; + if (!proxy_done_sync.WaitWithAbort(stop_token)) + { + FailTest("Provider: WaitWithAbort (proxies created) was stopped by stop_token"); + } + proxy_done_sync.Reset(); + + // Step 5. Move assign: moved_to = std::move(moved_from) + // moved_to now has kMovedTo identity + Handler A + std::cout << "\nProvider: Step 5 - Move assign moved_to = std::move(moved_from)" << std::endl; + auto moved_from_skeleton = moved_from_container.Extract(); + auto moved_to_skeleton = moved_to_container.Extract(); + moved_to_skeleton = std::move(moved_from_skeleton); + + // Step 6. Signal consumer: move done, call Handler A via kMovedTo proxy + std::cout << "\nProvider: Step 6 - Notify consumer: move done" << std::endl; + skeleton_ready_sync.Notify(); + + // Step 7. Wait for consumer to call Handler A (a+b = 15) + std::cout << "\nProvider: Step 7 - Wait for Handler A call" << std::endl; + if (!proxy_done_sync.WaitWithAbort(stop_token)) + { + FailTest("Provider: WaitWithAbort (Handler A) was stopped by stop_token"); + } + proxy_done_sync.Reset(); + + // Step 8. Register Handler C on moved_to_skeleton (Skeleton A internally stores B's handle) + std::cout << "\nProvider: Step 8 - Register Handler C (a - b) on moved_to_skeleton" << std::endl; + const auto register_c_result = moved_to_skeleton.moved_method_.RegisterHandler( + [](std::int32_t& result, const std::int32_t& a, const std::int32_t& b) { + result = a - b; + }); + if (!register_c_result.has_value()) + { + FailTest("Provider: Failed to register Handler C: ", register_c_result.error()); + } + + // Step 9. Signal consumer: Handler C registered + std::cout << "\nProvider: Step 9 - Notify consumer: Handler C registered" << std::endl; + skeleton_ready_sync.Notify(); + + // Step 10. Wait for consumer to call Handler C (a-b = 5) + std::cout << "\nProvider: Step 10 - Wait for Handler C call" << std::endl; + if (!proxy_done_sync.WaitWithAbort(stop_token)) + { + FailTest("Provider: WaitWithAbort (Handler C) was stopped by stop_token"); + } +} + +} // namespace + +void RunProvider(const SkeletonMoveScenario& scenario, const score::cpp::stop_token& stop_token) +{ + auto proxy_done_sync = ProcessSynchronizer::Create(kProxyDoneShmPath); + if (!proxy_done_sync.has_value()) + { + FailTest("Provider: Failed to create proxy_done ProcessSynchronizer"); + } + + switch (scenario) + { + case SkeletonMoveScenario::kMoveConstructBeforeOffered: + { + RunProviderMoveConstructBeforeOffered(stop_token, proxy_done_sync.value()); + break; + } + case SkeletonMoveScenario::kMoveConstructAfterOffered: + { + auto skeleton_ready_sync = ProcessSynchronizer::Create(kSkeletonReadyShmPath); + if (!skeleton_ready_sync.has_value()) + { + FailTest("Provider: Failed to create skeleton_ready ProcessSynchronizer"); + } + RunProviderMoveConstructAfterOffered(stop_token, proxy_done_sync.value(), skeleton_ready_sync.value()); + break; + } + case SkeletonMoveScenario::kMoveAssignBeforeOffered: + { + RunProviderMoveAssignBeforeOffered(stop_token, proxy_done_sync.value()); + break; + } + case SkeletonMoveScenario::kMoveAssignAfterOffered: + { + auto skeleton_ready_sync = ProcessSynchronizer::Create(kSkeletonReadyShmPath); + if (!skeleton_ready_sync.has_value()) + { + FailTest("Provider: Failed to create skeleton_ready ProcessSynchronizer"); + } + RunProviderMoveAssignAfterOffered(stop_token, proxy_done_sync.value(), skeleton_ready_sync.value()); + break; + } + case SkeletonMoveScenario::kNumberOfScenarios: + [[fallthrough]]; + default: + { + FailTest("Provider: Unknown scenario"); + break; + } + } +} + +} // namespace score::mw::com::test diff --git a/score/mw/com/test/move_semantics/skeleton_method/provider.h b/score/mw/com/test/move_semantics/skeleton_method/provider.h new file mode 100644 index 000000000..412d572fa --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/provider.h @@ -0,0 +1,27 @@ +/******************************************************************************** + * 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_MOVE_SEMANTICS_SKELETON_METHOD_PROVIDER_H +#define SCORE_MW_COM_TEST_MOVE_SEMANTICS_SKELETON_METHOD_PROVIDER_H + +#include "score/mw/com/test/move_semantics/skeleton_method/test_parameters.h" + +#include + +namespace score::mw::com::test +{ + +void RunProvider(const SkeletonMoveScenario& scenario, const score::cpp::stop_token& stop_token); + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_MOVE_SEMANTICS_SKELETON_METHOD_PROVIDER_H From a5181ea86b727bc9f75a19bc596d3c03b7220716 Mon Sep 17 00:00:00 2001 From: tejveerpratap Date: Tue, 7 Jul 2026 13:02:59 +0530 Subject: [PATCH 3/3] test(mw/com): Add integration test scenarios --- .../skeleton_method/integration_test/BUILD | 95 +++++++++++++++++++ ...offered_skeleton_different_process_test.py | 19 ++++ ...fter_offered_skeleton_same_process_test.py | 18 ++++ ...offered_skeleton_different_process_test.py | 19 ++++ ...fore_offered_skeleton_same_process_test.py | 18 ++++ ...offered_skeleton_different_process_test.py | 19 ++++ ...fter_offered_skeleton_same_process_test.py | 18 ++++ ...offered_skeleton_different_process_test.py | 19 ++++ ...fore_offered_skeleton_same_process_test.py | 18 ++++ .../integration_test/test_fixture.py | 41 ++++++++ 10 files changed, 284 insertions(+) create mode 100644 score/mw/com/test/move_semantics/skeleton_method/integration_test/BUILD create mode 100644 score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_after_offered_skeleton_different_process_test.py create mode 100644 score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_after_offered_skeleton_same_process_test.py create mode 100644 score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_before_offered_skeleton_different_process_test.py create mode 100644 score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_before_offered_skeleton_same_process_test.py create mode 100644 score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_after_offered_skeleton_different_process_test.py create mode 100644 score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_after_offered_skeleton_same_process_test.py create mode 100644 score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_before_offered_skeleton_different_process_test.py create mode 100644 score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_before_offered_skeleton_same_process_test.py create mode 100644 score/mw/com/test/move_semantics/skeleton_method/integration_test/test_fixture.py diff --git a/score/mw/com/test/move_semantics/skeleton_method/integration_test/BUILD b/score/mw/com/test/move_semantics/skeleton_method/integration_test/BUILD new file mode 100644 index 000000000..6a78944a3 --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/integration_test/BUILD @@ -0,0 +1,95 @@ +# ******************************************************************************* +# 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_offered_skeleton_same_process_test", + srcs = [ + "move_construct_before_offered_skeleton_same_process_test.py", + "test_fixture.py", + ], + filesystem = "//score/mw/com/test/move_semantics/skeleton_method:main_consumer_and_provider-pkg", +) + +integration_test( + name = "move_construct_after_offered_skeleton_same_process_test", + srcs = [ + "move_construct_after_offered_skeleton_same_process_test.py", + "test_fixture.py", + ], + filesystem = "//score/mw/com/test/move_semantics/skeleton_method:main_consumer_and_provider-pkg", +) + +integration_test( + name = "move_assign_before_offered_skeleton_same_process_test", + srcs = [ + "move_assign_before_offered_skeleton_same_process_test.py", + "test_fixture.py", + ], + filesystem = "//score/mw/com/test/move_semantics/skeleton_method:main_consumer_and_provider-pkg", +) + +integration_test( + name = "move_assign_after_offered_skeleton_same_process_test", + srcs = [ + "move_assign_after_offered_skeleton_same_process_test.py", + "test_fixture.py", + ], + filesystem = "//score/mw/com/test/move_semantics/skeleton_method:main_consumer_and_provider-pkg", +) + +pkg_filegroup( + name = "different_processes_filesystem", + srcs = [ + "//score/mw/com/test/move_semantics/skeleton_method:main_consumer-pkg", + "//score/mw/com/test/move_semantics/skeleton_method:main_provider-pkg", + ], +) + +integration_test( + name = "move_construct_before_offered_skeleton_different_process_test", + srcs = [ + "move_construct_before_offered_skeleton_different_process_test.py", + "test_fixture.py", + ], + filesystem = ":different_processes_filesystem", +) + +integration_test( + name = "move_construct_after_offered_skeleton_different_process_test", + srcs = [ + "move_construct_after_offered_skeleton_different_process_test.py", + "test_fixture.py", + ], + filesystem = ":different_processes_filesystem", +) + +integration_test( + name = "move_assign_before_offered_skeleton_different_process_test", + srcs = [ + "move_assign_before_offered_skeleton_different_process_test.py", + "test_fixture.py", + ], + filesystem = ":different_processes_filesystem", +) + +integration_test( + name = "move_assign_after_offered_skeleton_different_process_test", + srcs = [ + "move_assign_after_offered_skeleton_different_process_test.py", + "test_fixture.py", + ], + filesystem = ":different_processes_filesystem", +) diff --git a/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_after_offered_skeleton_different_process_test.py b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_after_offered_skeleton_different_process_test.py new file mode 100644 index 000000000..53affcad5 --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_after_offered_skeleton_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, SkeletonMoveScenario + + +def test_move_assign_after_offered_different_process(target): + with consumer(target, SkeletonMoveScenario.MOVE_ASSIGN_AFTER_OFFERED): + with provider(target, SkeletonMoveScenario.MOVE_ASSIGN_AFTER_OFFERED): + pass diff --git a/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_after_offered_skeleton_same_process_test.py b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_after_offered_skeleton_same_process_test.py new file mode 100644 index 000000000..b5b8e33cc --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_after_offered_skeleton_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, SkeletonMoveScenario + + +def test_move_assign_after_offered_same_process(target): + with consumer_and_provider(target, SkeletonMoveScenario.MOVE_ASSIGN_AFTER_OFFERED): + pass diff --git a/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_before_offered_skeleton_different_process_test.py b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_before_offered_skeleton_different_process_test.py new file mode 100644 index 000000000..94cdd59fd --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_before_offered_skeleton_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, SkeletonMoveScenario + + +def test_move_assign_before_offered_different_process(target): + with consumer(target, SkeletonMoveScenario.MOVE_ASSIGN_BEFORE_OFFERED): + with provider(target, SkeletonMoveScenario.MOVE_ASSIGN_BEFORE_OFFERED): + pass diff --git a/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_before_offered_skeleton_same_process_test.py b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_before_offered_skeleton_same_process_test.py new file mode 100644 index 000000000..b49b935d2 --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_assign_before_offered_skeleton_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, SkeletonMoveScenario + + +def test_move_assign_before_offered_same_process(target): + with consumer_and_provider(target, SkeletonMoveScenario.MOVE_ASSIGN_BEFORE_OFFERED): + pass diff --git a/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_after_offered_skeleton_different_process_test.py b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_after_offered_skeleton_different_process_test.py new file mode 100644 index 000000000..f68e5d8eb --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_after_offered_skeleton_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, SkeletonMoveScenario + + +def test_move_construct_after_offered_different_process(target): + with consumer(target, SkeletonMoveScenario.MOVE_CONSTRUCT_AFTER_OFFERED): + with provider(target, SkeletonMoveScenario.MOVE_CONSTRUCT_AFTER_OFFERED): + pass diff --git a/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_after_offered_skeleton_same_process_test.py b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_after_offered_skeleton_same_process_test.py new file mode 100644 index 000000000..bdd5112b2 --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_after_offered_skeleton_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, SkeletonMoveScenario + + +def test_move_construct_after_offered_same_process(target): + with consumer_and_provider(target, SkeletonMoveScenario.MOVE_CONSTRUCT_AFTER_OFFERED): + pass diff --git a/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_before_offered_skeleton_different_process_test.py b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_before_offered_skeleton_different_process_test.py new file mode 100644 index 000000000..43e327388 --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_before_offered_skeleton_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, SkeletonMoveScenario + + +def test_move_construct_before_offered_different_process(target): + with consumer(target, SkeletonMoveScenario.MOVE_CONSTRUCT_BEFORE_OFFERED): + with provider(target, SkeletonMoveScenario.MOVE_CONSTRUCT_BEFORE_OFFERED): + pass diff --git a/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_before_offered_skeleton_same_process_test.py b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_before_offered_skeleton_same_process_test.py new file mode 100644 index 000000000..258fe040b --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/integration_test/move_construct_before_offered_skeleton_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, SkeletonMoveScenario + + +def test_move_construct_before_offered_same_process(target): + with consumer_and_provider(target, SkeletonMoveScenario.MOVE_CONSTRUCT_BEFORE_OFFERED): + pass diff --git a/score/mw/com/test/move_semantics/skeleton_method/integration_test/test_fixture.py b/score/mw/com/test/move_semantics/skeleton_method/integration_test/test_fixture.py new file mode 100644 index 000000000..56fde7402 --- /dev/null +++ b/score/mw/com/test/move_semantics/skeleton_method/integration_test/test_fixture.py @@ -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 +# ******************************************************************************* +from enum import IntEnum + + +class SkeletonMoveScenario(IntEnum): + MOVE_CONSTRUCT_BEFORE_OFFERED = 0 + MOVE_CONSTRUCT_AFTER_OFFERED = 1 + MOVE_ASSIGN_BEFORE_OFFERED = 2 + MOVE_ASSIGN_AFTER_OFFERED = 3 + + +def consumer_and_provider(target, scenario, **kwargs): + args = ["--scenario", str(int(scenario)), "--service-instance-manifest", f"./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", f"./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", f"./etc/mw_com_config.json"] + return target.wrap_exec( + "bin/main_provider", args, cwd="/opt/MainProviderApp", wait_on_exit=True, **kwargs + )