From ad0d78f67278bf7b3115719f537735cff99719ed Mon Sep 17 00:00:00 2001 From: sahithinukala Date: Tue, 26 May 2026 10:41:48 +0530 Subject: [PATCH 01/13] Update traits and traits tests for field get/set/notifier parameters --- score/mw/com/impl/traits.h | 4 ++-- score/mw/com/impl/traits_test.cpp | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/score/mw/com/impl/traits.h b/score/mw/com/impl/traits.h index 891933ee5..653270ef4 100644 --- a/score/mw/com/impl/traits.h +++ b/score/mw/com/impl/traits.h @@ -142,7 +142,7 @@ class ProxyTrait // Note : at the moment the SkeletonField::Get implementation is not in the branch which means the skeleton and // proxy side does not have same template parameters. template - using Field = ProxyField; + using Field = ProxyField; template using Method = ProxyMethod; @@ -164,7 +164,7 @@ class SkeletonTrait template using Event = SkeletonEvent; - template + template using Field = SkeletonField; template diff --git a/score/mw/com/impl/traits_test.cpp b/score/mw/com/impl/traits_test.cpp index 975653d5f..85913f373 100644 --- a/score/mw/com/impl/traits_test.cpp +++ b/score/mw/com/impl/traits_test.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -69,10 +70,13 @@ class MyInterface : public InterfaceTrait::Base public: using InterfaceTrait::Base::Base; + static constexpr bool kEnableSet{std::is_same_v}; + typename InterfaceTrait::template Event some_event{*this, kEventName}; - typename InterfaceTrait::template Field some_field{*this, kFieldName}; + typename InterfaceTrait::template Field some_field{*this, kFieldName}; typename InterfaceTrait::template Method some_method{*this, kMethodName}; }; + using MyProxy = AsProxy; using MySkeleton = AsSkeleton; From 56673caacc3dab7da3260a86fd1361bd9d6dbf7a Mon Sep 17 00:00:00 2001 From: sahithinukala Date: Fri, 29 May 2026 13:19:02 +0530 Subject: [PATCH 02/13] mw/com: move field_initial_value test package under fields --- .../test/{ => fields}/field_initial_value/BUILD | 16 ++++++++++++---- .../{ => fields}/field_initial_value/client.cpp | 3 +-- .../field_initial_value/config/logging.json | 1 - .../config/mw_com_config.json | 7 +++---- .../field_initial_value/integration_test/BUILD | 4 ++-- .../integration_test/test_field_initial_value.py | 0 .../{ => fields}/field_initial_value/service.cpp | 5 ++--- .../field_initial_value/test_datatype.cpp | 2 +- .../field_initial_value/test_datatype.h | 8 ++++---- 9 files changed, 25 insertions(+), 21 deletions(-) rename score/mw/com/test/{ => fields}/field_initial_value/BUILD (82%) rename score/mw/com/test/{ => fields}/field_initial_value/client.cpp (97%) rename score/mw/com/test/{ => fields}/field_initial_value/config/logging.json (99%) rename score/mw/com/test/{ => fields}/field_initial_value/config/mw_com_config.json (78%) rename score/mw/com/test/{ => fields}/field_initial_value/integration_test/BUILD (87%) rename score/mw/com/test/{ => fields}/field_initial_value/integration_test/test_field_initial_value.py (100%) rename score/mw/com/test/{ => fields}/field_initial_value/service.cpp (96%) rename score/mw/com/test/{ => fields}/field_initial_value/test_datatype.cpp (88%) rename score/mw/com/test/{ => fields}/field_initial_value/test_datatype.h (82%) diff --git a/score/mw/com/test/field_initial_value/BUILD b/score/mw/com/test/fields/field_initial_value/BUILD similarity index 82% rename from score/mw/com/test/field_initial_value/BUILD rename to score/mw/com/test/fields/field_initial_value/BUILD index e68fbbd18..c08fa4b75 100644 --- a/score/mw/com/test/field_initial_value/BUILD +++ b/score/mw/com/test/fields/field_initial_value/BUILD @@ -40,7 +40,7 @@ cc_binary( features = COMPILER_WARNING_FEATURES + [ "aborts_upon_exception", ], - visibility = ["//score/mw/com/test/field_initial_value:__pkg__"], + visibility = ["//score/mw/com/test/fields/field_initial_value:__pkg__"], deps = [ ":test_datatype", "//score/mw/com", @@ -56,7 +56,7 @@ cc_binary( features = COMPILER_WARNING_FEATURES + [ "aborts_upon_exception", ], - visibility = ["//score/mw/com/test/field_initial_value:__pkg__"], + visibility = ["//score/mw/com/test/fields/field_initial_value:__pkg__"], deps = [ ":test_datatype", "//score/mw/com", @@ -75,7 +75,7 @@ pkg_application( ], visibility = [ "//platform/aas/test/mw/com:__pkg__", - "//score/mw/com/test/field_initial_value:__subpackages__", + "//score/mw/com/test/fields/field_initial_value:__subpackages__", ], ) @@ -89,6 +89,14 @@ pkg_application( ], visibility = [ "//platform/aas/test/mw/com:__pkg__", - "//score/mw/com/test/field_initial_value:__subpackages__", + "//score/mw/com/test/fields/field_initial_value:__subpackages__", ], ) + +test_suite( + name = "component_tests", + tests = [ + "//score/mw/com/test/fields/field_initial_value/integration_test:test_field_initial_value", + ], + visibility = ["//score/mw/com/test/fields:__pkg__"], +) diff --git a/score/mw/com/test/field_initial_value/client.cpp b/score/mw/com/test/fields/field_initial_value/client.cpp similarity index 97% rename from score/mw/com/test/field_initial_value/client.cpp rename to score/mw/com/test/fields/field_initial_value/client.cpp index b58464eab..bdf0b1b11 100644 --- a/score/mw/com/test/field_initial_value/client.cpp +++ b/score/mw/com/test/fields/field_initial_value/client.cpp @@ -12,7 +12,7 @@ *******************************************************************************/ #include "score/mw/com/test/common_test_resources/sctf_test_runner.h" -#include "score/mw/com/test/field_initial_value/test_datatype.h" +#include "score/mw/com/test/fields/field_initial_value/test_datatype.h" #include "score/mw/com/types.h" #include @@ -122,7 +122,6 @@ int main(int argc, const char** argv) const auto& run_parameters = test_runner.GetRunParameters(); const auto num_retries = run_parameters.GetNumRetries(); const auto retry_backoff_time = run_parameters.GetRetryBackoffTime(); - const auto stop_token = test_runner.GetStopToken(); return score::mw::com::test::run_client(num_retries, retry_backoff_time); } diff --git a/score/mw/com/test/field_initial_value/config/logging.json b/score/mw/com/test/fields/field_initial_value/config/logging.json similarity index 99% rename from score/mw/com/test/field_initial_value/config/logging.json rename to score/mw/com/test/fields/field_initial_value/config/logging.json index f224f16f9..de20e5520 100644 --- a/score/mw/com/test/field_initial_value/config/logging.json +++ b/score/mw/com/test/fields/field_initial_value/config/logging.json @@ -5,4 +5,3 @@ "logLevelThresholdConsole": "kDebug", "logMode": "kRemote|kConsole" } - diff --git a/score/mw/com/test/field_initial_value/config/mw_com_config.json b/score/mw/com/test/fields/field_initial_value/config/mw_com_config.json similarity index 78% rename from score/mw/com/test/field_initial_value/config/mw_com_config.json rename to score/mw/com/test/fields/field_initial_value/config/mw_com_config.json index bbb0beba5..36b40fe8e 100644 --- a/score/mw/com/test/field_initial_value/config/mw_com_config.json +++ b/score/mw/com/test/fields/field_initial_value/config/mw_com_config.json @@ -1,7 +1,7 @@ { "serviceTypes": [ { - "serviceTypeName": "/score/mw/com/test/field_initial_value", + "serviceTypeName": "/score/mw/com/test/fields/field_initial_value", "version": { "major": 1, "minor": 0 @@ -22,8 +22,8 @@ ], "serviceInstances": [ { - "instanceSpecifier": "test/field_initial_value", - "serviceTypeName": "/score/mw/com/test/field_initial_value", + "instanceSpecifier": "test/fields/field_initial_value", + "serviceTypeName": "/score/mw/com/test/fields/field_initial_value", "version": { "major": 1, "minor": 0 @@ -45,4 +45,3 @@ } ] } - diff --git a/score/mw/com/test/field_initial_value/integration_test/BUILD b/score/mw/com/test/fields/field_initial_value/integration_test/BUILD similarity index 87% rename from score/mw/com/test/field_initial_value/integration_test/BUILD rename to score/mw/com/test/fields/field_initial_value/integration_test/BUILD index 0c75b747b..85fe56d70 100644 --- a/score/mw/com/test/field_initial_value/integration_test/BUILD +++ b/score/mw/com/test/fields/field_initial_value/integration_test/BUILD @@ -16,8 +16,8 @@ load("//quality/integration_testing:integration_testing.bzl", "integration_test" pkg_filegroup( name = "filesystem", srcs = [ - "//score/mw/com/test/field_initial_value:client-pkg", - "//score/mw/com/test/field_initial_value:service-pkg", + "//score/mw/com/test/fields/field_initial_value:client-pkg", + "//score/mw/com/test/fields/field_initial_value:service-pkg", ], ) diff --git a/score/mw/com/test/field_initial_value/integration_test/test_field_initial_value.py b/score/mw/com/test/fields/field_initial_value/integration_test/test_field_initial_value.py similarity index 100% rename from score/mw/com/test/field_initial_value/integration_test/test_field_initial_value.py rename to score/mw/com/test/fields/field_initial_value/integration_test/test_field_initial_value.py diff --git a/score/mw/com/test/field_initial_value/service.cpp b/score/mw/com/test/fields/field_initial_value/service.cpp similarity index 96% rename from score/mw/com/test/field_initial_value/service.cpp rename to score/mw/com/test/fields/field_initial_value/service.cpp index b17710b43..c77c39b6e 100644 --- a/score/mw/com/test/field_initial_value/service.cpp +++ b/score/mw/com/test/fields/field_initial_value/service.cpp @@ -12,11 +12,12 @@ *******************************************************************************/ #include "score/mw/com/test/common_test_resources/sctf_test_runner.h" -#include "score/mw/com/test/field_initial_value/test_datatype.h" +#include "score/mw/com/test/fields/field_initial_value/test_datatype.h" #include #include +#include #include #include @@ -26,8 +27,6 @@ namespace score::mw::com::test namespace { -using namespace std::chrono_literals; - int run_service(const std::chrono::milliseconds& cycle_time, const score::cpp::stop_token& stop_token) { auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); diff --git a/score/mw/com/test/field_initial_value/test_datatype.cpp b/score/mw/com/test/fields/field_initial_value/test_datatype.cpp similarity index 88% rename from score/mw/com/test/field_initial_value/test_datatype.cpp rename to score/mw/com/test/fields/field_initial_value/test_datatype.cpp index ab6b0f1ac..3a2a65351 100644 --- a/score/mw/com/test/field_initial_value/test_datatype.cpp +++ b/score/mw/com/test/fields/field_initial_value/test_datatype.cpp @@ -11,4 +11,4 @@ * SPDX-License-Identifier: Apache-2.0 *******************************************************************************/ -#include "score/mw/com/test/field_initial_value/test_datatype.h" +#include "score/mw/com/test/fields/field_initial_value/test_datatype.h" diff --git a/score/mw/com/test/field_initial_value/test_datatype.h b/score/mw/com/test/fields/field_initial_value/test_datatype.h similarity index 82% rename from score/mw/com/test/field_initial_value/test_datatype.h rename to score/mw/com/test/fields/field_initial_value/test_datatype.h index 3f7348692..42d0278bf 100644 --- a/score/mw/com/test/field_initial_value/test_datatype.h +++ b/score/mw/com/test/fields/field_initial_value/test_datatype.h @@ -11,8 +11,8 @@ * SPDX-License-Identifier: Apache-2.0 *******************************************************************************/ -#ifndef SCORE_MW_COM_TEST_FIELD_INITIAL_VALUE_TEST_DATATYPE_H -#define SCORE_MW_COM_TEST_FIELD_INITIAL_VALUE_TEST_DATATYPE_H +#ifndef SCORE_MW_COM_TEST_FIELDS_FIELD_INITIAL_VALUE_TEST_DATATYPE_H +#define SCORE_MW_COM_TEST_FIELDS_FIELD_INITIAL_VALUE_TEST_DATATYPE_H #include "score/mw/com/types.h" @@ -22,7 +22,7 @@ namespace score::mw::com::test { -constexpr const char* const kInstanceSpecifierString = "test/field_initial_value"; +constexpr const char* const kInstanceSpecifierString = "test/fields/field_initial_value"; const std::int32_t kTestValue = 18; template @@ -39,4 +39,4 @@ using TestDataSkeleton = score::mw::com::AsSkeleton; } // namespace score::mw::com::test -#endif // SCORE_MW_COM_TEST_FIELD_RECEIVE_HANDLER_SRC_LOLA_H +#endif // SCORE_MW_COM_TEST_FIELDS_FIELD_INITIAL_VALUE_TEST_DATATYPE_H From 6e5ec2311e59a41b0988ba11635e60b2479c2cf4 Mon Sep 17 00:00:00 2001 From: sahithinukala Date: Fri, 29 May 2026 13:19:31 +0530 Subject: [PATCH 03/13] mw/com: add fields test suite root package --- score/mw/com/test/fields/BUILD | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 score/mw/com/test/fields/BUILD diff --git a/score/mw/com/test/fields/BUILD b/score/mw/com/test/fields/BUILD new file mode 100644 index 000000000..7bf308537 --- /dev/null +++ b/score/mw/com/test/fields/BUILD @@ -0,0 +1,21 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + +test_suite( + name = "component_tests", + tests = [ + "//score/mw/com/test/fields/field_initial_value:component_tests", + "//score/mw/com/test/fields/set_and_notifier:component_tests", + ], + visibility = ["//score/mw/com/test:__pkg__"], +) From 906833c1a4a15161101f9eb046aa92ba00e85ca0 Mon Sep 17 00:00:00 2001 From: sahithinukala Date: Fri, 29 May 2026 13:19:31 +0530 Subject: [PATCH 04/13] mw/com: add set_and_notifier field integration tests --- .../mw/com/test/fields/set_and_notifier/BUILD | 92 ++++++ .../set_and_notifier/config/logging.json | 7 + .../config/mw_com_config.json | 48 +++ .../fields_test_resources/BUILD | 56 ++++ .../fields_test_resources/field_consumer.cpp | 300 ++++++++++++++++++ .../fields_test_resources/field_consumer.h | 28 ++ .../fields_test_resources/field_provider.cpp | 149 +++++++++ .../fields_test_resources/field_provider.h | 31 ++ .../fields_test_resources/test_datatype.cpp | 14 + .../fields_test_resources/test_datatype.h | 59 ++++ .../set_and_notifier/integration_test/BUILD | 32 ++ .../test_field_set_and_notifier.py | 39 +++ .../fields/set_and_notifier/main_client.cpp | 30 ++ .../fields/set_and_notifier/main_service.cpp | 29 ++ 14 files changed, 914 insertions(+) create mode 100644 score/mw/com/test/fields/set_and_notifier/BUILD create mode 100644 score/mw/com/test/fields/set_and_notifier/config/logging.json create mode 100644 score/mw/com/test/fields/set_and_notifier/config/mw_com_config.json create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/BUILD create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.h create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.h create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.cpp create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h create mode 100644 score/mw/com/test/fields/set_and_notifier/integration_test/BUILD create mode 100644 score/mw/com/test/fields/set_and_notifier/integration_test/test_field_set_and_notifier.py create mode 100644 score/mw/com/test/fields/set_and_notifier/main_client.cpp create mode 100644 score/mw/com/test/fields/set_and_notifier/main_service.cpp diff --git a/score/mw/com/test/fields/set_and_notifier/BUILD b/score/mw/com/test/fields/set_and_notifier/BUILD new file mode 100644 index 000000000..6933ede4d --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/BUILD @@ -0,0 +1,92 @@ +# ******************************************************************************* +# 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") +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_lola_schema", + json = "config/mw_com_config.json", + schema = "//score/mw/com:config_schema", + tags = ["lint"], +) + +cc_binary( + name = "main_service", + srcs = ["main_service.cpp"], + data = ["config/mw_com_config.json"], + features = COMPILER_WARNING_FEATURES + [ + "aborts_upon_exception", + ], + visibility = ["//score/mw/com/test/fields:__pkg__"], + deps = [ + "//score/mw/com", + "//score/mw/com/test/common_test_resources:sctf_test_runner", + "//score/mw/com/test/fields/set_and_notifier/fields_test_resources:field_provider", + "@score_baselibs//score/mw/log", + ], +) + +cc_binary( + name = "main_client", + srcs = ["main_client.cpp"], + data = ["config/mw_com_config.json"], + features = COMPILER_WARNING_FEATURES + [ + "aborts_upon_exception", + ], + visibility = ["//score/mw/com/test/fields:__pkg__"], + deps = [ + "//score/mw/com", + "//score/mw/com/test/common_test_resources:sctf_test_runner", + "//score/mw/com/test/fields/set_and_notifier/fields_test_resources:field_consumer", + "@score_baselibs//score/mw/log", + ], +) + +pkg_application( + name = "main_service-pkg", + app_name = "MainServiceApp", + bin = [":main_service"], + etc = [ + "config/mw_com_config.json", + "config/logging.json", + ], + visibility = [ + "//platform/aas/test/mw/com:__pkg__", + "//score/mw/com/test/fields/set_and_notifier:__subpackages__", + ], +) + +pkg_application( + name = "main_client-pkg", + app_name = "MainClientApp", + bin = [":main_client"], + etc = [ + "config/mw_com_config.json", + "config/logging.json", + ], + visibility = [ + "//platform/aas/test/mw/com:__pkg__", + "//score/mw/com/test/fields/set_and_notifier:__subpackages__", + ], +) + +test_suite( + name = "component_tests", + tests = [ + "//score/mw/com/test/fields/set_and_notifier/integration_test:test_field_set_and_notifier", + ], + visibility = ["//score/mw/com/test/fields:__pkg__"], +) diff --git a/score/mw/com/test/fields/set_and_notifier/config/logging.json b/score/mw/com/test/fields/set_and_notifier/config/logging.json new file mode 100644 index 000000000..de20e5520 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/config/logging.json @@ -0,0 +1,7 @@ +{ + "appId": "FRH", + "appDesc": "field_initial_value", + "logLevel": "kDebug", + "logLevelThresholdConsole": "kDebug", + "logMode": "kRemote|kConsole" +} diff --git a/score/mw/com/test/fields/set_and_notifier/config/mw_com_config.json b/score/mw/com/test/fields/set_and_notifier/config/mw_com_config.json new file mode 100644 index 000000000..60df3e6a9 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/config/mw_com_config.json @@ -0,0 +1,48 @@ +{ + "serviceTypes": [ + { + "serviceTypeName": "/score/mw/com/test/fields/set_and_notifier", + "version": { + "major": 1, + "minor": 0 + }, + "bindings": [ + { + "binding": "SHM", + "serviceId": 3428, + "fields": [ + { + "fieldName": "test_field", + "fieldId": 1, + "Set": true + } + ] + } + ] + } + ], + "serviceInstances": [ + { + "instanceSpecifier": "test/fields/set_and_notifier", + "serviceTypeName": "/score/mw/com/test/fields/set_and_notifier", + "version": { + "major": 1, + "minor": 0 + }, + "instances": [ + { + "instanceId": 1024, + "asil-level": "QM", + "binding": "SHM", + "fields": [ + { + "fieldName": "test_field", + "maxSubscribers": 1, + "numberOfSampleSlots": 1 + } + ] + } + ] + } + ] +} diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/BUILD b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/BUILD new file mode 100644 index 000000000..f0d4d4ffc --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/BUILD @@ -0,0 +1,56 @@ +# ******************************************************************************* +# 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_library") +load("@score_baselibs//score/language/safecpp:toolchain_features.bzl", "COMPILER_WARNING_FEATURES") + +cc_library( + name = "test_datatype", + srcs = ["test_datatype.cpp"], + hdrs = ["test_datatype.h"], + features = COMPILER_WARNING_FEATURES, + visibility = [ + "//score/mw/com/test/fields/set_and_notifier:__subpackages__", + ], + deps = [ + "//score/mw/com", + ], +) + +cc_library( + name = "field_consumer", + srcs = ["field_consumer.cpp"], + hdrs = ["field_consumer.h"], + features = COMPILER_WARNING_FEATURES, + visibility = [ + "//score/mw/com/test/fields/set_and_notifier:__subpackages__", + ], + deps = [ + ":test_datatype", + "//score/mw/com", + ], +) + +cc_library( + name = "field_provider", + srcs = ["field_provider.cpp"], + hdrs = ["field_provider.h"], + features = COMPILER_WARNING_FEATURES, + visibility = [ + "//score/mw/com/test/fields/set_and_notifier:__subpackages__", + ], + deps = [ + ":test_datatype", + "//score/mw/com", + ], +) diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp new file mode 100644 index 000000000..1cee8398a --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp @@ -0,0 +1,300 @@ +/******************************************************************************* + * 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/fields/set_and_notifier/fields_test_resources/field_consumer.h" + +#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h" +#include "score/mw/com/types.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace score::mw::com::test +{ +namespace +{ + +constexpr auto kMaxNumSamples{1U}; + +template +bool WaitForSubscription(FieldType& field, std::size_t retries, const std::chrono::milliseconds retry_backoff_time) +{ + while (field.GetSubscriptionState() != score::mw::com::impl::SubscriptionState::kSubscribed) + { + std::this_thread::sleep_for(retry_backoff_time); + if (retries == 0) + { + return false; + } + --retries; + } + return true; +} + +template +bool PollForValue(FieldType& field, + const std::int32_t expected_value, + std::size_t retries, + const std::chrono::milliseconds retry_backoff_time) +{ + while (retries > 0) + { + score::cpp::optional received_value; + const auto samples_result = field.GetNewSamples( + [&received_value](const auto& sample_ptr) noexcept { + received_value = *sample_ptr; + }, + kMaxNumSamples); + + if (samples_result.has_value() && received_value.has_value() && received_value.value() == expected_value) + { + return true; + } + + std::this_thread::sleep_for(retry_backoff_time); + --retries; + } + + return false; +} + +template +bool SetWithRetries(FieldType& field, + std::int32_t& requested_value, + std::int32_t& accepted_value, + std::size_t retries, + const std::chrono::milliseconds retry_backoff_time, + std::string& last_error) +{ + while (true) + { + const auto set_result = field.Set(requested_value); + if (set_result.has_value()) + { + accepted_value = *(set_result.value()); + return true; + } + + std::ostringstream error_stream; + error_stream << set_result.error(); + last_error = error_stream.str(); + + if (retries == 0) + { + return false; + } + + --retries; + std::this_thread::sleep_for(retry_backoff_time); + } +} + +int run_notifier_client(const std::size_t num_retries, const std::chrono::milliseconds retry_backoff_time) +{ + auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); + if (!instance_specifier_result.has_value()) + { + std::cerr << "Unable to create instance specifier, terminating\n"; + return -7; + } + auto instance_specifier = std::move(instance_specifier_result).value(); + + std::promise> service_discovery_promise{}; + auto service_discovery_future = service_discovery_promise.get_future(); + auto handles_result = InitialOnlyProxy::StartFindService( + [moved_service_discovery_promise = std::move(service_discovery_promise)](auto handles, auto handle) mutable { + moved_service_discovery_promise.set_value(handles); + score::cpp::ignore = InitialOnlyProxy::StopFindService(handle); + }, + std::move(instance_specifier)); + if (!handles_result.has_value()) + { + std::cerr << "Unable to get handles, terminating\n"; + return -1; + } + + auto handles = service_discovery_future.get(); + if (handles.empty()) + { + std::cerr << "Unable to find lola service, terminating\n"; + return -2; + } + + auto proxy_result = InitialOnlyProxy::Create(handles[0]); + if (!proxy_result.has_value()) + { + std::cerr << "Unable to create InitialOnlyProxy: " << proxy_result.error() << "\n"; + return -3; + } + + auto& proxy = proxy_result.value(); + std::ignore = proxy.test_field.Subscribe(kMaxNumSamples); + if (!WaitForSubscription(proxy.test_field, num_retries, retry_backoff_time)) + { + std::cerr << "Subscription failed in notifier scenario.\n"; + return -4; + } + + const bool initial_value_received = PollForValue(proxy.test_field, kInitialValue, num_retries, retry_backoff_time); + proxy.test_field.Unsubscribe(); + + if (!initial_value_received) + { + std::cerr << "Did not receive expected initial value " << kInitialValue << " in notifier scenario.\n"; + return -5; + } + + return 0; +} + +int run_set_client(const std::size_t num_retries, const std::chrono::milliseconds retry_backoff_time) +{ + auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); + if (!instance_specifier_result.has_value()) + { + std::cerr << "Unable to create instance specifier, terminating\n"; + return -27; + } + auto instance_specifier = std::move(instance_specifier_result).value(); + + std::promise> service_discovery_promise{}; + auto service_discovery_future = service_discovery_promise.get_future(); + auto handles_result = SetEnabledProxy::StartFindService( + [moved_service_discovery_promise = std::move(service_discovery_promise)](auto handles, auto handle) mutable { + moved_service_discovery_promise.set_value(handles); + score::cpp::ignore = SetEnabledProxy::StopFindService(handle); + }, + std::move(instance_specifier)); + if (!handles_result.has_value()) + { + std::cerr << "Unable to get handles, terminating\n"; + return -21; + } + + auto handles = service_discovery_future.get(); + if (handles.empty()) + { + std::cerr << "Unable to find lola service, terminating\n"; + return -22; + } + + auto proxy_result = SetEnabledProxy::Create(handles[0]); + if (!proxy_result.has_value()) + { + std::cerr << "Unable to create SetEnabledProxy: " << proxy_result.error() << "\n"; + return -13; + } + + auto& proxy = proxy_result.value(); + std::ignore = proxy.test_field.Subscribe(kMaxNumSamples); + if (!WaitForSubscription(proxy.test_field, num_retries, retry_backoff_time)) + { + std::cerr << "Subscription failed in set scenario.\n"; + return -14; + } + + const bool initial_value_received = PollForValue(proxy.test_field, kInitialValue, num_retries, retry_backoff_time); + if (!initial_value_received) + { + std::cerr << "Did not receive initial value " << kInitialValue << " in set scenario.\n"; + return -18; + } + + std::int32_t valid_requested_value = kSetValidValue; + std::int32_t valid_accepted_value{0}; + std::string valid_set_error; + if (!SetWithRetries(proxy.test_field, + valid_requested_value, + valid_accepted_value, + num_retries, + retry_backoff_time, + valid_set_error)) + { + std::cerr << "Valid Set call failed: " << valid_set_error << "\n"; + return -19; + } + + if (valid_accepted_value != kSetValidValue) + { + std::cerr << "Valid Set accepted value mismatch. Expected " << kSetValidValue << " but got " + << valid_accepted_value << "\n"; + return -20; + } + + const bool valid_value_received = PollForValue(proxy.test_field, kSetValidValue, num_retries, retry_backoff_time); + if (!valid_value_received) + { + std::cerr << "Did not receive valid set value " << kSetValidValue << " after Set call.\n"; + return -21; + } + + std::int32_t requested_value = kSetRequestValue; + std::int32_t accepted_value{0}; + std::string invalid_set_error; + if (!SetWithRetries( + proxy.test_field, requested_value, accepted_value, num_retries, retry_backoff_time, invalid_set_error)) + { + std::cerr << "Set call failed: " << invalid_set_error << "\n"; + return -22; + } + + if (accepted_value != kSetAcceptedValue) + { + std::cerr << "Set accepted value mismatch. Expected " << kSetAcceptedValue << " but got " << accepted_value + << "\n"; + return -23; + } + + const bool clamped_value_received = + PollForValue(proxy.test_field, kSetAcceptedValue, num_retries, retry_backoff_time); + proxy.test_field.Unsubscribe(); + + if (!clamped_value_received) + { + std::cerr << "Did not receive clamped value " << kSetAcceptedValue << " after Set call.\n"; + return -24; + } + + return 0; +} + +} // namespace + +int run_client(const std::size_t num_retries, + const std::chrono::milliseconds retry_backoff_time, + const std::string& mode) +{ + if (mode == "notifier") + { + return run_notifier_client(num_retries, retry_backoff_time); + } + if (mode == "set") + { + return run_set_client(num_retries, retry_backoff_time); + } + + // TODO: Add "get" mode client scenario coverage once getter-enabled field variant is introduced. + std::cerr << "Unsupported mode passed to client: " << mode << "\n"; + return -1; +} + +} // namespace score::mw::com::test diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.h new file mode 100644 index 000000000..c7455e770 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.h @@ -0,0 +1,28 @@ +/******************************************************************************* + * 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_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_FIELD_CONSUMER_H +#define SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_FIELD_CONSUMER_H + +#include +#include +#include + +namespace score::mw::com::test +{ + +int run_client(std::size_t num_retries, std::chrono::milliseconds retry_backoff_time, const std::string& mode); + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_FIELD_CONSUMER_H diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp new file mode 100644 index 000000000..c945f8e63 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp @@ -0,0 +1,149 @@ +/******************************************************************************* + * 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/fields/set_and_notifier/fields_test_resources/field_provider.h" + +#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h" + +#include +#include +#include +#include +#include + +namespace score::mw::com::test +{ +namespace +{ + +int run_notifier_service(const std::chrono::milliseconds& cycle_time, const score::cpp::stop_token& stop_token) +{ + auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); + if (!instance_specifier_result.has_value()) + { + std::cerr << "Unable to create instance specifier, terminating\n"; + return -3; + } + auto instance_specifier = std::move(instance_specifier_result).value(); + + auto service_result = InitialOnlySkeleton::Create(std::move(instance_specifier)); + if (!service_result.has_value()) + { + std::cerr << "Unable to construct InitialOnlySkeleton: " << service_result.error() << ", bailing!\n"; + return -4; + } + + InitialOnlySkeleton& service{service_result.value()}; + + const auto update_result = service.test_field.Update(kInitialValue); + if (!update_result.has_value()) + { + std::cerr << "Unable to update initial field value: " << update_result.error() << ", bailing!\n"; + return -6; + } + const auto offer_result = service.OfferService(); + if (!offer_result.has_value()) + { + std::cerr << "Unable to offer InitialOnlySkeleton: " << offer_result.error() << ", bailing!\n"; + return -5; + } + + while (!stop_token.stop_requested()) + { + std::this_thread::sleep_for(cycle_time); + } + + service.StopOfferService(); + + return 0; +} + +int run_set_service(const std::chrono::milliseconds& cycle_time, const score::cpp::stop_token& stop_token) +{ + auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); + if (!instance_specifier_result.has_value()) + { + std::cerr << "Unable to create instance specifier, terminating\n"; + return -13; + } + auto instance_specifier = std::move(instance_specifier_result).value(); + + auto service_result = SetEnabledSkeleton::Create(std::move(instance_specifier)); + if (!service_result.has_value()) + { + std::cerr << "Unable to construct SetEnabledSkeleton: " << service_result.error() << ", bailing!\n"; + return -14; + } + + SetEnabledSkeleton& service{service_result.value()}; + const auto register_handler_result = service.test_field.RegisterSetHandler([](std::int32_t& value) noexcept { + if (value > kSetAcceptedValue) + { + value = kSetAcceptedValue; + } + if (value < 0) + { + value = 0; + } + }); + if (!register_handler_result.has_value()) + { + std::cerr << "Unable to register set handler: " << register_handler_result.error() << ", bailing!\n"; + return -15; + } + + const auto update_result = service.test_field.Update(kInitialValue); + if (!update_result.has_value()) + { + std::cerr << "Unable to update initial field value: " << update_result.error() << ", bailing!\n"; + return -16; + } + + const auto offer_result = service.OfferService(); + if (!offer_result.has_value()) + { + std::cerr << "Unable to offer SetEnabledSkeleton: " << offer_result.error() << ", bailing!\n"; + return -17; + } + + while (!stop_token.stop_requested()) + { + std::this_thread::sleep_for(cycle_time); + } + + service.StopOfferService(); + + return 0; +} + +} // namespace + +int run_service(const std::chrono::milliseconds& cycle_time, + const score::cpp::stop_token& stop_token, + const std::string& mode) +{ + if (mode == "notifier") + { + return run_notifier_service(cycle_time, stop_token); + } + if (mode == "set") + { + return run_set_service(cycle_time, stop_token); + } + + // TODO: Add "get" mode service scenario coverage once getter-enabled field variant is introduced. + std::cerr << "Unsupported mode passed to service: " << mode << "\n"; + return -1; +} + +} // namespace score::mw::com::test diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.h new file mode 100644 index 000000000..6d6d2386c --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.h @@ -0,0 +1,31 @@ +/******************************************************************************* + * 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_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_FIELD_PROVIDER_H +#define SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_FIELD_PROVIDER_H + +#include + +#include +#include + +namespace score::mw::com::test +{ + +int run_service(const std::chrono::milliseconds& cycle_time, + const score::cpp::stop_token& stop_token, + const std::string& mode); + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_FIELD_PROVIDER_H diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.cpp new file mode 100644 index 000000000..1acbc6aac --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.cpp @@ -0,0 +1,14 @@ +/******************************************************************************* + * 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/fields/set_and_notifier/fields_test_resources/test_datatype.h" diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h new file mode 100644 index 000000000..b938631e4 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h @@ -0,0 +1,59 @@ +/******************************************************************************* + * 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_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_TEST_DATATYPE_H +#define SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_TEST_DATATYPE_H + +#include "score/mw/com/types.h" + +#include + +namespace score::mw::com::test +{ + +constexpr const char* const kInstanceSpecifierString = "test/fields/set_and_notifier"; + +const std::int32_t kInitialValue = 18; +const std::int32_t kSetValidValue = 42; +const std::int32_t kSetRequestValue = 1234; +const std::int32_t kSetAcceptedValue = 100; + +template +class InitialOnlyInterface : public T::Base +{ + public: + using T::Base::Base; + + typename T::template Field test_field{*this, "test_field"}; +}; + +template +class SetEnabledInterface : public T::Base +{ + public: + using T::Base::Base; + + typename T::template Field test_field{*this, "test_field"}; +}; + +using InitialOnlyProxy = score::mw::com::AsProxy; +using InitialOnlySkeleton = score::mw::com::AsSkeleton; + +using SetEnabledProxy = score::mw::com::AsProxy; +using SetEnabledSkeleton = score::mw::com::AsSkeleton; + +// TODO: Add a getter-enabled field interface type for dedicated "get" mode integration scenarios. + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_TEST_DATATYPE_H diff --git a/score/mw/com/test/fields/set_and_notifier/integration_test/BUILD b/score/mw/com/test/fields/set_and_notifier/integration_test/BUILD new file mode 100644 index 000000000..14c2344a3 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/BUILD @@ -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 +# ******************************************************************************* + +load("@rules_pkg//pkg:mappings.bzl", "pkg_filegroup") +load("//quality/integration_testing:integration_testing.bzl", "integration_test") + +pkg_filegroup( + name = "filesystem", + srcs = [ + "//score/mw/com/test/fields/set_and_notifier:main_client-pkg", + "//score/mw/com/test/fields/set_and_notifier:main_service-pkg", + ], +) + +integration_test( + name = "test_field_set_and_notifier", + timeout = "moderate", + srcs = [ + "test_field_set_and_notifier.py", + ], + filesystem = ":filesystem", +) diff --git a/score/mw/com/test/fields/set_and_notifier/integration_test/test_field_set_and_notifier.py b/score/mw/com/test/fields/set_and_notifier/integration_test/test_field_set_and_notifier.py new file mode 100644 index 000000000..aeb530512 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/test_field_set_and_notifier.py @@ -0,0 +1,39 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + + +def client(target, mode, **kwargs): + args = ["--num-retries", "20", "--backoff-time", "50", "--mode", mode] + return target.wrap_exec("bin/main_client", args, cwd="/opt/MainClientApp", wait_on_exit=True, **kwargs) + + +def service(target, mode, **kwargs): + args = ["--cycle-time", "250", "--mode", mode] + return target.wrap_exec("bin/main_service", args, cwd="/opt/MainServiceApp", **kwargs) + + +def test_field_notifier_initial_value(target): + """Test field initial value exchange between service and client.""" + with service(target, "notifier"): + with client(target, "notifier"): + pass + + +def test_field_set_value(target): + """Test field set exchange and accepted value propagation between service and client.""" + with service(target, "set"): + with client(target, "set"): + pass + + +# TODO: Add a dedicated get scenario test once getter-enabled field mode is available. diff --git a/score/mw/com/test/fields/set_and_notifier/main_client.cpp b/score/mw/com/test/fields/set_and_notifier/main_client.cpp new file mode 100644 index 000000000..0adb5a6d9 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/main_client.cpp @@ -0,0 +1,30 @@ +/******************************************************************************* + * 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/common_test_resources/sctf_test_runner.h" +#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.h" + +#include + +int main(int argc, const char** argv) +{ + using Parameters = score::mw::com::test::SctfTestRunner::RunParameters::Parameters; + + const std::vector allowed_parameters{ + Parameters::NUM_RETRIES, Parameters::RETRY_BACKOFF_TIME, Parameters::MODE}; + score::mw::com::test::SctfTestRunner test_runner(argc, argv, allowed_parameters); + const auto& run_parameters = test_runner.GetRunParameters(); + + return score::mw::com::test::run_client( + run_parameters.GetNumRetries(), run_parameters.GetRetryBackoffTime(), run_parameters.GetMode()); +} diff --git a/score/mw/com/test/fields/set_and_notifier/main_service.cpp b/score/mw/com/test/fields/set_and_notifier/main_service.cpp new file mode 100644 index 000000000..c912b689d --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/main_service.cpp @@ -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 + *******************************************************************************/ + +#include "score/mw/com/test/common_test_resources/sctf_test_runner.h" +#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.h" + +#include + +int main(int argc, const char** argv) +{ + using Parameters = score::mw::com::test::SctfTestRunner::RunParameters::Parameters; + + const std::vector allowed_parameters{Parameters::CYCLE_TIME, Parameters::MODE}; + score::mw::com::test::SctfTestRunner test_runner(argc, argv, allowed_parameters); + const auto& run_parameters = test_runner.GetRunParameters(); + + return score::mw::com::test::run_service( + run_parameters.GetCycleTime(), test_runner.GetStopToken(), run_parameters.GetMode()); +} From 3abcb6f9f3997e46ea2ca3eb6b083bc411a20783 Mon Sep 17 00:00:00 2001 From: sahithinukala Date: Tue, 2 Jun 2026 14:40:21 +0530 Subject: [PATCH 05/13] mw/com: Address review comments for fields integration tests --- score/mw/com/test/fields/BUILD | 9 - .../com/test/fields/field_initial_value/BUILD | 13 +- .../fields/field_initial_value/client.cpp | 12 ++ .../test_field_initial_value.py | 2 +- .../fields/field_initial_value/service.cpp | 53 +++--- .../mw/com/test/fields/set_and_notifier/BUILD | 35 ++-- .../set_and_notifier/config/logging.json | 4 +- .../test/fields/set_and_notifier/consumer.cpp | 72 ++++++++ .../fields_test_resources/BUILD | 13 +- .../fields_test_resources/field_consumer.cpp | 165 ++++++++---------- .../fields_test_resources/field_consumer.h | 2 +- .../fields_test_resources/field_provider.cpp | 93 +++++----- .../fields_test_resources/field_provider.h | 5 +- .../initial_only_interface.h | 33 ++++ .../set_enabled_interface.h | 33 ++++ .../fields_test_resources/test_constants.h | 31 ++++ .../fields_test_resources/test_datatype.h | 29 +-- .../set_and_notifier/integration_test/BUILD | 24 ++- .../integration_test/test_fixture.py | 23 +++ .../integration_test/test_get.py | 18 ++ .../integration_test/test_get_and_notifier.py | 19 ++ .../integration_test/test_notifier.py | 21 +++ .../integration_test/test_set_and_get.py | 20 +++ ...d_notifier.py => test_set_and_notifier.py} | 23 +-- .../test_set_get_and_notifier.py | 20 +++ .../fields/set_and_notifier/main_client.cpp | 30 ---- .../fields/set_and_notifier/main_service.cpp | 29 --- .../test/fields/set_and_notifier/provider.cpp | 64 +++++++ .../test/methods/methods_test_resources/BUILD | 1 + 29 files changed, 572 insertions(+), 324 deletions(-) create mode 100644 score/mw/com/test/fields/set_and_notifier/consumer.cpp create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_interface.h create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_interface.h create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.h create mode 100644 score/mw/com/test/fields/set_and_notifier/integration_test/test_fixture.py create mode 100644 score/mw/com/test/fields/set_and_notifier/integration_test/test_get.py create mode 100644 score/mw/com/test/fields/set_and_notifier/integration_test/test_get_and_notifier.py create mode 100644 score/mw/com/test/fields/set_and_notifier/integration_test/test_notifier.py create mode 100644 score/mw/com/test/fields/set_and_notifier/integration_test/test_set_and_get.py rename score/mw/com/test/fields/set_and_notifier/integration_test/{test_field_set_and_notifier.py => test_set_and_notifier.py} (51%) create mode 100644 score/mw/com/test/fields/set_and_notifier/integration_test/test_set_get_and_notifier.py delete mode 100644 score/mw/com/test/fields/set_and_notifier/main_client.cpp delete mode 100644 score/mw/com/test/fields/set_and_notifier/main_service.cpp create mode 100644 score/mw/com/test/fields/set_and_notifier/provider.cpp diff --git a/score/mw/com/test/fields/BUILD b/score/mw/com/test/fields/BUILD index 7bf308537..ca5de742e 100644 --- a/score/mw/com/test/fields/BUILD +++ b/score/mw/com/test/fields/BUILD @@ -10,12 +10,3 @@ # # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* - -test_suite( - name = "component_tests", - tests = [ - "//score/mw/com/test/fields/field_initial_value:component_tests", - "//score/mw/com/test/fields/set_and_notifier:component_tests", - ], - visibility = ["//score/mw/com/test:__pkg__"], -) diff --git a/score/mw/com/test/fields/field_initial_value/BUILD b/score/mw/com/test/fields/field_initial_value/BUILD index c08fa4b75..d32a1198b 100644 --- a/score/mw/com/test/fields/field_initial_value/BUILD +++ b/score/mw/com/test/fields/field_initial_value/BUILD @@ -44,7 +44,9 @@ cc_binary( deps = [ ":test_datatype", "//score/mw/com", - "//score/mw/com/test/common_test_resources:sctf_test_runner", + "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:stop_token_sig_term_handler", + "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", "@score_baselibs//score/mw/log", ], ) @@ -61,6 +63,7 @@ cc_binary( ":test_datatype", "//score/mw/com", "//score/mw/com/test/common_test_resources:sctf_test_runner", + "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", "@score_baselibs//score/mw/log", ], ) @@ -92,11 +95,3 @@ pkg_application( "//score/mw/com/test/fields/field_initial_value:__subpackages__", ], ) - -test_suite( - name = "component_tests", - tests = [ - "//score/mw/com/test/fields/field_initial_value/integration_test:test_field_initial_value", - ], - visibility = ["//score/mw/com/test/fields:__pkg__"], -) diff --git a/score/mw/com/test/fields/field_initial_value/client.cpp b/score/mw/com/test/fields/field_initial_value/client.cpp index bdf0b1b11..9a7a2862b 100644 --- a/score/mw/com/test/fields/field_initial_value/client.cpp +++ b/score/mw/com/test/fields/field_initial_value/client.cpp @@ -13,6 +13,7 @@ #include "score/mw/com/test/common_test_resources/sctf_test_runner.h" #include "score/mw/com/test/fields/field_initial_value/test_datatype.h" +#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include "score/mw/com/types.h" #include @@ -21,6 +22,7 @@ #include #include #include +#include #include namespace score::mw::com::test @@ -31,10 +33,19 @@ namespace constexpr auto kMaxNumSamples{1U}; +const std::string kInterprocessNotificationShmPath{"/field_initial_value_interprocess_notification"}; + int run_client(const std::size_t num_retries, const std::chrono::milliseconds retry_backoff_time) { using score::mw::com::test::TestDataProxy; + auto process_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); + if (!process_synchronizer_result.has_value()) + { + std::cerr << "Unable to create ProcessSynchronizer, terminating\n"; + return -8; + } + auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); if (!instance_specifier_result.has_value()) { @@ -106,6 +117,7 @@ int run_client(const std::size_t num_retries, const std::chrono::milliseconds re return -6; } + process_synchronizer_result->Notify(); return 0; } diff --git a/score/mw/com/test/fields/field_initial_value/integration_test/test_field_initial_value.py b/score/mw/com/test/fields/field_initial_value/integration_test/test_field_initial_value.py index e0dd9c991..1bf5b0f00 100644 --- a/score/mw/com/test/fields/field_initial_value/integration_test/test_field_initial_value.py +++ b/score/mw/com/test/fields/field_initial_value/integration_test/test_field_initial_value.py @@ -18,7 +18,7 @@ def client(target, **kwargs): def service(target, **kwargs): - args = ["--cycle-time", "250"] + args = [] return target.wrap_exec("bin/service", args, cwd="/opt/ServiceApp", **kwargs) diff --git a/score/mw/com/test/fields/field_initial_value/service.cpp b/score/mw/com/test/fields/field_initial_value/service.cpp index c77c39b6e..56d613853 100644 --- a/score/mw/com/test/fields/field_initial_value/service.cpp +++ b/score/mw/com/test/fields/field_initial_value/service.cpp @@ -11,14 +11,17 @@ * SPDX-License-Identifier: Apache-2.0 *******************************************************************************/ -#include "score/mw/com/test/common_test_resources/sctf_test_runner.h" +#include "score/mw/com/runtime.h" +#include "score/mw/com/test/common_test_resources/fail_test.h" +#include "score/mw/com/test/common_test_resources/stop_token_sig_term_handler.h" #include "score/mw/com/test/fields/field_initial_value/test_datatype.h" +#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include -#include +#include #include -#include +#include #include namespace score::mw::com::test @@ -27,21 +30,27 @@ namespace score::mw::com::test namespace { -int run_service(const std::chrono::milliseconds& cycle_time, const score::cpp::stop_token& stop_token) +const std::string kInterprocessNotificationShmPath{"/field_initial_value_interprocess_notification"}; + +void run_service(const score::cpp::stop_token& stop_token) { + auto process_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); + if (!process_synchronizer_result.has_value()) + { + FailTest("Service: Unable to create ProcessSynchronizer"); + } + auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); if (!instance_specifier_result.has_value()) { - std::cerr << "Unable to create instance specifier, terminating\n"; - return -3; + FailTest("Service: Unable to create instance specifier"); } auto instance_specifier = std::move(instance_specifier_result).value(); auto service_result = TestDataSkeleton::Create(std::move(instance_specifier)); if (!service_result.has_value()) { - std::cerr << "Unable to construct TestDataSkeleton: " << service_result.error() << ", bailing!\n"; - return -4; + FailTest("Service: Unable to construct TestDataSkeleton: ", service_result.error()); } TestDataSkeleton& lola_service{service_result.value()}; @@ -49,24 +58,20 @@ int run_service(const std::chrono::milliseconds& cycle_time, const score::cpp::s const auto update_result = lola_service.test_field.Update(kTestValue); if (!update_result.has_value()) { - std::cerr << "Unable to update test field: " << update_result.error() << ", bailing!\n"; - return -6; + FailTest("Service: Unable to update test field: ", update_result.error()); } const auto offer_result = lola_service.OfferService(); if (!offer_result.has_value()) { - std::cerr << "Unable to offer service for TestDataSkeleton: " << offer_result.error() << ", bailing!\n"; - return -5; + FailTest("Service: Unable to offer service for TestDataSkeleton: ", offer_result.error()); } - while (!stop_token.stop_requested()) + if (!process_synchronizer_result->WaitWithAbort(stop_token)) { - std::this_thread::sleep_for(cycle_time); + FailTest("Service: WaitWithAbort was stopped by stop_token instead of notification"); } lola_service.StopOfferService(); - - return 0; } } // namespace @@ -75,13 +80,15 @@ int run_service(const std::chrono::milliseconds& cycle_time, const score::cpp::s int main(int argc, const char** argv) { - using Parameters = score::mw::com::test::SctfTestRunner::RunParameters::Parameters; + score::mw::com::runtime::InitializeRuntime(argc, argv); - const std::vector allowed_parameters{Parameters::CYCLE_TIME}; - score::mw::com::test::SctfTestRunner test_runner(argc, argv, allowed_parameters); - const auto& run_parameters = test_runner.GetRunParameters(); - const auto cycle_time = run_parameters.GetCycleTime(); - const auto stop_token = test_runner.GetStopToken(); + 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\n"; + } - return score::mw::com::test::run_service(cycle_time, stop_token); + score::mw::com::test::run_service(stop_source.get_token()); + return EXIT_SUCCESS; } diff --git a/score/mw/com/test/fields/set_and_notifier/BUILD b/score/mw/com/test/fields/set_and_notifier/BUILD index 6933ede4d..6a0b0840b 100644 --- a/score/mw/com/test/fields/set_and_notifier/BUILD +++ b/score/mw/com/test/fields/set_and_notifier/BUILD @@ -24,8 +24,8 @@ validate_json_schema_test( ) cc_binary( - name = "main_service", - srcs = ["main_service.cpp"], + name = "provider", + srcs = ["provider.cpp"], data = ["config/mw_com_config.json"], features = COMPILER_WARNING_FEATURES + [ "aborts_upon_exception", @@ -33,15 +33,17 @@ cc_binary( visibility = ["//score/mw/com/test/fields:__pkg__"], deps = [ "//score/mw/com", - "//score/mw/com/test/common_test_resources:sctf_test_runner", + "//score/mw/com/test/common_test_resources:command_line_parser", + "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:stop_token_sig_term_handler", "//score/mw/com/test/fields/set_and_notifier/fields_test_resources:field_provider", "@score_baselibs//score/mw/log", ], ) cc_binary( - name = "main_client", - srcs = ["main_client.cpp"], + name = "consumer", + srcs = ["consumer.cpp"], data = ["config/mw_com_config.json"], features = COMPILER_WARNING_FEATURES + [ "aborts_upon_exception", @@ -49,16 +51,17 @@ cc_binary( visibility = ["//score/mw/com/test/fields:__pkg__"], deps = [ "//score/mw/com", - "//score/mw/com/test/common_test_resources:sctf_test_runner", + "//score/mw/com/test/common_test_resources:command_line_parser", + "//score/mw/com/test/common_test_resources:fail_test", "//score/mw/com/test/fields/set_and_notifier/fields_test_resources:field_consumer", "@score_baselibs//score/mw/log", ], ) pkg_application( - name = "main_service-pkg", - app_name = "MainServiceApp", - bin = [":main_service"], + name = "provider-pkg", + app_name = "MainProviderApp", + bin = [":provider"], etc = [ "config/mw_com_config.json", "config/logging.json", @@ -70,9 +73,9 @@ pkg_application( ) pkg_application( - name = "main_client-pkg", - app_name = "MainClientApp", - bin = [":main_client"], + name = "consumer-pkg", + app_name = "MainConsumerApp", + bin = [":consumer"], etc = [ "config/mw_com_config.json", "config/logging.json", @@ -82,11 +85,3 @@ pkg_application( "//score/mw/com/test/fields/set_and_notifier:__subpackages__", ], ) - -test_suite( - name = "component_tests", - tests = [ - "//score/mw/com/test/fields/set_and_notifier/integration_test:test_field_set_and_notifier", - ], - visibility = ["//score/mw/com/test/fields:__pkg__"], -) diff --git a/score/mw/com/test/fields/set_and_notifier/config/logging.json b/score/mw/com/test/fields/set_and_notifier/config/logging.json index de20e5520..a49f8cded 100644 --- a/score/mw/com/test/fields/set_and_notifier/config/logging.json +++ b/score/mw/com/test/fields/set_and_notifier/config/logging.json @@ -1,6 +1,6 @@ { - "appId": "FRH", - "appDesc": "field_initial_value", + "appId": "FSAN", + "appDesc": "field_set_and_notifier", "logLevel": "kDebug", "logLevelThresholdConsole": "kDebug", "logMode": "kRemote|kConsole" diff --git a/score/mw/com/test/fields/set_and_notifier/consumer.cpp b/score/mw/com/test/fields/set_and_notifier/consumer.cpp new file mode 100644 index 000000000..4db24f4db --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/consumer.cpp @@ -0,0 +1,72 @@ +/******************************************************************************* + * 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/command_line_parser.h" +#include "score/mw/com/test/common_test_resources/fail_test.h" +#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.h" + +#include +#include +#include +#include +#include +#include + +int main(int argc, const char** argv) +{ + constexpr auto kNumRetriesArg = "num-retries"; + constexpr auto kBackoffTimeArg = "backoff-time"; + constexpr auto kModeArg = "mode"; + constexpr auto kServiceInstanceManifestArg = "service-instance-manifest"; + + const std::vector> parameter_description_pairs{ + {kNumRetriesArg, "Number of retries"}, + {kBackoffTimeArg, "Retry backoff time in milliseconds"}, + {kModeArg, "Consumer mode: notifier or set"}, + {kServiceInstanceManifestArg, "Path to the service instance manifest"}, + }; + + const auto args = score::mw::com::test::ParseCommandLineArguments(argc, argv, parameter_description_pairs); + + const auto num_retries_result = score::mw::com::test::GetValueIfProvided(args, kNumRetriesArg); + if (!num_retries_result.has_value()) + { + score::mw::com::test::FailTest("Consumer: missing or invalid --", kNumRetriesArg, " argument"); + } + + const auto backoff_time_result = score::mw::com::test::GetValueIfProvided(args, kBackoffTimeArg); + if (!backoff_time_result.has_value()) + { + score::mw::com::test::FailTest("Consumer: missing or invalid --", kBackoffTimeArg, " argument"); + } + + const auto mode_result = score::mw::com::test::GetValueIfProvided(args, kModeArg); + if (!mode_result.has_value()) + { + score::mw::com::test::FailTest("Consumer: missing or invalid --", kModeArg, " argument"); + } + + const auto manifest_result = + score::mw::com::test::GetValueIfProvided(args, kServiceInstanceManifestArg); + if (!manifest_result.has_value()) + { + score::mw::com::test::FailTest("Consumer: missing or invalid --", kServiceInstanceManifestArg, " argument"); + } + + score::mw::com::runtime::InitializeRuntime(score::mw::com::runtime::RuntimeConfiguration{manifest_result.value()}); + + score::mw::com::test::run_consumer( + num_retries_result.value(), std::chrono::milliseconds{backoff_time_result.value()}, mode_result.value()); + return EXIT_SUCCESS; +} diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/BUILD b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/BUILD index f0d4d4ffc..36de65c78 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/BUILD +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/BUILD @@ -17,7 +17,12 @@ load("@score_baselibs//score/language/safecpp:toolchain_features.bzl", "COMPILER cc_library( name = "test_datatype", srcs = ["test_datatype.cpp"], - hdrs = ["test_datatype.h"], + hdrs = [ + "initial_only_interface.h", + "set_enabled_interface.h", + "test_constants.h", + "test_datatype.h", + ], features = COMPILER_WARNING_FEATURES, visibility = [ "//score/mw/com/test/fields/set_and_notifier:__subpackages__", @@ -38,6 +43,9 @@ cc_library( deps = [ ":test_datatype", "//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", ], ) @@ -52,5 +60,8 @@ cc_library( deps = [ ":test_datatype", "//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", ], ) diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp index 1cee8398a..378eae826 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp @@ -13,20 +13,22 @@ #include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_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/fields/set_and_notifier/fields_test_resources/test_constants.h" #include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h" +#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include "score/mw/com/types.h" #include #include #include -#include #include #include #include #include #include -#include namespace score::mw::com::test { @@ -34,6 +36,14 @@ namespace { constexpr auto kMaxNumSamples{1U}; +const std::string kInterprocessNotificationShmPath{"/fields_set_and_notifier_interprocess_notification"}; + +template +void NotifyAndFail(ProcessSynchronizer& process_synchronizer, Args&&... args) +{ + process_synchronizer.Notify(); + FailTest(std::forward(args)...); +} template bool WaitForSubscription(FieldType& field, std::size_t retries, const std::chrono::milliseconds retry_backoff_time) @@ -108,50 +118,33 @@ bool SetWithRetries(FieldType& field, } } -int run_notifier_client(const std::size_t num_retries, const std::chrono::milliseconds retry_backoff_time) +void run_notifier_consumer(const std::size_t num_retries, const std::chrono::milliseconds retry_backoff_time) { - auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); - if (!instance_specifier_result.has_value()) + auto process_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); + if (!process_synchronizer_result.has_value()) { - std::cerr << "Unable to create instance specifier, terminating\n"; - return -7; + FailTest("Consumer: Could not create ProcessSynchronizer"); } - auto instance_specifier = std::move(instance_specifier_result).value(); + auto& process_synchronizer = process_synchronizer_result.value(); - std::promise> service_discovery_promise{}; - auto service_discovery_future = service_discovery_promise.get_future(); - auto handles_result = InitialOnlyProxy::StartFindService( - [moved_service_discovery_promise = std::move(service_discovery_promise)](auto handles, auto handle) mutable { - moved_service_discovery_promise.set_value(handles); - score::cpp::ignore = InitialOnlyProxy::StopFindService(handle); - }, - std::move(instance_specifier)); - if (!handles_result.has_value()) - { - std::cerr << "Unable to get handles, terminating\n"; - return -1; - } - - auto handles = service_discovery_future.get(); - if (handles.empty()) + auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); + if (!instance_specifier_result.has_value()) { - std::cerr << "Unable to find lola service, terminating\n"; - return -2; + NotifyAndFail(process_synchronizer, "Consumer: Unable to create instance specifier"); } + auto instance_specifier = std::move(instance_specifier_result).value(); - auto proxy_result = InitialOnlyProxy::Create(handles[0]); - if (!proxy_result.has_value()) + ProxyContainer proxy_container{}; + if (!proxy_container.CreateProxy(std::move(instance_specifier))) { - std::cerr << "Unable to create InitialOnlyProxy: " << proxy_result.error() << "\n"; - return -3; + NotifyAndFail(process_synchronizer, "Consumer: Unable to create InitialOnlyProxy"); } - auto& proxy = proxy_result.value(); + auto& proxy = proxy_container.GetProxy(); std::ignore = proxy.test_field.Subscribe(kMaxNumSamples); if (!WaitForSubscription(proxy.test_field, num_retries, retry_backoff_time)) { - std::cerr << "Subscription failed in notifier scenario.\n"; - return -4; + NotifyAndFail(process_synchronizer, "Consumer: Subscription failed in notifier scenario"); } const bool initial_value_received = PollForValue(proxy.test_field, kInitialValue, num_retries, retry_backoff_time); @@ -159,64 +152,49 @@ int run_notifier_client(const std::size_t num_retries, const std::chrono::millis if (!initial_value_received) { - std::cerr << "Did not receive expected initial value " << kInitialValue << " in notifier scenario.\n"; - return -5; + NotifyAndFail(process_synchronizer, + "Consumer: Did not receive expected initial value ", + kInitialValue, + " in notifier scenario"); } - return 0; + process_synchronizer.Notify(); } -int run_set_client(const std::size_t num_retries, const std::chrono::milliseconds retry_backoff_time) +void run_set_consumer(const std::size_t num_retries, const std::chrono::milliseconds retry_backoff_time) { - auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); - if (!instance_specifier_result.has_value()) - { - std::cerr << "Unable to create instance specifier, terminating\n"; - return -27; - } - auto instance_specifier = std::move(instance_specifier_result).value(); - - std::promise> service_discovery_promise{}; - auto service_discovery_future = service_discovery_promise.get_future(); - auto handles_result = SetEnabledProxy::StartFindService( - [moved_service_discovery_promise = std::move(service_discovery_promise)](auto handles, auto handle) mutable { - moved_service_discovery_promise.set_value(handles); - score::cpp::ignore = SetEnabledProxy::StopFindService(handle); - }, - std::move(instance_specifier)); - if (!handles_result.has_value()) + auto process_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); + if (!process_synchronizer_result.has_value()) { - std::cerr << "Unable to get handles, terminating\n"; - return -21; + FailTest("Consumer: Could not create ProcessSynchronizer"); } + auto& process_synchronizer = process_synchronizer_result.value(); - auto handles = service_discovery_future.get(); - if (handles.empty()) + auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); + if (!instance_specifier_result.has_value()) { - std::cerr << "Unable to find lola service, terminating\n"; - return -22; + NotifyAndFail(process_synchronizer, "Consumer: Unable to create instance specifier"); } + auto instance_specifier = std::move(instance_specifier_result).value(); - auto proxy_result = SetEnabledProxy::Create(handles[0]); - if (!proxy_result.has_value()) + ProxyContainer proxy_container{}; + if (!proxy_container.CreateProxy(std::move(instance_specifier))) { - std::cerr << "Unable to create SetEnabledProxy: " << proxy_result.error() << "\n"; - return -13; + NotifyAndFail(process_synchronizer, "Consumer: Unable to create SetEnabledProxy"); } - auto& proxy = proxy_result.value(); + auto& proxy = proxy_container.GetProxy(); std::ignore = proxy.test_field.Subscribe(kMaxNumSamples); if (!WaitForSubscription(proxy.test_field, num_retries, retry_backoff_time)) { - std::cerr << "Subscription failed in set scenario.\n"; - return -14; + NotifyAndFail(process_synchronizer, "Consumer: Subscription failed in set scenario"); } const bool initial_value_received = PollForValue(proxy.test_field, kInitialValue, num_retries, retry_backoff_time); if (!initial_value_received) { - std::cerr << "Did not receive initial value " << kInitialValue << " in set scenario.\n"; - return -18; + NotifyAndFail( + process_synchronizer, "Consumer: Did not receive initial value ", kInitialValue, " in set scenario"); } std::int32_t valid_requested_value = kSetValidValue; @@ -229,22 +207,23 @@ int run_set_client(const std::size_t num_retries, const std::chrono::millisecond retry_backoff_time, valid_set_error)) { - std::cerr << "Valid Set call failed: " << valid_set_error << "\n"; - return -19; + NotifyAndFail(process_synchronizer, "Consumer: Valid Set call failed: ", valid_set_error); } if (valid_accepted_value != kSetValidValue) { - std::cerr << "Valid Set accepted value mismatch. Expected " << kSetValidValue << " but got " - << valid_accepted_value << "\n"; - return -20; + NotifyAndFail(process_synchronizer, + "Consumer: Valid Set accepted value mismatch. Expected ", + kSetValidValue, + " but got ", + valid_accepted_value); } const bool valid_value_received = PollForValue(proxy.test_field, kSetValidValue, num_retries, retry_backoff_time); if (!valid_value_received) { - std::cerr << "Did not receive valid set value " << kSetValidValue << " after Set call.\n"; - return -21; + NotifyAndFail( + process_synchronizer, "Consumer: Did not receive valid set value ", kSetValidValue, " after Set call"); } std::int32_t requested_value = kSetRequestValue; @@ -253,15 +232,16 @@ int run_set_client(const std::size_t num_retries, const std::chrono::millisecond if (!SetWithRetries( proxy.test_field, requested_value, accepted_value, num_retries, retry_backoff_time, invalid_set_error)) { - std::cerr << "Set call failed: " << invalid_set_error << "\n"; - return -22; + NotifyAndFail(process_synchronizer, "Consumer: Set call failed: ", invalid_set_error); } if (accepted_value != kSetAcceptedValue) { - std::cerr << "Set accepted value mismatch. Expected " << kSetAcceptedValue << " but got " << accepted_value - << "\n"; - return -23; + NotifyAndFail(process_synchronizer, + "Consumer: Set accepted value mismatch. Expected ", + kSetAcceptedValue, + " but got ", + accepted_value); } const bool clamped_value_received = @@ -270,31 +250,32 @@ int run_set_client(const std::size_t num_retries, const std::chrono::millisecond if (!clamped_value_received) { - std::cerr << "Did not receive clamped value " << kSetAcceptedValue << " after Set call.\n"; - return -24; + NotifyAndFail( + process_synchronizer, "Consumer: Did not receive clamped value ", kSetAcceptedValue, " after Set call"); } - return 0; + process_synchronizer.Notify(); } } // namespace -int run_client(const std::size_t num_retries, - const std::chrono::milliseconds retry_backoff_time, - const std::string& mode) +void run_consumer(const std::size_t num_retries, + const std::chrono::milliseconds retry_backoff_time, + const std::string& mode) { if (mode == "notifier") { - return run_notifier_client(num_retries, retry_backoff_time); + run_notifier_consumer(num_retries, retry_backoff_time); + return; } if (mode == "set") { - return run_set_client(num_retries, retry_backoff_time); + run_set_consumer(num_retries, retry_backoff_time); + return; } - // TODO: Add "get" mode client scenario coverage once getter-enabled field variant is introduced. - std::cerr << "Unsupported mode passed to client: " << mode << "\n"; - return -1; + // TODO: Add "get" mode consumer scenario coverage once getter-enabled field variant is introduced. + FailTest("Consumer: Unsupported mode: ", mode); } } // namespace score::mw::com::test diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.h index c7455e770..0aa22fd85 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.h +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.h @@ -21,7 +21,7 @@ namespace score::mw::com::test { -int run_client(std::size_t num_retries, std::chrono::milliseconds retry_backoff_time, const std::string& mode); +void run_consumer(std::size_t num_retries, std::chrono::milliseconds retry_backoff_time, const std::string& mode); } // namespace score::mw::com::test diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp index c945f8e63..9f631366b 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp @@ -13,12 +13,15 @@ #include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_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/fields/set_and_notifier/fields_test_resources/test_constants.h" #include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h" +#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include #include #include -#include #include namespace score::mw::com::test @@ -26,66 +29,57 @@ namespace score::mw::com::test namespace { -int run_notifier_service(const std::chrono::milliseconds& cycle_time, const score::cpp::stop_token& stop_token) +const std::string kInterprocessNotificationShmPath{"/fields_set_and_notifier_interprocess_notification"}; + +void run_notifier_provider(const score::cpp::stop_token& stop_token) { - auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); - if (!instance_specifier_result.has_value()) + auto process_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); + if (!process_synchronizer_result.has_value()) { - std::cerr << "Unable to create instance specifier, terminating\n"; - return -3; + FailTest("Provider: Could not create ProcessSynchronizer"); } - auto instance_specifier = std::move(instance_specifier_result).value(); - auto service_result = InitialOnlySkeleton::Create(std::move(instance_specifier)); - if (!service_result.has_value()) + SkeletonContainer skeleton_container{kInstanceSpecifierString}; + if (!skeleton_container.CreateSkeleton()) { - std::cerr << "Unable to construct InitialOnlySkeleton: " << service_result.error() << ", bailing!\n"; - return -4; + FailTest("Provider: Unable to construct InitialOnlySkeleton"); } - InitialOnlySkeleton& service{service_result.value()}; + auto& service = skeleton_container.GetSkeleton(); const auto update_result = service.test_field.Update(kInitialValue); if (!update_result.has_value()) { - std::cerr << "Unable to update initial field value: " << update_result.error() << ", bailing!\n"; - return -6; + FailTest("Provider: Unable to update initial field value: ", update_result.error()); } - const auto offer_result = service.OfferService(); - if (!offer_result.has_value()) + if (!skeleton_container.OfferService()) { - std::cerr << "Unable to offer InitialOnlySkeleton: " << offer_result.error() << ", bailing!\n"; - return -5; + FailTest("Provider: Unable to offer InitialOnlySkeleton"); } - while (!stop_token.stop_requested()) + if (!process_synchronizer_result->WaitWithAbort(stop_token)) { - std::this_thread::sleep_for(cycle_time); + FailTest("Provider: WaitWithAbort was stopped by stop_token instead of notification"); } service.StopOfferService(); - - return 0; } -int run_set_service(const std::chrono::milliseconds& cycle_time, const score::cpp::stop_token& stop_token) +void run_set_provider(const score::cpp::stop_token& stop_token) { - auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); - if (!instance_specifier_result.has_value()) + auto process_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); + if (!process_synchronizer_result.has_value()) { - std::cerr << "Unable to create instance specifier, terminating\n"; - return -13; + FailTest("Provider: Could not create ProcessSynchronizer"); } - auto instance_specifier = std::move(instance_specifier_result).value(); - auto service_result = SetEnabledSkeleton::Create(std::move(instance_specifier)); - if (!service_result.has_value()) + SkeletonContainer skeleton_container{kInstanceSpecifierString}; + if (!skeleton_container.CreateSkeleton()) { - std::cerr << "Unable to construct SetEnabledSkeleton: " << service_result.error() << ", bailing!\n"; - return -14; + FailTest("Provider: Unable to construct SetEnabledSkeleton"); } - SetEnabledSkeleton& service{service_result.value()}; + auto& service = skeleton_container.GetSkeleton(); const auto register_handler_result = service.test_field.RegisterSetHandler([](std::int32_t& value) noexcept { if (value > kSetAcceptedValue) { @@ -98,52 +92,45 @@ int run_set_service(const std::chrono::milliseconds& cycle_time, const score::cp }); if (!register_handler_result.has_value()) { - std::cerr << "Unable to register set handler: " << register_handler_result.error() << ", bailing!\n"; - return -15; + FailTest("Provider: Unable to register set handler: ", register_handler_result.error()); } const auto update_result = service.test_field.Update(kInitialValue); if (!update_result.has_value()) { - std::cerr << "Unable to update initial field value: " << update_result.error() << ", bailing!\n"; - return -16; + FailTest("Provider: Unable to update initial field value: ", update_result.error()); } - const auto offer_result = service.OfferService(); - if (!offer_result.has_value()) + if (!skeleton_container.OfferService()) { - std::cerr << "Unable to offer SetEnabledSkeleton: " << offer_result.error() << ", bailing!\n"; - return -17; + FailTest("Provider: Unable to offer SetEnabledSkeleton"); } - while (!stop_token.stop_requested()) + if (!process_synchronizer_result->WaitWithAbort(stop_token)) { - std::this_thread::sleep_for(cycle_time); + FailTest("Provider: WaitWithAbort was stopped by stop_token instead of notification"); } service.StopOfferService(); - - return 0; } } // namespace -int run_service(const std::chrono::milliseconds& cycle_time, - const score::cpp::stop_token& stop_token, - const std::string& mode) +void run_provider(const score::cpp::stop_token& stop_token, const std::string& mode) { if (mode == "notifier") { - return run_notifier_service(cycle_time, stop_token); + run_notifier_provider(stop_token); + return; } if (mode == "set") { - return run_set_service(cycle_time, stop_token); + run_set_provider(stop_token); + return; } - // TODO: Add "get" mode service scenario coverage once getter-enabled field variant is introduced. - std::cerr << "Unsupported mode passed to service: " << mode << "\n"; - return -1; + // TODO: Add "get" mode provider scenario coverage once getter-enabled field variant is introduced. + FailTest("Provider: Unsupported mode: ", mode); } } // namespace score::mw::com::test diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.h index 6d6d2386c..95a5dc32f 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.h +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.h @@ -16,15 +16,12 @@ #include -#include #include namespace score::mw::com::test { -int run_service(const std::chrono::milliseconds& cycle_time, - const score::cpp::stop_token& stop_token, - const std::string& mode); +void run_provider(const score::cpp::stop_token& stop_token, const std::string& mode); } // namespace score::mw::com::test diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_interface.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_interface.h new file mode 100644 index 000000000..bca864504 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_interface.h @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_INITIAL_ONLY_INTERFACE_H +#define SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_INITIAL_ONLY_INTERFACE_H + +#include + +namespace score::mw::com::test +{ + +template +class InitialOnlyInterface : public T::Base +{ + public: + using T::Base::Base; + + typename T::template Field test_field{*this, "test_field"}; +}; + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_INITIAL_ONLY_INTERFACE_H diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_interface.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_interface.h new file mode 100644 index 000000000..d2fb237a5 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_interface.h @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_SET_ENABLED_INTERFACE_H +#define SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_SET_ENABLED_INTERFACE_H + +#include + +namespace score::mw::com::test +{ + +template +class SetEnabledInterface : public T::Base +{ + public: + using T::Base::Base; + + typename T::template Field test_field{*this, "test_field"}; +}; + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_SET_ENABLED_INTERFACE_H diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.h new file mode 100644 index 000000000..ec0c36aaf --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.h @@ -0,0 +1,31 @@ +/******************************************************************************* + * 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_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_TEST_CONSTANTS_H +#define SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_TEST_CONSTANTS_H + +#include + +namespace score::mw::com::test +{ + +constexpr const char* const kInstanceSpecifierString = "test/fields/set_and_notifier"; + +constexpr std::int32_t kInitialValue = 18; +constexpr std::int32_t kSetValidValue = 42; +constexpr std::int32_t kSetRequestValue = 1234; +constexpr std::int32_t kSetAcceptedValue = 100; + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_TEST_CONSTANTS_H diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h index b938631e4..e26a70eb6 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h @@ -14,38 +14,13 @@ #ifndef SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_TEST_DATATYPE_H #define SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_TEST_DATATYPE_H +#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_interface.h" +#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_interface.h" #include "score/mw/com/types.h" -#include - namespace score::mw::com::test { -constexpr const char* const kInstanceSpecifierString = "test/fields/set_and_notifier"; - -const std::int32_t kInitialValue = 18; -const std::int32_t kSetValidValue = 42; -const std::int32_t kSetRequestValue = 1234; -const std::int32_t kSetAcceptedValue = 100; - -template -class InitialOnlyInterface : public T::Base -{ - public: - using T::Base::Base; - - typename T::template Field test_field{*this, "test_field"}; -}; - -template -class SetEnabledInterface : public T::Base -{ - public: - using T::Base::Base; - - typename T::template Field test_field{*this, "test_field"}; -}; - using InitialOnlyProxy = score::mw::com::AsProxy; using InitialOnlySkeleton = score::mw::com::AsSkeleton; diff --git a/score/mw/com/test/fields/set_and_notifier/integration_test/BUILD b/score/mw/com/test/fields/set_and_notifier/integration_test/BUILD index 14c2344a3..77cc6f923 100644 --- a/score/mw/com/test/fields/set_and_notifier/integration_test/BUILD +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/BUILD @@ -17,16 +17,32 @@ load("//quality/integration_testing:integration_testing.bzl", "integration_test" pkg_filegroup( name = "filesystem", srcs = [ - "//score/mw/com/test/fields/set_and_notifier:main_client-pkg", - "//score/mw/com/test/fields/set_and_notifier:main_service-pkg", + "//score/mw/com/test/fields/set_and_notifier:consumer-pkg", + "//score/mw/com/test/fields/set_and_notifier:provider-pkg", ], ) +py_library( + name = "test_fixture", + srcs = ["test_fixture.py"], +) + +integration_test( + name = "test_notifier", + timeout = "moderate", + srcs = [ + "test_notifier.py", + ":test_fixture", + ], + filesystem = ":filesystem", +) + integration_test( - name = "test_field_set_and_notifier", + name = "test_set_and_notifier", timeout = "moderate", srcs = [ - "test_field_set_and_notifier.py", + "test_set_and_notifier.py", + ":test_fixture", ], filesystem = ":filesystem", ) diff --git a/score/mw/com/test/fields/set_and_notifier/integration_test/test_fixture.py b/score/mw/com/test/fields/set_and_notifier/integration_test/test_fixture.py new file mode 100644 index 000000000..414fc716b --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/test_fixture.py @@ -0,0 +1,23 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + + +def consumer(target, mode, **kwargs): + args = ["--num-retries", "20", "--backoff-time", "50", "--mode", mode, + "--service-instance-manifest", "./etc/mw_com_config.json"] + return target.wrap_exec("bin/consumer", args, cwd="/opt/MainConsumerApp", wait_on_exit=True, **kwargs) + + +def provider(target, mode, **kwargs): + args = ["--mode", mode, "--service-instance-manifest", "./etc/mw_com_config.json"] + return target.wrap_exec("bin/provider", args, cwd="/opt/MainProviderApp", **kwargs) diff --git a/score/mw/com/test/fields/set_and_notifier/integration_test/test_get.py b/score/mw/com/test/fields/set_and_notifier/integration_test/test_get.py new file mode 100644 index 000000000..af068eba8 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/test_get.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, provider + +# TODO: Implement once get mode is supported by the provider and consumer binaries. +# Scenarios to cover: +# 1. calling Update / send -> calling get returns value set with send diff --git a/score/mw/com/test/fields/set_and_notifier/integration_test/test_get_and_notifier.py b/score/mw/com/test/fields/set_and_notifier/integration_test/test_get_and_notifier.py new file mode 100644 index 000000000..21648aabc --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/test_get_and_notifier.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 + +# TODO: Implement once get_and_notifier mode is supported by the provider and consumer binaries. +# Scenarios to cover (same as notifier and get, verifying result of both GetNewSamples and getter): +# 1. calling Update / send -> calling get returns value set with send +# 2. calling Update / send -> calling GetNewSamples returns value set with send diff --git a/score/mw/com/test/fields/set_and_notifier/integration_test/test_notifier.py b/score/mw/com/test/fields/set_and_notifier/integration_test/test_notifier.py new file mode 100644 index 000000000..13d2b3800 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/test_notifier.py @@ -0,0 +1,21 @@ +# ******************************************************************************* +# 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 + + +def test_field_notifier_initial_value(target): + """Test field initial value exchange between provider and consumer.""" + with provider(target, "notifier"): + with consumer(target, "notifier"): + pass diff --git a/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_and_get.py b/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_and_get.py new file mode 100644 index 000000000..ce184446b --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_and_get.py @@ -0,0 +1,20 @@ +# ******************************************************************************* +# 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 + +# TODO: Implement once set_and_get mode is supported by the provider and consumer binaries. +# Scenarios to cover: +# 1. calling set with valid value -> calling get returns value set with setter +# 2. calling set with invalid value (set handler clamps the value) -> calling get returns clamped value +# 3. calling Update / send -> calling get returns value set with send diff --git a/score/mw/com/test/fields/set_and_notifier/integration_test/test_field_set_and_notifier.py b/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_and_notifier.py similarity index 51% rename from score/mw/com/test/fields/set_and_notifier/integration_test/test_field_set_and_notifier.py rename to score/mw/com/test/fields/set_and_notifier/integration_test/test_set_and_notifier.py index aeb530512..65574c804 100644 --- a/score/mw/com/test/fields/set_and_notifier/integration_test/test_field_set_and_notifier.py +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_and_notifier.py @@ -11,28 +11,13 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* - -def client(target, mode, **kwargs): - args = ["--num-retries", "20", "--backoff-time", "50", "--mode", mode] - return target.wrap_exec("bin/main_client", args, cwd="/opt/MainClientApp", wait_on_exit=True, **kwargs) - - -def service(target, mode, **kwargs): - args = ["--cycle-time", "250", "--mode", mode] - return target.wrap_exec("bin/main_service", args, cwd="/opt/MainServiceApp", **kwargs) - - -def test_field_notifier_initial_value(target): - """Test field initial value exchange between service and client.""" - with service(target, "notifier"): - with client(target, "notifier"): - pass +from test_fixture import consumer, provider def test_field_set_value(target): - """Test field set exchange and accepted value propagation between service and client.""" - with service(target, "set"): - with client(target, "set"): + """Test field set exchange and accepted value propagation between provider and consumer.""" + with provider(target, "set"): + with consumer(target, "set"): pass diff --git a/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_get_and_notifier.py b/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_get_and_notifier.py new file mode 100644 index 000000000..c7e39ac8a --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_get_and_notifier.py @@ -0,0 +1,20 @@ +# ******************************************************************************* +# 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 + +# TODO: Implement once set_get_and_notifier mode is supported by the provider and consumer binaries. +# Scenarios to cover (same as set_and_notifier, but also verify result of getter): +# 1. calling set with valid value -> calling get and GetNewSamples both return value set with setter +# 2. calling set with invalid value (set handler clamps the value) -> calling get and GetNewSamples both return clamped value +# 3. calling Update / send -> calling get and GetNewSamples both return value set with send diff --git a/score/mw/com/test/fields/set_and_notifier/main_client.cpp b/score/mw/com/test/fields/set_and_notifier/main_client.cpp deleted file mode 100644 index 0adb5a6d9..000000000 --- a/score/mw/com/test/fields/set_and_notifier/main_client.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************* - * 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/common_test_resources/sctf_test_runner.h" -#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.h" - -#include - -int main(int argc, const char** argv) -{ - using Parameters = score::mw::com::test::SctfTestRunner::RunParameters::Parameters; - - const std::vector allowed_parameters{ - Parameters::NUM_RETRIES, Parameters::RETRY_BACKOFF_TIME, Parameters::MODE}; - score::mw::com::test::SctfTestRunner test_runner(argc, argv, allowed_parameters); - const auto& run_parameters = test_runner.GetRunParameters(); - - return score::mw::com::test::run_client( - run_parameters.GetNumRetries(), run_parameters.GetRetryBackoffTime(), run_parameters.GetMode()); -} diff --git a/score/mw/com/test/fields/set_and_notifier/main_service.cpp b/score/mw/com/test/fields/set_and_notifier/main_service.cpp deleted file mode 100644 index c912b689d..000000000 --- a/score/mw/com/test/fields/set_and_notifier/main_service.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************* - * 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/common_test_resources/sctf_test_runner.h" -#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.h" - -#include - -int main(int argc, const char** argv) -{ - using Parameters = score::mw::com::test::SctfTestRunner::RunParameters::Parameters; - - const std::vector allowed_parameters{Parameters::CYCLE_TIME, Parameters::MODE}; - score::mw::com::test::SctfTestRunner test_runner(argc, argv, allowed_parameters); - const auto& run_parameters = test_runner.GetRunParameters(); - - return score::mw::com::test::run_service( - run_parameters.GetCycleTime(), test_runner.GetStopToken(), run_parameters.GetMode()); -} diff --git a/score/mw/com/test/fields/set_and_notifier/provider.cpp b/score/mw/com/test/fields/set_and_notifier/provider.cpp new file mode 100644 index 000000000..456108489 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/provider.cpp @@ -0,0 +1,64 @@ +/******************************************************************************* + * 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/command_line_parser.h" +#include "score/mw/com/test/common_test_resources/fail_test.h" +#include "score/mw/com/test/common_test_resources/stop_token_sig_term_handler.h" +#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.h" + +#include +#include +#include +#include +#include + +int main(int argc, const char** argv) +{ + constexpr auto kModeArg = "mode"; + constexpr auto kServiceInstanceManifestArg = "service-instance-manifest"; + + const std::vector> parameter_description_pairs{ + {kModeArg, "Provider mode: notifier or set"}, + {kServiceInstanceManifestArg, "Path to the service instance manifest"}, + }; + + const auto args = score::mw::com::test::ParseCommandLineArguments(argc, argv, parameter_description_pairs); + + const auto mode_result = score::mw::com::test::GetValueIfProvided(args, kModeArg); + if (!mode_result.has_value()) + { + score::mw::com::test::FailTest("Provider: missing or invalid --", kModeArg, " argument"); + } + + const auto manifest_result = + score::mw::com::test::GetValueIfProvided(args, kServiceInstanceManifestArg); + if (!manifest_result.has_value()) + { + score::mw::com::test::FailTest("Provider: missing or invalid --", kServiceInstanceManifestArg, " argument"); + } + + score::mw::com::runtime::InitializeRuntime(score::mw::com::runtime::RuntimeConfiguration{manifest_result.value()}); + + 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\n"; + } + + const auto& mode = mode_result.value(); + + score::mw::com::test::run_provider(stop_source.get_token(), mode); + return EXIT_SUCCESS; +} diff --git a/score/mw/com/test/methods/methods_test_resources/BUILD b/score/mw/com/test/methods/methods_test_resources/BUILD index 5859773a4..5587f4567 100644 --- a/score/mw/com/test/methods/methods_test_resources/BUILD +++ b/score/mw/com/test/methods/methods_test_resources/BUILD @@ -55,6 +55,7 @@ cc_library( hdrs = ["process_synchronizer.h"], features = COMPILER_WARNING_FEATURES, visibility = [ + "//score/mw/com/test/fields:__subpackages__", "//score/mw/com/test/methods:__subpackages__", ], deps = [ From eee332f7861a9cab93c8564a44c43a7017920ae0 Mon Sep 17 00:00:00 2001 From: sahithinukala Date: Mon, 15 Jun 2026 23:07:14 +0530 Subject: [PATCH 06/13] refactor: move ProcessSynchronizer to common_test_resources ProcessSynchronizer was located in methods_test_resources but was already used by field tests. Move it to common_test_resources and update all include paths and BUILD dependencies accordingly. --- score/mw/com/test/common_test_resources/BUILD | 16 +++++++++ .../process_synchronizer.cpp | 2 +- .../process_synchronizer.h | 6 ++-- .../com/test/fields/field_initial_value/BUILD | 4 +-- .../fields/field_initial_value/client.cpp | 33 +++++++----------- .../fields/field_initial_value/service.cpp | 2 +- .../fields_test_resources/test_datatype.cpp | 14 -------- .../fields_test_resources/test_datatype.h | 34 ------------------- .../{consumer.cpp => main_consumer.cpp} | 0 .../{provider.cpp => main_provider.cpp} | 0 .../test/methods/basic_acceptance_test/BUILD | 4 +-- .../basic_acceptance_test/consumer.cpp | 2 +- .../basic_acceptance_test/provider.cpp | 2 +- .../test/methods/methods_test_resources/BUILD | 19 ----------- .../methods/non_trivial_constructors/BUILD | 4 +-- .../non_trivial_constructors/consumer.cpp | 2 +- .../non_trivial_constructors/provider.cpp | 2 +- .../test/methods/signature_variations/BUILD | 4 +-- .../methods/signature_variations/consumer.cpp | 2 +- .../methods/signature_variations/provider.cpp | 2 +- 20 files changed, 48 insertions(+), 106 deletions(-) rename score/mw/com/test/{methods/methods_test_resources => common_test_resources}/process_synchronizer.cpp (97%) rename score/mw/com/test/{methods/methods_test_resources => common_test_resources}/process_synchronizer.h (88%) delete mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.cpp delete mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h rename score/mw/com/test/fields/set_and_notifier/{consumer.cpp => main_consumer.cpp} (100%) rename score/mw/com/test/fields/set_and_notifier/{provider.cpp => main_provider.cpp} (100%) diff --git a/score/mw/com/test/common_test_resources/BUILD b/score/mw/com/test/common_test_resources/BUILD index 8b96b95b8..42829b518 100644 --- a/score/mw/com/test/common_test_resources/BUILD +++ b/score/mw/com/test/common_test_resources/BUILD @@ -396,3 +396,19 @@ cc_library( "@score_baselibs//score/result", ], ) + +cc_library( + name = "process_synchronizer", + srcs = ["process_synchronizer.cpp"], + hdrs = ["process_synchronizer.h"], + features = COMPILER_WARNING_FEATURES, + visibility = ["//score/mw/com/test:__subpackages__"], + deps = [ + "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:shared_memory_object_creator", + "//score/mw/com/test/common_test_resources:shared_memory_object_guard", + "@score_baselibs//score/mw/log", + "@score_baselibs//score/os/utils/interprocess:interprocess_notification", + "@score_baselibs//score/result", + ], +) diff --git a/score/mw/com/test/methods/methods_test_resources/process_synchronizer.cpp b/score/mw/com/test/common_test_resources/process_synchronizer.cpp similarity index 97% rename from score/mw/com/test/methods/methods_test_resources/process_synchronizer.cpp rename to score/mw/com/test/common_test_resources/process_synchronizer.cpp index d8b82aece..81d3142b0 100644 --- a/score/mw/com/test/methods/methods_test_resources/process_synchronizer.cpp +++ b/score/mw/com/test/common_test_resources/process_synchronizer.cpp @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" +#include "score/mw/com/test/common_test_resources/process_synchronizer.h" #include "score/mw/com/test/common_test_resources/fail_test.h" #include "score/mw/com/test/common_test_resources/shared_memory_object_creator.h" diff --git a/score/mw/com/test/methods/methods_test_resources/process_synchronizer.h b/score/mw/com/test/common_test_resources/process_synchronizer.h similarity index 88% rename from score/mw/com/test/methods/methods_test_resources/process_synchronizer.h rename to score/mw/com/test/common_test_resources/process_synchronizer.h index 9430db8cf..758c3570f 100644 --- a/score/mw/com/test/methods/methods_test_resources/process_synchronizer.h +++ b/score/mw/com/test/common_test_resources/process_synchronizer.h @@ -10,8 +10,8 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -#ifndef SCORE_MW_COM_TEST_METHODS_METHODS_TEST_RESOURCES_PROCESS_SYNCHRONIZER_H -#define SCORE_MW_COM_TEST_METHODS_METHODS_TEST_RESOURCES_PROCESS_SYNCHRONIZER_H +#ifndef SCORE_MW_COM_TEST_COMMON_TEST_RESOURCES_PROCESS_SYNCHRONIZER_H +#define SCORE_MW_COM_TEST_COMMON_TEST_RESOURCES_PROCESS_SYNCHRONIZER_H #include "score/mw/com/test/common_test_resources/shared_memory_object_creator.h" #include "score/mw/com/test/common_test_resources/shared_memory_object_guard.h" @@ -46,4 +46,4 @@ class ProcessSynchronizer } // namespace score::mw::com::test -#endif // SCORE_MW_COM_TEST_METHODS_METHODS_TEST_RESOURCES_PROCESS_SYNCHRONIZER_H +#endif // SCORE_MW_COM_TEST_COMMON_TEST_RESOURCES_PROCESS_SYNCHRONIZER_H diff --git a/score/mw/com/test/fields/field_initial_value/BUILD b/score/mw/com/test/fields/field_initial_value/BUILD index d32a1198b..884a98ddd 100644 --- a/score/mw/com/test/fields/field_initial_value/BUILD +++ b/score/mw/com/test/fields/field_initial_value/BUILD @@ -45,8 +45,8 @@ cc_binary( ":test_datatype", "//score/mw/com", "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/common_test_resources:stop_token_sig_term_handler", - "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", "@score_baselibs//score/mw/log", ], ) @@ -62,8 +62,8 @@ cc_binary( deps = [ ":test_datatype", "//score/mw/com", + "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/common_test_resources:sctf_test_runner", - "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", "@score_baselibs//score/mw/log", ], ) diff --git a/score/mw/com/test/fields/field_initial_value/client.cpp b/score/mw/com/test/fields/field_initial_value/client.cpp index 9a7a2862b..2a4ba8735 100644 --- a/score/mw/com/test/fields/field_initial_value/client.cpp +++ b/score/mw/com/test/fields/field_initial_value/client.cpp @@ -11,9 +11,10 @@ * SPDX-License-Identifier: Apache-2.0 *******************************************************************************/ +#include "score/mw/com/test/common_test_resources/fail_test.h" +#include "score/mw/com/test/common_test_resources/process_synchronizer.h" #include "score/mw/com/test/common_test_resources/sctf_test_runner.h" #include "score/mw/com/test/fields/field_initial_value/test_datatype.h" -#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include "score/mw/com/types.h" #include @@ -35,22 +36,20 @@ constexpr auto kMaxNumSamples{1U}; const std::string kInterprocessNotificationShmPath{"/field_initial_value_interprocess_notification"}; -int run_client(const std::size_t num_retries, const std::chrono::milliseconds retry_backoff_time) +void run_client(const std::size_t num_retries, const std::chrono::milliseconds retry_backoff_time) { using score::mw::com::test::TestDataProxy; auto process_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); if (!process_synchronizer_result.has_value()) { - std::cerr << "Unable to create ProcessSynchronizer, terminating\n"; - return -8; + FailTest("Unable to create ProcessSynchronizer"); } auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); if (!instance_specifier_result.has_value()) { - std::cerr << "Unable to create instance specifier, terminating\n"; - return -7; + FailTest("Unable to create instance specifier"); } auto instance_specifier = std::move(instance_specifier_result).value(); @@ -65,22 +64,19 @@ int run_client(const std::size_t num_retries, const std::chrono::milliseconds re if (!lola_proxy_handles_result.has_value()) { - std::cerr << "Unable to get handles, terminating\n"; - return -1; + FailTest("Unable to get handles"); } auto lola_proxy_handles = service_discovery_future.get(); if (lola_proxy_handles.empty()) { - std::cerr << "Unable to find lola service, terminating\n"; - return -2; + FailTest("Unable to find lola service"); } auto lola_proxy_result = TestDataProxy::Create(lola_proxy_handles[0]); if (!lola_proxy_result.has_value()) { - std::cerr << "Unable to create lola proxy, terminating\n"; - return -3; + FailTest("Unable to create lola proxy"); } auto& lola_proxy = lola_proxy_result.value(); score::cpp::optional received_value; @@ -93,8 +89,7 @@ int run_client(const std::size_t num_retries, const std::chrono::milliseconds re retries--; if (retries <= 0) { - std::cerr << "Subscription failed!\n"; - return -4; + FailTest("Subscription failed"); } } std::ignore = lola_proxy.test_field.GetNewSamples( @@ -107,18 +102,15 @@ int run_client(const std::size_t num_retries, const std::chrono::milliseconds re if (!received_value.has_value()) { - std::cerr << "Lola didn't receive a sample!\n"; - return -5; + FailTest("Lola didn't receive a sample"); } if (received_value.value() != kTestValue) { - std::cerr << "Expecting:" << kTestValue << " Received:" << received_value.value() << "!\n "; - return -6; + FailTest("Received value does not match expected value"); } process_synchronizer_result->Notify(); - return 0; } } // namespace @@ -135,5 +127,6 @@ int main(int argc, const char** argv) const auto num_retries = run_parameters.GetNumRetries(); const auto retry_backoff_time = run_parameters.GetRetryBackoffTime(); - return score::mw::com::test::run_client(num_retries, retry_backoff_time); + score::mw::com::test::run_client(num_retries, retry_backoff_time); + return EXIT_SUCCESS; } diff --git a/score/mw/com/test/fields/field_initial_value/service.cpp b/score/mw/com/test/fields/field_initial_value/service.cpp index 56d613853..3c5e6ee29 100644 --- a/score/mw/com/test/fields/field_initial_value/service.cpp +++ b/score/mw/com/test/fields/field_initial_value/service.cpp @@ -13,9 +13,9 @@ #include "score/mw/com/runtime.h" #include "score/mw/com/test/common_test_resources/fail_test.h" +#include "score/mw/com/test/common_test_resources/process_synchronizer.h" #include "score/mw/com/test/common_test_resources/stop_token_sig_term_handler.h" #include "score/mw/com/test/fields/field_initial_value/test_datatype.h" -#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.cpp deleted file mode 100644 index 1acbc6aac..000000000 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/******************************************************************************* - * 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/fields/set_and_notifier/fields_test_resources/test_datatype.h" diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h deleted file mode 100644 index e26a70eb6..000000000 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h +++ /dev/null @@ -1,34 +0,0 @@ -/******************************************************************************* - * 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_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_TEST_DATATYPE_H -#define SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_TEST_DATATYPE_H - -#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_interface.h" -#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_interface.h" -#include "score/mw/com/types.h" - -namespace score::mw::com::test -{ - -using InitialOnlyProxy = score::mw::com::AsProxy; -using InitialOnlySkeleton = score::mw::com::AsSkeleton; - -using SetEnabledProxy = score::mw::com::AsProxy; -using SetEnabledSkeleton = score::mw::com::AsSkeleton; - -// TODO: Add a getter-enabled field interface type for dedicated "get" mode integration scenarios. - -} // namespace score::mw::com::test - -#endif // SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_TEST_DATATYPE_H diff --git a/score/mw/com/test/fields/set_and_notifier/consumer.cpp b/score/mw/com/test/fields/set_and_notifier/main_consumer.cpp similarity index 100% rename from score/mw/com/test/fields/set_and_notifier/consumer.cpp rename to score/mw/com/test/fields/set_and_notifier/main_consumer.cpp diff --git a/score/mw/com/test/fields/set_and_notifier/provider.cpp b/score/mw/com/test/fields/set_and_notifier/main_provider.cpp similarity index 100% rename from score/mw/com/test/fields/set_and_notifier/provider.cpp rename to score/mw/com/test/fields/set_and_notifier/main_provider.cpp diff --git a/score/mw/com/test/methods/basic_acceptance_test/BUILD b/score/mw/com/test/methods/basic_acceptance_test/BUILD index 0c6a46966..34b85eb74 100644 --- a/score/mw/com/test/methods/basic_acceptance_test/BUILD +++ b/score/mw/com/test/methods/basic_acceptance_test/BUILD @@ -41,8 +41,8 @@ cc_library( implementation_deps = [ ":test_method_datatype", "//score/mw/com", + "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/common_test_resources:proxy_container", - "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", ], ) @@ -54,8 +54,8 @@ cc_library( implementation_deps = [ ":test_method_datatype", "//score/mw/com", + "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/common_test_resources:skeleton_container", - "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", ], deps = [ "@score_baselibs//score/language/futurecpp", diff --git a/score/mw/com/test/methods/basic_acceptance_test/consumer.cpp b/score/mw/com/test/methods/basic_acceptance_test/consumer.cpp index 3fd59e604..d4a755875 100644 --- a/score/mw/com/test/methods/basic_acceptance_test/consumer.cpp +++ b/score/mw/com/test/methods/basic_acceptance_test/consumer.cpp @@ -13,9 +13,9 @@ #include "score/mw/com/test/methods/basic_acceptance_test/consumer.h" #include "score/mw/com/test/common_test_resources/fail_test.h" +#include "score/mw/com/test/common_test_resources/process_synchronizer.h" #include "score/mw/com/test/common_test_resources/proxy_container.h" #include "score/mw/com/test/methods/basic_acceptance_test/test_method_datatype.h" -#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include "score/mw/com/types.h" #include diff --git a/score/mw/com/test/methods/basic_acceptance_test/provider.cpp b/score/mw/com/test/methods/basic_acceptance_test/provider.cpp index 052ca6943..dd2f8c989 100644 --- a/score/mw/com/test/methods/basic_acceptance_test/provider.cpp +++ b/score/mw/com/test/methods/basic_acceptance_test/provider.cpp @@ -13,9 +13,9 @@ #include "score/mw/com/test/methods/basic_acceptance_test/provider.h" #include "score/mw/com/test/common_test_resources/fail_test.h" +#include "score/mw/com/test/common_test_resources/process_synchronizer.h" #include "score/mw/com/test/common_test_resources/skeleton_container.h" #include "score/mw/com/test/methods/basic_acceptance_test/test_method_datatype.h" -#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include "score/mw/com/types.h" #include "score/result/result.h" diff --git a/score/mw/com/test/methods/methods_test_resources/BUILD b/score/mw/com/test/methods/methods_test_resources/BUILD index 5587f4567..37a18ab16 100644 --- a/score/mw/com/test/methods/methods_test_resources/BUILD +++ b/score/mw/com/test/methods/methods_test_resources/BUILD @@ -48,22 +48,3 @@ cc_library( "@score_baselibs//score/mw/log", ], ) - -cc_library( - name = "process_synchronizer", - srcs = ["process_synchronizer.cpp"], - hdrs = ["process_synchronizer.h"], - features = COMPILER_WARNING_FEATURES, - visibility = [ - "//score/mw/com/test/fields:__subpackages__", - "//score/mw/com/test/methods:__subpackages__", - ], - deps = [ - "//score/mw/com/test/common_test_resources:fail_test", - "//score/mw/com/test/common_test_resources:shared_memory_object_creator", - "//score/mw/com/test/common_test_resources:shared_memory_object_guard", - "@score_baselibs//score/mw/log", - "@score_baselibs//score/os/utils/interprocess:interprocess_notification", - "@score_baselibs//score/result", - ], -) diff --git a/score/mw/com/test/methods/non_trivial_constructors/BUILD b/score/mw/com/test/methods/non_trivial_constructors/BUILD index 626c5a96c..4b7469c52 100644 --- a/score/mw/com/test/methods/non_trivial_constructors/BUILD +++ b/score/mw/com/test/methods/non_trivial_constructors/BUILD @@ -40,8 +40,8 @@ cc_library( implementation_deps = [ ":test_method_datatype", "//score/mw/com", + "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/common_test_resources:proxy_container", - "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", ], deps = [ "@score_baselibs//score/language/futurecpp", @@ -56,8 +56,8 @@ cc_library( deps = [ ":test_method_datatype", "//score/mw/com", + "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/common_test_resources:skeleton_container", - "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", ], ) diff --git a/score/mw/com/test/methods/non_trivial_constructors/consumer.cpp b/score/mw/com/test/methods/non_trivial_constructors/consumer.cpp index 3304d4541..0bbe688f3 100644 --- a/score/mw/com/test/methods/non_trivial_constructors/consumer.cpp +++ b/score/mw/com/test/methods/non_trivial_constructors/consumer.cpp @@ -13,8 +13,8 @@ #include "score/mw/com/test/methods/non_trivial_constructors/consumer.h" #include "score/mw/com/test/common_test_resources/fail_test.h" +#include "score/mw/com/test/common_test_resources/process_synchronizer.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/methods/non_trivial_constructors/test_method_datatype.h" #include "score/mw/com/types.h" diff --git a/score/mw/com/test/methods/non_trivial_constructors/provider.cpp b/score/mw/com/test/methods/non_trivial_constructors/provider.cpp index d326e2552..ff4c51569 100644 --- a/score/mw/com/test/methods/non_trivial_constructors/provider.cpp +++ b/score/mw/com/test/methods/non_trivial_constructors/provider.cpp @@ -13,8 +13,8 @@ #include "score/mw/com/test/methods/non_trivial_constructors/provider.h" #include "score/mw/com/test/common_test_resources/fail_test.h" +#include "score/mw/com/test/common_test_resources/process_synchronizer.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/methods/non_trivial_constructors/test_method_datatype.h" #include "score/mw/com/types.h" diff --git a/score/mw/com/test/methods/signature_variations/BUILD b/score/mw/com/test/methods/signature_variations/BUILD index 1d4007c90..19d2ec224 100644 --- a/score/mw/com/test/methods/signature_variations/BUILD +++ b/score/mw/com/test/methods/signature_variations/BUILD @@ -41,8 +41,8 @@ cc_library( implementation_deps = [ ":test_method_datatype", "//score/mw/com", + "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/methods/methods_test_resources:method_consumer", - "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", ], deps = [ "@score_baselibs//score/language/futurecpp", @@ -57,8 +57,8 @@ cc_library( deps = [ ":test_method_datatype", "//score/mw/com", + "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/methods/methods_test_resources:method_provider", - "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", ], ) diff --git a/score/mw/com/test/methods/signature_variations/consumer.cpp b/score/mw/com/test/methods/signature_variations/consumer.cpp index 2d6123f00..e820c0b85 100644 --- a/score/mw/com/test/methods/signature_variations/consumer.cpp +++ b/score/mw/com/test/methods/signature_variations/consumer.cpp @@ -12,8 +12,8 @@ ********************************************************************************/ #include "score/mw/com/test/methods/signature_variations/consumer.h" +#include "score/mw/com/test/common_test_resources/process_synchronizer.h" #include "score/mw/com/test/methods/methods_test_resources/method_consumer.h" -#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include "score/mw/com/test/methods/signature_variations/test_method_datatype.h" #include "score/mw/com/types.h" diff --git a/score/mw/com/test/methods/signature_variations/provider.cpp b/score/mw/com/test/methods/signature_variations/provider.cpp index ffd5ec0f1..aaf7bb9f0 100644 --- a/score/mw/com/test/methods/signature_variations/provider.cpp +++ b/score/mw/com/test/methods/signature_variations/provider.cpp @@ -12,8 +12,8 @@ ********************************************************************************/ #include "score/mw/com/test/methods/signature_variations/provider.h" +#include "score/mw/com/test/common_test_resources/process_synchronizer.h" #include "score/mw/com/test/methods/methods_test_resources/method_provider.h" -#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include "score/mw/com/test/methods/signature_variations/test_method_datatype.h" #include "score/mw/com/types.h" From 47ebcfd0d0d4883f3918ac750ded58bb721cfb1c Mon Sep 17 00:00:00 2001 From: sahithinukala Date: Mon, 15 Jun 2026 23:10:37 +0530 Subject: [PATCH 07/13] refactor: set_and_notifier structural changes - Update test_constants: replace kSetValidValue/kSetAcceptedValue with kSetTransformedValue and add kUpdatedValue - Update BUILD files to reference the new common interface targets - Update field_provider to use updated constants and logic - Update integration test fixture to accept config filename parameter so notifier and set_and_notifier tests use separate manifests - Rename test_field_set_value -> test_field_set_and_notifier_value --- .../mw/com/test/fields/set_and_notifier/BUILD | 27 +++++++-- .../fields_test_resources/BUILD | 21 ++++--- .../fields_test_resources/field_provider.cpp | 58 ++++++++++++------- .../initial_only_interface.h | 33 ----------- .../set_enabled_interface.h | 33 ----------- .../fields_test_resources/test_constants.h | 4 +- .../integration_test/test_fixture.py | 8 +-- .../integration_test/test_notifier.py | 4 +- .../integration_test/test_set_and_notifier.py | 6 +- 9 files changed, 81 insertions(+), 113 deletions(-) delete mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_interface.h delete mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_interface.h diff --git a/score/mw/com/test/fields/set_and_notifier/BUILD b/score/mw/com/test/fields/set_and_notifier/BUILD index 6a0b0840b..fb866313b 100644 --- a/score/mw/com/test/fields/set_and_notifier/BUILD +++ b/score/mw/com/test/fields/set_and_notifier/BUILD @@ -23,10 +23,20 @@ validate_json_schema_test( tags = ["lint"], ) +validate_json_schema_test( + name = "validate_initial_only_field_lola_schema", + json = "config/initial_only_field_mw_com_config.json", + schema = "//score/mw/com:config_schema", + tags = ["lint"], +) + cc_binary( name = "provider", - srcs = ["provider.cpp"], - data = ["config/mw_com_config.json"], + srcs = ["main_provider.cpp"], + data = [ + "config/initial_only_field_mw_com_config.json", + "config/mw_com_config.json", + ], features = COMPILER_WARNING_FEATURES + [ "aborts_upon_exception", ], @@ -43,8 +53,11 @@ cc_binary( cc_binary( name = "consumer", - srcs = ["consumer.cpp"], - data = ["config/mw_com_config.json"], + srcs = ["main_consumer.cpp"], + data = [ + "config/initial_only_field_mw_com_config.json", + "config/mw_com_config.json", + ], features = COMPILER_WARNING_FEATURES + [ "aborts_upon_exception", ], @@ -63,8 +76,9 @@ pkg_application( app_name = "MainProviderApp", bin = [":provider"], etc = [ - "config/mw_com_config.json", + "config/initial_only_field_mw_com_config.json", "config/logging.json", + "config/mw_com_config.json", ], visibility = [ "//platform/aas/test/mw/com:__pkg__", @@ -77,8 +91,9 @@ pkg_application( app_name = "MainConsumerApp", bin = [":consumer"], etc = [ - "config/mw_com_config.json", + "config/initial_only_field_mw_com_config.json", "config/logging.json", + "config/mw_com_config.json", ], visibility = [ "//platform/aas/test/mw/com:__pkg__", diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/BUILD b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/BUILD index 36de65c78..fbc0e14eb 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/BUILD +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/BUILD @@ -15,13 +15,16 @@ load("@rules_cc//cc:defs.bzl", "cc_library") load("@score_baselibs//score/language/safecpp:toolchain_features.bzl", "COMPILER_WARNING_FEATURES") cc_library( - name = "test_datatype", - srcs = ["test_datatype.cpp"], + name = "field_types", + srcs = [ + "initial_only_field.cpp", + "set_enabled_field.cpp", + "test_constants.cpp", + ], hdrs = [ - "initial_only_interface.h", - "set_enabled_interface.h", + "initial_only_field.h", + "set_enabled_field.h", "test_constants.h", - "test_datatype.h", ], features = COMPILER_WARNING_FEATURES, visibility = [ @@ -41,11 +44,11 @@ cc_library( "//score/mw/com/test/fields/set_and_notifier:__subpackages__", ], deps = [ - ":test_datatype", + ":field_types", "//score/mw/com", "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/common_test_resources:proxy_container", - "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", ], ) @@ -58,10 +61,10 @@ cc_library( "//score/mw/com/test/fields/set_and_notifier:__subpackages__", ], deps = [ - ":test_datatype", + ":field_types", "//score/mw/com", "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/common_test_resources:skeleton_container", - "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", ], ) diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp index 9f631366b..ddb44a813 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp @@ -14,10 +14,11 @@ #include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.h" #include "score/mw/com/test/common_test_resources/fail_test.h" +#include "score/mw/com/test/common_test_resources/process_synchronizer.h" #include "score/mw/com/test/common_test_resources/skeleton_container.h" +#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.h" +#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_field.h" #include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.h" -#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h" -#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include #include @@ -30,13 +31,20 @@ namespace { const std::string kInterprocessNotificationShmPath{"/fields_set_and_notifier_interprocess_notification"}; +const std::string kNotifierConsumerReadyShmPath{"/fields_notifier_consumer_ready"}; void run_notifier_provider(const score::cpp::stop_token& stop_token) { - auto process_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); - if (!process_synchronizer_result.has_value()) + auto consumer_ready_synchronizer_result = ProcessSynchronizer::Create(kNotifierConsumerReadyShmPath); + if (!consumer_ready_synchronizer_result.has_value()) { - FailTest("Provider: Could not create ProcessSynchronizer"); + FailTest("Provider: Could not create consumer ready ProcessSynchronizer"); + } + + auto done_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); + if (!done_synchronizer_result.has_value()) + { + FailTest("Provider: Could not create done ProcessSynchronizer"); } SkeletonContainer skeleton_container{kInstanceSpecifierString}; @@ -47,25 +55,40 @@ void run_notifier_provider(const score::cpp::stop_token& stop_token) auto& service = skeleton_container.GetSkeleton(); - const auto update_result = service.test_field.Update(kInitialValue); - if (!update_result.has_value()) { - FailTest("Provider: Unable to update initial field value: ", update_result.error()); + const auto update_result = service.test_field.Update(kInitialValue); + if (!update_result.has_value()) + { + FailTest("Provider: Unable to update initial field value: ", update_result.error()); + } } if (!skeleton_container.OfferService()) { FailTest("Provider: Unable to offer InitialOnlySkeleton"); } - if (!process_synchronizer_result->WaitWithAbort(stop_token)) + if (!consumer_ready_synchronizer_result->WaitWithAbort(stop_token)) { - FailTest("Provider: WaitWithAbort was stopped by stop_token instead of notification"); + FailTest("Provider: WaitWithAbort (consumer ready) was stopped by stop_token instead of notification"); + } + + { + const auto update_result = service.test_field.Update(kUpdatedValue); + if (!update_result.has_value()) + { + FailTest("Provider: Unable to update field with updated value: ", update_result.error()); + } + } + + if (!done_synchronizer_result->WaitWithAbort(stop_token)) + { + FailTest("Provider: WaitWithAbort (done) was stopped by stop_token instead of notification"); } service.StopOfferService(); } -void run_set_provider(const score::cpp::stop_token& stop_token) +void run_set_and_notifier_provider(const score::cpp::stop_token& stop_token) { auto process_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); if (!process_synchronizer_result.has_value()) @@ -81,14 +104,7 @@ void run_set_provider(const score::cpp::stop_token& stop_token) auto& service = skeleton_container.GetSkeleton(); const auto register_handler_result = service.test_field.RegisterSetHandler([](std::int32_t& value) noexcept { - if (value > kSetAcceptedValue) - { - value = kSetAcceptedValue; - } - if (value < 0) - { - value = 0; - } + value = value * 2 + 1; }); if (!register_handler_result.has_value()) { @@ -123,9 +139,9 @@ void run_provider(const score::cpp::stop_token& stop_token, const std::string& m run_notifier_provider(stop_token); return; } - if (mode == "set") + if (mode == "set_and_notifier") { - run_set_provider(stop_token); + run_set_and_notifier_provider(stop_token); return; } diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_interface.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_interface.h deleted file mode 100644 index bca864504..000000000 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_interface.h +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * 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_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_INITIAL_ONLY_INTERFACE_H -#define SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_INITIAL_ONLY_INTERFACE_H - -#include - -namespace score::mw::com::test -{ - -template -class InitialOnlyInterface : public T::Base -{ - public: - using T::Base::Base; - - typename T::template Field test_field{*this, "test_field"}; -}; - -} // namespace score::mw::com::test - -#endif // SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_INITIAL_ONLY_INTERFACE_H diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_interface.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_interface.h deleted file mode 100644 index d2fb237a5..000000000 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_interface.h +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * 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_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_SET_ENABLED_INTERFACE_H -#define SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_SET_ENABLED_INTERFACE_H - -#include - -namespace score::mw::com::test -{ - -template -class SetEnabledInterface : public T::Base -{ - public: - using T::Base::Base; - - typename T::template Field test_field{*this, "test_field"}; -}; - -} // namespace score::mw::com::test - -#endif // SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_SET_ENABLED_INTERFACE_H diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.h index ec0c36aaf..bea27d2fc 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.h +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.h @@ -22,9 +22,9 @@ namespace score::mw::com::test constexpr const char* const kInstanceSpecifierString = "test/fields/set_and_notifier"; constexpr std::int32_t kInitialValue = 18; -constexpr std::int32_t kSetValidValue = 42; constexpr std::int32_t kSetRequestValue = 1234; -constexpr std::int32_t kSetAcceptedValue = 100; +constexpr std::int32_t kSetTransformedValue = kSetRequestValue * 2 + 1; +constexpr std::int32_t kUpdatedValue = 19; } // namespace score::mw::com::test diff --git a/score/mw/com/test/fields/set_and_notifier/integration_test/test_fixture.py b/score/mw/com/test/fields/set_and_notifier/integration_test/test_fixture.py index 414fc716b..5f74fef2f 100644 --- a/score/mw/com/test/fields/set_and_notifier/integration_test/test_fixture.py +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/test_fixture.py @@ -12,12 +12,12 @@ # ******************************************************************************* -def consumer(target, mode, **kwargs): +def consumer(target, mode, config, **kwargs): args = ["--num-retries", "20", "--backoff-time", "50", "--mode", mode, - "--service-instance-manifest", "./etc/mw_com_config.json"] + "--service-instance-manifest", f"./etc/{config}"] return target.wrap_exec("bin/consumer", args, cwd="/opt/MainConsumerApp", wait_on_exit=True, **kwargs) -def provider(target, mode, **kwargs): - args = ["--mode", mode, "--service-instance-manifest", "./etc/mw_com_config.json"] +def provider(target, mode, config, **kwargs): + args = ["--mode", mode, "--service-instance-manifest", f"./etc/{config}"] return target.wrap_exec("bin/provider", args, cwd="/opt/MainProviderApp", **kwargs) diff --git a/score/mw/com/test/fields/set_and_notifier/integration_test/test_notifier.py b/score/mw/com/test/fields/set_and_notifier/integration_test/test_notifier.py index 13d2b3800..2d399560b 100644 --- a/score/mw/com/test/fields/set_and_notifier/integration_test/test_notifier.py +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/test_notifier.py @@ -16,6 +16,6 @@ def test_field_notifier_initial_value(target): """Test field initial value exchange between provider and consumer.""" - with provider(target, "notifier"): - with consumer(target, "notifier"): + with provider(target, "notifier", "initial_only_field_mw_com_config.json"): + with consumer(target, "notifier", "initial_only_field_mw_com_config.json"): pass diff --git a/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_and_notifier.py b/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_and_notifier.py index 65574c804..c646bac23 100644 --- a/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_and_notifier.py +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_and_notifier.py @@ -14,10 +14,10 @@ from test_fixture import consumer, provider -def test_field_set_value(target): +def test_field_set_and_notifier_value(target): """Test field set exchange and accepted value propagation between provider and consumer.""" - with provider(target, "set"): - with consumer(target, "set"): + with provider(target, "set_and_notifier", "mw_com_config.json"): + with consumer(target, "set_and_notifier", "mw_com_config.json"): pass From fb95172d631e73ffb47b94bac464c18afafaee04 Mon Sep 17 00:00:00 2001 From: sahithinukala Date: Mon, 15 Jun 2026 23:13:12 +0530 Subject: [PATCH 08/13] mw/com: use event-driven SetReceiveHandler in field_consumer --- .../fields_test_resources/field_consumer.cpp | 302 +++++++++--------- 1 file changed, 158 insertions(+), 144 deletions(-) diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp index 378eae826..8bcaaa30d 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp @@ -14,20 +14,21 @@ #include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.h" #include "score/mw/com/test/common_test_resources/fail_test.h" +#include "score/mw/com/test/common_test_resources/process_synchronizer.h" #include "score/mw/com/test/common_test_resources/proxy_container.h" +#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.h" +#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_field.h" #include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.h" -#include "score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h" -#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include "score/mw/com/types.h" #include #include +#include #include #include -#include +#include #include -#include #include namespace score::mw::com::test @@ -37,228 +38,242 @@ namespace constexpr auto kMaxNumSamples{1U}; const std::string kInterprocessNotificationShmPath{"/fields_set_and_notifier_interprocess_notification"}; - -template -void NotifyAndFail(ProcessSynchronizer& process_synchronizer, Args&&... args) -{ - process_synchronizer.Notify(); - FailTest(std::forward(args)...); -} +const std::string kNotifierConsumerReadyShmPath{"/fields_notifier_consumer_ready"}; template bool WaitForSubscription(FieldType& field, std::size_t retries, const std::chrono::milliseconds retry_backoff_time) { - while (field.GetSubscriptionState() != score::mw::com::impl::SubscriptionState::kSubscribed) + std::mutex mutex; + std::condition_variable cv; + bool subscribed{false}; + + const auto handler_result = field.SetSubscriptionStateChangeHandler( + [&mutex, &cv, &subscribed](score::mw::com::impl::SubscriptionState new_state) noexcept -> bool { + if (new_state == score::mw::com::impl::SubscriptionState::kSubscribed) + { + { + std::lock_guard lock{mutex}; + subscribed = true; + } + cv.notify_one(); + return false; + } + return true; + }); + + if (!handler_result.has_value()) { - std::this_thread::sleep_for(retry_backoff_time); - if (retries == 0) - { - return false; - } - --retries; + return false; } - return true; + + // subscription may have become kSubscribed before the handler was registered + if (field.GetSubscriptionState() == score::mw::com::impl::SubscriptionState::kSubscribed) + { + std::ignore = field.UnsetSubscriptionStateChangeHandler(); + return true; + } + + const auto total_wait_time = retry_backoff_time * retries; + std::unique_lock lock{mutex}; + const bool success = cv.wait_for(lock, total_wait_time, [&subscribed] { + return subscribed; + }); + if (!success) + { + std::ignore = field.UnsetSubscriptionStateChangeHandler(); + } + return success; } template -bool PollForValue(FieldType& field, +bool WaitForValue(FieldType& field, const std::int32_t expected_value, std::size_t retries, const std::chrono::milliseconds retry_backoff_time) { - while (retries > 0) + struct SyncState { - score::cpp::optional received_value; - const auto samples_result = field.GetNewSamples( - [&received_value](const auto& sample_ptr) noexcept { - received_value = *sample_ptr; + std::mutex mutex{}; + std::condition_variable cv{}; + bool value_received{false}; + }; + SyncState sync_state; + + const auto handler_result = field.SetReceiveHandler([&field, &sync_state, expected_value]() noexcept { + score::cpp::optional received; + std::ignore = field.GetNewSamples( + [&received](const auto& sample_ptr) noexcept { + received = *sample_ptr; }, kMaxNumSamples); - - if (samples_result.has_value() && received_value.has_value() && received_value.value() == expected_value) + if (received.has_value() && received.value() == expected_value) { - return true; + { + std::lock_guard lock{sync_state.mutex}; + sync_state.value_received = true; + } + sync_state.cv.notify_one(); } + }); - std::this_thread::sleep_for(retry_backoff_time); - --retries; + if (!handler_result.has_value()) + { + return false; } - return false; -} - -template -bool SetWithRetries(FieldType& field, - std::int32_t& requested_value, - std::int32_t& accepted_value, - std::size_t retries, - const std::chrono::milliseconds retry_backoff_time, - std::string& last_error) -{ - while (true) + // Handle race: value may already be in the buffer before the handler was registered { - const auto set_result = field.Set(requested_value); - if (set_result.has_value()) + score::cpp::optional existing; + std::ignore = field.GetNewSamples( + [&existing](const auto& sample_ptr) noexcept { + existing = *sample_ptr; + }, + kMaxNumSamples); + if (existing.has_value() && existing.value() == expected_value) { - accepted_value = *(set_result.value()); + std::ignore = field.UnsetReceiveHandler(); return true; } + } - std::ostringstream error_stream; - error_stream << set_result.error(); - last_error = error_stream.str(); - - if (retries == 0) - { - return false; - } - - --retries; - std::this_thread::sleep_for(retry_backoff_time); + const auto total_wait_time = retry_backoff_time * retries; + bool success; + { + std::unique_lock lock{sync_state.mutex}; + success = sync_state.cv.wait_for(lock, total_wait_time, [&sync_state] { + return sync_state.value_received; + }); } + std::ignore = field.UnsetReceiveHandler(); + return success; } +} // namespace + void run_notifier_consumer(const std::size_t num_retries, const std::chrono::milliseconds retry_backoff_time) { - auto process_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); - if (!process_synchronizer_result.has_value()) + auto consumer_ready_synchronizer_result = ProcessSynchronizer::Create(kNotifierConsumerReadyShmPath); + if (!consumer_ready_synchronizer_result.has_value()) { - FailTest("Consumer: Could not create ProcessSynchronizer"); + FailTest("Consumer: Could not create consumer ready ProcessSynchronizer"); } - auto& process_synchronizer = process_synchronizer_result.value(); + auto& consumer_ready_synchronizer = consumer_ready_synchronizer_result.value(); - auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); - if (!instance_specifier_result.has_value()) + auto done_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); + if (!done_synchronizer_result.has_value()) { - NotifyAndFail(process_synchronizer, "Consumer: Unable to create instance specifier"); + FailTest("Consumer: Could not create done ProcessSynchronizer"); } - auto instance_specifier = std::move(instance_specifier_result).value(); + ExitFunctionGuard done_guard{[&done_synchronizer_result]() { + done_synchronizer_result->Notify(); + }}; - ProxyContainer proxy_container{}; - if (!proxy_container.CreateProxy(std::move(instance_specifier))) + // Step 1. Find service and create proxy + std::cout << "\nConsumer: Step 1" << std::endl; + auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); + if (!instance_specifier_result.has_value()) { - NotifyAndFail(process_synchronizer, "Consumer: Unable to create InitialOnlyProxy"); + FailTest("Consumer: Unable to create instance specifier"); } - + ProxyContainer proxy_container{}; + proxy_container.CreateProxy(std::move(instance_specifier_result).value(), "set_and_notifier"); auto& proxy = proxy_container.GetProxy(); + + // Step 2. Subscribe to field and wait for subscription + std::cout << "\nConsumer: Step 2" << std::endl; std::ignore = proxy.test_field.Subscribe(kMaxNumSamples); if (!WaitForSubscription(proxy.test_field, num_retries, retry_backoff_time)) { - NotifyAndFail(process_synchronizer, "Consumer: Subscription failed in notifier scenario"); + FailTest("Consumer: Subscription failed in notifier scenario"); } - const bool initial_value_received = PollForValue(proxy.test_field, kInitialValue, num_retries, retry_backoff_time); - proxy.test_field.Unsubscribe(); - + // Step 3. Verify initial value received + std::cout << "\nConsumer: Step 3" << std::endl; + const bool initial_value_received = WaitForValue(proxy.test_field, kInitialValue, num_retries, retry_backoff_time); if (!initial_value_received) { - NotifyAndFail(process_synchronizer, - "Consumer: Did not receive expected initial value ", - kInitialValue, - " in notifier scenario"); + FailTest("Consumer: Did not receive expected initial value ", kInitialValue, " in notifier scenario"); } - process_synchronizer.Notify(); + // Step 4. Notify provider that consumer is ready + std::cout << "\nConsumer: Step 4" << std::endl; + consumer_ready_synchronizer.Notify(); + + // Step 5. Verify updated value received after provider publishes update + std::cout << "\nConsumer: Step 5" << std::endl; + const bool updated_value_received = WaitForValue(proxy.test_field, kUpdatedValue, num_retries, retry_backoff_time); + proxy.test_field.Unsubscribe(); + + if (!updated_value_received) + { + FailTest("Consumer: Did not receive expected updated value ", kUpdatedValue, " in notifier scenario"); + } } -void run_set_consumer(const std::size_t num_retries, const std::chrono::milliseconds retry_backoff_time) +void run_set_and_notifier_consumer(const std::size_t num_retries, const std::chrono::milliseconds retry_backoff_time) { auto process_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); if (!process_synchronizer_result.has_value()) { FailTest("Consumer: Could not create ProcessSynchronizer"); } - auto& process_synchronizer = process_synchronizer_result.value(); + ExitFunctionGuard process_synchronizer_guard{[&process_synchronizer_result]() { + process_synchronizer_result->Notify(); + }}; + // Step 1. Find service and create proxy + std::cout << "\nConsumer: Step 1" << std::endl; auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); if (!instance_specifier_result.has_value()) { - NotifyAndFail(process_synchronizer, "Consumer: Unable to create instance specifier"); + FailTest("Consumer: Unable to create instance specifier"); } - auto instance_specifier = std::move(instance_specifier_result).value(); - ProxyContainer proxy_container{}; - if (!proxy_container.CreateProxy(std::move(instance_specifier))) - { - NotifyAndFail(process_synchronizer, "Consumer: Unable to create SetEnabledProxy"); - } - + proxy_container.CreateProxy(std::move(instance_specifier_result).value(), "set_and_notifier"); auto& proxy = proxy_container.GetProxy(); + + // Step 2. Subscribe to field and wait for subscription + std::cout << "\nConsumer: Step 2" << std::endl; std::ignore = proxy.test_field.Subscribe(kMaxNumSamples); if (!WaitForSubscription(proxy.test_field, num_retries, retry_backoff_time)) { - NotifyAndFail(process_synchronizer, "Consumer: Subscription failed in set scenario"); + FailTest("Consumer: Subscription failed in set scenario"); } - const bool initial_value_received = PollForValue(proxy.test_field, kInitialValue, num_retries, retry_backoff_time); + // Step 3. Verify initial value received + std::cout << "\nConsumer: Step 3" << std::endl; + const bool initial_value_received = WaitForValue(proxy.test_field, kInitialValue, num_retries, retry_backoff_time); if (!initial_value_received) { - NotifyAndFail( - process_synchronizer, "Consumer: Did not receive initial value ", kInitialValue, " in set scenario"); - } - - std::int32_t valid_requested_value = kSetValidValue; - std::int32_t valid_accepted_value{0}; - std::string valid_set_error; - if (!SetWithRetries(proxy.test_field, - valid_requested_value, - valid_accepted_value, - num_retries, - retry_backoff_time, - valid_set_error)) - { - NotifyAndFail(process_synchronizer, "Consumer: Valid Set call failed: ", valid_set_error); - } - - if (valid_accepted_value != kSetValidValue) - { - NotifyAndFail(process_synchronizer, - "Consumer: Valid Set accepted value mismatch. Expected ", - kSetValidValue, - " but got ", - valid_accepted_value); - } - - const bool valid_value_received = PollForValue(proxy.test_field, kSetValidValue, num_retries, retry_backoff_time); - if (!valid_value_received) - { - NotifyAndFail( - process_synchronizer, "Consumer: Did not receive valid set value ", kSetValidValue, " after Set call"); + FailTest("Consumer: Did not receive initial value ", kInitialValue, " in set scenario"); } - std::int32_t requested_value = kSetRequestValue; - std::int32_t accepted_value{0}; - std::string invalid_set_error; - if (!SetWithRetries( - proxy.test_field, requested_value, accepted_value, num_retries, retry_backoff_time, invalid_set_error)) + // Step 4. Set new field value and verify accepted value matches expected transformed value + std::cout << "\nConsumer: Step 4" << std::endl; + const auto set_result = proxy.test_field.Set(kSetRequestValue); + if (!set_result.has_value()) { - NotifyAndFail(process_synchronizer, "Consumer: Set call failed: ", invalid_set_error); + FailTest("Consumer: Set call failed: ", set_result.error()); } + const std::int32_t accepted_value = *(set_result.value()); - if (accepted_value != kSetAcceptedValue) + if (accepted_value != kSetTransformedValue) { - NotifyAndFail(process_synchronizer, - "Consumer: Set accepted value mismatch. Expected ", - kSetAcceptedValue, - " but got ", - accepted_value); + FailTest("Consumer: Set accepted value mismatch. Expected ", kSetTransformedValue, " but got ", accepted_value); } - const bool clamped_value_received = - PollForValue(proxy.test_field, kSetAcceptedValue, num_retries, retry_backoff_time); + // Step 5. Verify transformed value received via field notification + std::cout << "\nConsumer: Step 5" << std::endl; + const bool transformed_value_received = + WaitForValue(proxy.test_field, kSetTransformedValue, num_retries, retry_backoff_time); proxy.test_field.Unsubscribe(); - if (!clamped_value_received) + if (!transformed_value_received) { - NotifyAndFail( - process_synchronizer, "Consumer: Did not receive clamped value ", kSetAcceptedValue, " after Set call"); + FailTest("Consumer: Did not receive transformed value ", kSetTransformedValue, " after Set call"); } - - process_synchronizer.Notify(); } -} // namespace - void run_consumer(const std::size_t num_retries, const std::chrono::milliseconds retry_backoff_time, const std::string& mode) @@ -268,14 +283,13 @@ void run_consumer(const std::size_t num_retries, run_notifier_consumer(num_retries, retry_backoff_time); return; } - if (mode == "set") + if (mode == "set_and_notifier") { - run_set_consumer(num_retries, retry_backoff_time); + run_set_and_notifier_consumer(num_retries, retry_backoff_time); return; } // TODO: Add "get" mode consumer scenario coverage once getter-enabled field variant is introduced. FailTest("Consumer: Unsupported mode: ", mode); } - } // namespace score::mw::com::test From 3d688842cdd80960e302f02795c47b6fb4988736 Mon Sep 17 00:00:00 2001 From: sahithinukala Date: Mon, 15 Jun 2026 23:14:29 +0530 Subject: [PATCH 09/13] mw/com: extract ParseConfig in main_consumer --- .../fields/set_and_notifier/main_consumer.cpp | 30 ++++++++++++++++--- .../fields/set_and_notifier/main_provider.cpp | 26 ++++++++++++---- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/score/mw/com/test/fields/set_and_notifier/main_consumer.cpp b/score/mw/com/test/fields/set_and_notifier/main_consumer.cpp index 4db24f4db..20ab84ed6 100644 --- a/score/mw/com/test/fields/set_and_notifier/main_consumer.cpp +++ b/score/mw/com/test/fields/set_and_notifier/main_consumer.cpp @@ -23,7 +23,18 @@ #include #include -int main(int argc, const char** argv) +namespace +{ + +struct ConsumerConfig +{ + std::size_t num_retries; + std::chrono::milliseconds retry_backoff_time; + std::string mode; + std::string manifest; +}; + +ConsumerConfig ParseConfig(int argc, const char** argv) { constexpr auto kNumRetriesArg = "num-retries"; constexpr auto kBackoffTimeArg = "backoff-time"; @@ -64,9 +75,20 @@ int main(int argc, const char** argv) score::mw::com::test::FailTest("Consumer: missing or invalid --", kServiceInstanceManifestArg, " argument"); } - score::mw::com::runtime::InitializeRuntime(score::mw::com::runtime::RuntimeConfiguration{manifest_result.value()}); + return ConsumerConfig{num_retries_result.value(), + std::chrono::milliseconds{backoff_time_result.value()}, + mode_result.value(), + manifest_result.value()}; +} + +} // namespace + +int main(int argc, const char** argv) +{ + const auto config = ParseConfig(argc, argv); + + score::mw::com::runtime::InitializeRuntime(score::mw::com::runtime::RuntimeConfiguration{config.manifest}); - score::mw::com::test::run_consumer( - num_retries_result.value(), std::chrono::milliseconds{backoff_time_result.value()}, mode_result.value()); + score::mw::com::test::run_consumer(config.num_retries, config.retry_backoff_time, config.mode); return EXIT_SUCCESS; } diff --git a/score/mw/com/test/fields/set_and_notifier/main_provider.cpp b/score/mw/com/test/fields/set_and_notifier/main_provider.cpp index 456108489..d5bb0931b 100644 --- a/score/mw/com/test/fields/set_and_notifier/main_provider.cpp +++ b/score/mw/com/test/fields/set_and_notifier/main_provider.cpp @@ -23,7 +23,16 @@ #include #include -int main(int argc, const char** argv) +namespace +{ + +struct ProviderConfig +{ + std::string mode; + std::string manifest; +}; + +ProviderConfig ParseConfig(int argc, const char** argv) { constexpr auto kModeArg = "mode"; constexpr auto kServiceInstanceManifestArg = "service-instance-manifest"; @@ -48,7 +57,16 @@ int main(int argc, const char** argv) score::mw::com::test::FailTest("Provider: missing or invalid --", kServiceInstanceManifestArg, " argument"); } - score::mw::com::runtime::InitializeRuntime(score::mw::com::runtime::RuntimeConfiguration{manifest_result.value()}); + return ProviderConfig{mode_result.value(), manifest_result.value()}; +} + +} // namespace + +int main(int argc, const char** argv) +{ + const auto config = ParseConfig(argc, argv); + + score::mw::com::runtime::InitializeRuntime(score::mw::com::runtime::RuntimeConfiguration{config.manifest}); score::cpp::stop_source stop_source{}; const bool sig_term_handler_setup_success = score::mw::com::SetupStopTokenSigTermHandler(stop_source); @@ -57,8 +75,6 @@ int main(int argc, const char** argv) std::cerr << "Unable to set signal handler for SIGINT and/or SIGTERM, cautiously continuing\n"; } - const auto& mode = mode_result.value(); - - score::mw::com::test::run_provider(stop_source.get_token(), mode); + score::mw::com::test::run_provider(stop_source.get_token(), config.mode); return EXIT_SUCCESS; } From 7ad6bc0dcb0bbf7020bb3290f61e8e1ba4fdbe9f Mon Sep 17 00:00:00 2001 From: sahithinukala Date: Mon, 15 Jun 2026 23:18:33 +0530 Subject: [PATCH 10/13] mw/com: add field interface types and test resources for set_and_notifier --- .../initial_only_field_mw_com_config.json | 47 +++++++++++++++++++ .../config/mw_com_config.json | 4 +- .../fields_test_resources/field_consumer.cpp | 18 +++---- .../fields_test_resources/field_provider.cpp | 12 +++-- .../initial_only_field.cpp | 14 ++++++ .../initial_only_field.h | 37 +++++++++++++++ .../set_enabled_field.cpp | 14 ++++++ .../fields_test_resources/set_enabled_field.h | 37 +++++++++++++++ .../fields_test_resources/test_constants.cpp | 14 ++++++ 9 files changed, 179 insertions(+), 18 deletions(-) create mode 100644 score/mw/com/test/fields/set_and_notifier/config/initial_only_field_mw_com_config.json create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.cpp create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.h create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_field.cpp create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_field.h create mode 100644 score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.cpp diff --git a/score/mw/com/test/fields/set_and_notifier/config/initial_only_field_mw_com_config.json b/score/mw/com/test/fields/set_and_notifier/config/initial_only_field_mw_com_config.json new file mode 100644 index 000000000..d93820845 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/config/initial_only_field_mw_com_config.json @@ -0,0 +1,47 @@ +{ + "serviceTypes": [ + { + "serviceTypeName": "/score/mw/com/test/fields/set_and_notifier", + "version": { + "major": 1, + "minor": 0 + }, + "bindings": [ + { + "binding": "SHM", + "serviceId": 3427, + "fields": [ + { + "fieldName": "initial_only_field", + "fieldId": 1 + } + ] + } + ] + } + ], + "serviceInstances": [ + { + "instanceSpecifier": "test/fields/set_and_notifier", + "serviceTypeName": "/score/mw/com/test/fields/set_and_notifier", + "version": { + "major": 1, + "minor": 0 + }, + "instances": [ + { + "instanceId": 1023, + "asil-level": "QM", + "binding": "SHM", + "fields": [ + { + "fieldName": "initial_only_field", + "maxSubscribers": 1, + "numberOfSampleSlots": 1 + } + ] + } + ] + } + ] +} diff --git a/score/mw/com/test/fields/set_and_notifier/config/mw_com_config.json b/score/mw/com/test/fields/set_and_notifier/config/mw_com_config.json index 60df3e6a9..766a20bb2 100644 --- a/score/mw/com/test/fields/set_and_notifier/config/mw_com_config.json +++ b/score/mw/com/test/fields/set_and_notifier/config/mw_com_config.json @@ -12,7 +12,7 @@ "serviceId": 3428, "fields": [ { - "fieldName": "test_field", + "fieldName": "set_enabled_field", "fieldId": 1, "Set": true } @@ -36,7 +36,7 @@ "binding": "SHM", "fields": [ { - "fieldName": "test_field", + "fieldName": "set_enabled_field", "maxSubscribers": 1, "numberOfSampleSlots": 1 } diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp index 8bcaaa30d..3dbd9b1ec 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp @@ -40,6 +40,10 @@ constexpr auto kMaxNumSamples{1U}; const std::string kInterprocessNotificationShmPath{"/fields_set_and_notifier_interprocess_notification"}; const std::string kNotifierConsumerReadyShmPath{"/fields_notifier_consumer_ready"}; +// InstanceSpecifier::Create can only fail if the provided string is invalid. +// Verified once here; all test functions reuse this constant. +const InstanceSpecifier kInstanceSpecifier = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}).value(); + template bool WaitForSubscription(FieldType& field, std::size_t retries, const std::chrono::milliseconds retry_backoff_time) { @@ -170,13 +174,8 @@ void run_notifier_consumer(const std::size_t num_retries, const std::chrono::mil // Step 1. Find service and create proxy std::cout << "\nConsumer: Step 1" << std::endl; - auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); - if (!instance_specifier_result.has_value()) - { - FailTest("Consumer: Unable to create instance specifier"); - } ProxyContainer proxy_container{}; - proxy_container.CreateProxy(std::move(instance_specifier_result).value(), "set_and_notifier"); + proxy_container.CreateProxy(kInstanceSpecifier, "set_and_notifier"); auto& proxy = proxy_container.GetProxy(); // Step 2. Subscribe to field and wait for subscription @@ -223,13 +222,8 @@ void run_set_and_notifier_consumer(const std::size_t num_retries, const std::chr // Step 1. Find service and create proxy std::cout << "\nConsumer: Step 1" << std::endl; - auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); - if (!instance_specifier_result.has_value()) - { - FailTest("Consumer: Unable to create instance specifier"); - } ProxyContainer proxy_container{}; - proxy_container.CreateProxy(std::move(instance_specifier_result).value(), "set_and_notifier"); + proxy_container.CreateProxy(kInstanceSpecifier, "set_and_notifier"); auto& proxy = proxy_container.GetProxy(); // Step 2. Subscribe to field and wait for subscription diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp index ddb44a813..a3129ebc2 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp @@ -33,6 +33,10 @@ namespace const std::string kInterprocessNotificationShmPath{"/fields_set_and_notifier_interprocess_notification"}; const std::string kNotifierConsumerReadyShmPath{"/fields_notifier_consumer_ready"}; +// InstanceSpecifier::Create can only fail if the provided string is invalid. +// Verified once here; all test functions reuse this constant. +const InstanceSpecifier kInstanceSpecifier = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}).value(); + void run_notifier_provider(const score::cpp::stop_token& stop_token) { auto consumer_ready_synchronizer_result = ProcessSynchronizer::Create(kNotifierConsumerReadyShmPath); @@ -56,7 +60,7 @@ void run_notifier_provider(const score::cpp::stop_token& stop_token) auto& service = skeleton_container.GetSkeleton(); { - const auto update_result = service.test_field.Update(kInitialValue); + const auto update_result = service.initial_only_field.Update(kInitialValue); if (!update_result.has_value()) { FailTest("Provider: Unable to update initial field value: ", update_result.error()); @@ -73,7 +77,7 @@ void run_notifier_provider(const score::cpp::stop_token& stop_token) } { - const auto update_result = service.test_field.Update(kUpdatedValue); + const auto update_result = service.initial_only_field.Update(kUpdatedValue); if (!update_result.has_value()) { FailTest("Provider: Unable to update field with updated value: ", update_result.error()); @@ -103,7 +107,7 @@ void run_set_and_notifier_provider(const score::cpp::stop_token& stop_token) } auto& service = skeleton_container.GetSkeleton(); - const auto register_handler_result = service.test_field.RegisterSetHandler([](std::int32_t& value) noexcept { + const auto register_handler_result = service.set_enabled_field.RegisterSetHandler([](std::int32_t& value) noexcept { value = value * 2 + 1; }); if (!register_handler_result.has_value()) @@ -111,7 +115,7 @@ void run_set_and_notifier_provider(const score::cpp::stop_token& stop_token) FailTest("Provider: Unable to register set handler: ", register_handler_result.error()); } - const auto update_result = service.test_field.Update(kInitialValue); + const auto update_result = service.set_enabled_field.Update(kInitialValue); if (!update_result.has_value()) { FailTest("Provider: Unable to update initial field value: ", update_result.error()); diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.cpp new file mode 100644 index 000000000..8f8241526 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.cpp @@ -0,0 +1,14 @@ +/******************************************************************************* + * 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/fields/set_and_notifier/fields_test_resources/initial_only_field.h" diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.h new file mode 100644 index 000000000..6ce6d0f2a --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.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_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_INITIAL_ONLY_FIELD_H +#define SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_INITIAL_ONLY_FIELD_H + +#include "score/mw/com/types.h" +#include + +namespace score::mw::com::test +{ + +template +class InitialOnlyInterface : public T::Base +{ + public: + using T::Base::Base; + + typename T::template Field initial_only_field{*this, "initial_only_field"}; +}; + +using InitialOnlyProxy = score::mw::com::AsProxy; +using InitialOnlySkeleton = score::mw::com::AsSkeleton; + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_INITIAL_ONLY_INTERFACE_H diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_field.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_field.cpp new file mode 100644 index 000000000..f0757a93a --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_field.cpp @@ -0,0 +1,14 @@ +/******************************************************************************* + * 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/fields/set_and_notifier/fields_test_resources/set_enabled_field.h" diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_field.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_field.h new file mode 100644 index 000000000..0ef5e6988 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/set_enabled_field.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_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_SET_ENABLED_FIELD_H +#define SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_SET_ENABLED_FIELD_H + +#include "score/mw/com/types.h" +#include + +namespace score::mw::com::test +{ + +template +class SetEnabledInterface : public T::Base +{ + public: + using T::Base::Base; + + typename T::template Field set_enabled_field{*this, "set_enabled_field"}; +}; + +using SetEnabledProxy = score::mw::com::AsProxy; +using SetEnabledSkeleton = score::mw::com::AsSkeleton; + +} // namespace score::mw::com::test + +#endif // SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_SET_ENABLED_FIELD_H diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.cpp new file mode 100644 index 000000000..4f33318f7 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_constants.cpp @@ -0,0 +1,14 @@ +/******************************************************************************* + * 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/fields/set_and_notifier/fields_test_resources/test_constants.h" From 59e1339ca7945fad9857053cf9bb65f32a70198b Mon Sep 17 00:00:00 2001 From: sahithinukala Date: Tue, 16 Jun 2026 11:36:05 +0530 Subject: [PATCH 11/13] mw/com: fix race condition in notifier consumer test Register the receive handler for kUpdatedValue before notifying the provider to ensure the LoLa notification is never missed. LoLa notifications are fire-and-forget. If the provider called Update(kUpdatedValue) before the consumer registered its receive handler, the OS notification fired to zero handlers and was lost, causing WaitForValue to time out after 1000ms. --- .../fields_test_resources/field_consumer.cpp | 84 ++++++++++++++++--- .../fields_test_resources/field_provider.cpp | 24 ++---- .../initial_only_field.h | 2 +- 3 files changed, 78 insertions(+), 32 deletions(-) diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp index 3dbd9b1ec..083593a22 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp @@ -168,7 +168,8 @@ void run_notifier_consumer(const std::size_t num_retries, const std::chrono::mil { FailTest("Consumer: Could not create done ProcessSynchronizer"); } - ExitFunctionGuard done_guard{[&done_synchronizer_result]() { + ExitFunctionGuard exit_guard{[&consumer_ready_synchronizer_result, &done_synchronizer_result]() { + consumer_ready_synchronizer_result->Notify(); done_synchronizer_result->Notify(); }}; @@ -180,28 +181,84 @@ void run_notifier_consumer(const std::size_t num_retries, const std::chrono::mil // Step 2. Subscribe to field and wait for subscription std::cout << "\nConsumer: Step 2" << std::endl; - std::ignore = proxy.test_field.Subscribe(kMaxNumSamples); - if (!WaitForSubscription(proxy.test_field, num_retries, retry_backoff_time)) + std::ignore = proxy.initial_only_field.Subscribe(kMaxNumSamples); + if (!WaitForSubscription(proxy.initial_only_field, num_retries, retry_backoff_time)) { FailTest("Consumer: Subscription failed in notifier scenario"); } // Step 3. Verify initial value received std::cout << "\nConsumer: Step 3" << std::endl; - const bool initial_value_received = WaitForValue(proxy.test_field, kInitialValue, num_retries, retry_backoff_time); + const bool initial_value_received = + WaitForValue(proxy.initial_only_field, kInitialValue, num_retries, retry_backoff_time); if (!initial_value_received) { FailTest("Consumer: Did not receive expected initial value ", kInitialValue, " in notifier scenario"); } - // Step 4. Notify provider that consumer is ready + // Step 4. Register receive handler for updated value before notifying provider, to avoid missing the + // notification if the provider calls Update() before the handler is registered. std::cout << "\nConsumer: Step 4" << std::endl; + struct SyncState + { + std::mutex mutex{}; + std::condition_variable cv{}; + bool value_received{false}; + }; + SyncState sync_state; + + const auto handler_result = proxy.initial_only_field.SetReceiveHandler([&proxy, &sync_state]() noexcept { + score::cpp::optional received; + std::ignore = proxy.initial_only_field.GetNewSamples( + [&received](const auto& sample_ptr) noexcept { + received = *sample_ptr; + }, + kMaxNumSamples); + if (received.has_value() && received.value() == kUpdatedValue) + { + { + std::lock_guard lock{sync_state.mutex}; + sync_state.value_received = true; + } + sync_state.cv.notify_one(); + } + }); + if (!handler_result.has_value()) + { + FailTest("Consumer: Could not register receive handler for updated value in notifier scenario"); + } + consumer_ready_synchronizer.Notify(); // Step 5. Verify updated value received after provider publishes update std::cout << "\nConsumer: Step 5" << std::endl; - const bool updated_value_received = WaitForValue(proxy.test_field, kUpdatedValue, num_retries, retry_backoff_time); - proxy.test_field.Unsubscribe(); + + // Handle race: value may already be in the buffer before Notify() returned + bool updated_value_received = false; + { + score::cpp::optional existing; + std::ignore = proxy.initial_only_field.GetNewSamples( + [&existing](const auto& sample_ptr) noexcept { + existing = *sample_ptr; + }, + kMaxNumSamples); + if (existing.has_value() && existing.value() == kUpdatedValue) + { + updated_value_received = true; + } + } + + if (!updated_value_received) + { + const auto total_wait_time = retry_backoff_time * num_retries; + std::unique_lock lock{sync_state.mutex}; + updated_value_received = sync_state.cv.wait_for(lock, total_wait_time, [&sync_state] { + return sync_state.value_received; + }); + } + + std::ignore = proxy.initial_only_field.UnsetReceiveHandler(); + proxy.initial_only_field.Unsubscribe(); if (!updated_value_received) { @@ -228,15 +285,16 @@ void run_set_and_notifier_consumer(const std::size_t num_retries, const std::chr // Step 2. Subscribe to field and wait for subscription std::cout << "\nConsumer: Step 2" << std::endl; - std::ignore = proxy.test_field.Subscribe(kMaxNumSamples); - if (!WaitForSubscription(proxy.test_field, num_retries, retry_backoff_time)) + std::ignore = proxy.set_enabled_field.Subscribe(kMaxNumSamples); + if (!WaitForSubscription(proxy.set_enabled_field, num_retries, retry_backoff_time)) { FailTest("Consumer: Subscription failed in set scenario"); } // Step 3. Verify initial value received std::cout << "\nConsumer: Step 3" << std::endl; - const bool initial_value_received = WaitForValue(proxy.test_field, kInitialValue, num_retries, retry_backoff_time); + const bool initial_value_received = + WaitForValue(proxy.set_enabled_field, kInitialValue, num_retries, retry_backoff_time); if (!initial_value_received) { FailTest("Consumer: Did not receive initial value ", kInitialValue, " in set scenario"); @@ -244,7 +302,7 @@ void run_set_and_notifier_consumer(const std::size_t num_retries, const std::chr // Step 4. Set new field value and verify accepted value matches expected transformed value std::cout << "\nConsumer: Step 4" << std::endl; - const auto set_result = proxy.test_field.Set(kSetRequestValue); + const auto set_result = proxy.set_enabled_field.Set(kSetRequestValue); if (!set_result.has_value()) { FailTest("Consumer: Set call failed: ", set_result.error()); @@ -259,8 +317,8 @@ void run_set_and_notifier_consumer(const std::size_t num_retries, const std::chr // Step 5. Verify transformed value received via field notification std::cout << "\nConsumer: Step 5" << std::endl; const bool transformed_value_received = - WaitForValue(proxy.test_field, kSetTransformedValue, num_retries, retry_backoff_time); - proxy.test_field.Unsubscribe(); + WaitForValue(proxy.set_enabled_field, kSetTransformedValue, num_retries, retry_backoff_time); + proxy.set_enabled_field.Unsubscribe(); if (!transformed_value_received) { diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp index a3129ebc2..0b1d5efeb 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp @@ -51,11 +51,8 @@ void run_notifier_provider(const score::cpp::stop_token& stop_token) FailTest("Provider: Could not create done ProcessSynchronizer"); } - SkeletonContainer skeleton_container{kInstanceSpecifierString}; - if (!skeleton_container.CreateSkeleton()) - { - FailTest("Provider: Unable to construct InitialOnlySkeleton"); - } + SkeletonContainer skeleton_container{}; + skeleton_container.CreateSkeleton(kInstanceSpecifier, "set_and_notifier"); auto& service = skeleton_container.GetSkeleton(); @@ -66,10 +63,7 @@ void run_notifier_provider(const score::cpp::stop_token& stop_token) FailTest("Provider: Unable to update initial field value: ", update_result.error()); } } - if (!skeleton_container.OfferService()) - { - FailTest("Provider: Unable to offer InitialOnlySkeleton"); - } + skeleton_container.OfferService("set_and_notifier"); if (!consumer_ready_synchronizer_result->WaitWithAbort(stop_token)) { @@ -100,11 +94,8 @@ void run_set_and_notifier_provider(const score::cpp::stop_token& stop_token) FailTest("Provider: Could not create ProcessSynchronizer"); } - SkeletonContainer skeleton_container{kInstanceSpecifierString}; - if (!skeleton_container.CreateSkeleton()) - { - FailTest("Provider: Unable to construct SetEnabledSkeleton"); - } + SkeletonContainer skeleton_container{}; + skeleton_container.CreateSkeleton(kInstanceSpecifier, "set_and_notifier"); auto& service = skeleton_container.GetSkeleton(); const auto register_handler_result = service.set_enabled_field.RegisterSetHandler([](std::int32_t& value) noexcept { @@ -121,10 +112,7 @@ void run_set_and_notifier_provider(const score::cpp::stop_token& stop_token) FailTest("Provider: Unable to update initial field value: ", update_result.error()); } - if (!skeleton_container.OfferService()) - { - FailTest("Provider: Unable to offer SetEnabledSkeleton"); - } + skeleton_container.OfferService("set_and_notifier"); if (!process_synchronizer_result->WaitWithAbort(stop_token)) { diff --git a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.h b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.h index 6ce6d0f2a..764308381 100644 --- a/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.h +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/initial_only_field.h @@ -34,4 +34,4 @@ using InitialOnlySkeleton = score::mw::com::AsSkeleton; } // namespace score::mw::com::test -#endif // SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_INITIAL_ONLY_INTERFACE_H +#endif // SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_INITIAL_ONLY_FIELD_H From 6f9095e1ac12c60a534f8c4b21f9530dc040abe7 Mon Sep 17 00:00:00 2001 From: sahithinukala Date: Fri, 19 Jun 2026 19:12:49 +0530 Subject: [PATCH 12/13] mw/com: drop files already merged via PR #571 --- score/mw/com/test/common_test_resources/BUILD | 16 ---------------- .../test/methods/basic_acceptance_test/BUILD | 4 ++-- .../methods/basic_acceptance_test/consumer.cpp | 2 +- .../methods/basic_acceptance_test/provider.cpp | 2 +- .../test/methods/methods_test_resources/BUILD | 18 ++++++++++++++++++ .../methods/non_trivial_constructors/BUILD | 4 ++-- .../non_trivial_constructors/consumer.cpp | 2 +- .../non_trivial_constructors/provider.cpp | 2 +- 8 files changed, 26 insertions(+), 24 deletions(-) diff --git a/score/mw/com/test/common_test_resources/BUILD b/score/mw/com/test/common_test_resources/BUILD index 42829b518..8b96b95b8 100644 --- a/score/mw/com/test/common_test_resources/BUILD +++ b/score/mw/com/test/common_test_resources/BUILD @@ -396,19 +396,3 @@ cc_library( "@score_baselibs//score/result", ], ) - -cc_library( - name = "process_synchronizer", - srcs = ["process_synchronizer.cpp"], - hdrs = ["process_synchronizer.h"], - features = COMPILER_WARNING_FEATURES, - visibility = ["//score/mw/com/test:__subpackages__"], - deps = [ - "//score/mw/com/test/common_test_resources:fail_test", - "//score/mw/com/test/common_test_resources:shared_memory_object_creator", - "//score/mw/com/test/common_test_resources:shared_memory_object_guard", - "@score_baselibs//score/mw/log", - "@score_baselibs//score/os/utils/interprocess:interprocess_notification", - "@score_baselibs//score/result", - ], -) diff --git a/score/mw/com/test/methods/basic_acceptance_test/BUILD b/score/mw/com/test/methods/basic_acceptance_test/BUILD index 34b85eb74..0c6a46966 100644 --- a/score/mw/com/test/methods/basic_acceptance_test/BUILD +++ b/score/mw/com/test/methods/basic_acceptance_test/BUILD @@ -41,8 +41,8 @@ cc_library( implementation_deps = [ ":test_method_datatype", "//score/mw/com", - "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/common_test_resources:proxy_container", + "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", ], ) @@ -54,8 +54,8 @@ cc_library( implementation_deps = [ ":test_method_datatype", "//score/mw/com", - "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/common_test_resources:skeleton_container", + "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", ], deps = [ "@score_baselibs//score/language/futurecpp", diff --git a/score/mw/com/test/methods/basic_acceptance_test/consumer.cpp b/score/mw/com/test/methods/basic_acceptance_test/consumer.cpp index d4a755875..3fd59e604 100644 --- a/score/mw/com/test/methods/basic_acceptance_test/consumer.cpp +++ b/score/mw/com/test/methods/basic_acceptance_test/consumer.cpp @@ -13,9 +13,9 @@ #include "score/mw/com/test/methods/basic_acceptance_test/consumer.h" #include "score/mw/com/test/common_test_resources/fail_test.h" -#include "score/mw/com/test/common_test_resources/process_synchronizer.h" #include "score/mw/com/test/common_test_resources/proxy_container.h" #include "score/mw/com/test/methods/basic_acceptance_test/test_method_datatype.h" +#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include "score/mw/com/types.h" #include diff --git a/score/mw/com/test/methods/basic_acceptance_test/provider.cpp b/score/mw/com/test/methods/basic_acceptance_test/provider.cpp index dd2f8c989..052ca6943 100644 --- a/score/mw/com/test/methods/basic_acceptance_test/provider.cpp +++ b/score/mw/com/test/methods/basic_acceptance_test/provider.cpp @@ -13,9 +13,9 @@ #include "score/mw/com/test/methods/basic_acceptance_test/provider.h" #include "score/mw/com/test/common_test_resources/fail_test.h" -#include "score/mw/com/test/common_test_resources/process_synchronizer.h" #include "score/mw/com/test/common_test_resources/skeleton_container.h" #include "score/mw/com/test/methods/basic_acceptance_test/test_method_datatype.h" +#include "score/mw/com/test/methods/methods_test_resources/process_synchronizer.h" #include "score/mw/com/types.h" #include "score/result/result.h" diff --git a/score/mw/com/test/methods/methods_test_resources/BUILD b/score/mw/com/test/methods/methods_test_resources/BUILD index 37a18ab16..5859773a4 100644 --- a/score/mw/com/test/methods/methods_test_resources/BUILD +++ b/score/mw/com/test/methods/methods_test_resources/BUILD @@ -48,3 +48,21 @@ cc_library( "@score_baselibs//score/mw/log", ], ) + +cc_library( + name = "process_synchronizer", + srcs = ["process_synchronizer.cpp"], + hdrs = ["process_synchronizer.h"], + features = COMPILER_WARNING_FEATURES, + visibility = [ + "//score/mw/com/test/methods:__subpackages__", + ], + deps = [ + "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:shared_memory_object_creator", + "//score/mw/com/test/common_test_resources:shared_memory_object_guard", + "@score_baselibs//score/mw/log", + "@score_baselibs//score/os/utils/interprocess:interprocess_notification", + "@score_baselibs//score/result", + ], +) diff --git a/score/mw/com/test/methods/non_trivial_constructors/BUILD b/score/mw/com/test/methods/non_trivial_constructors/BUILD index 4b7469c52..626c5a96c 100644 --- a/score/mw/com/test/methods/non_trivial_constructors/BUILD +++ b/score/mw/com/test/methods/non_trivial_constructors/BUILD @@ -40,8 +40,8 @@ cc_library( implementation_deps = [ ":test_method_datatype", "//score/mw/com", - "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/common_test_resources:proxy_container", + "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", ], deps = [ "@score_baselibs//score/language/futurecpp", @@ -56,8 +56,8 @@ cc_library( deps = [ ":test_method_datatype", "//score/mw/com", - "//score/mw/com/test/common_test_resources:process_synchronizer", "//score/mw/com/test/common_test_resources:skeleton_container", + "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", ], ) diff --git a/score/mw/com/test/methods/non_trivial_constructors/consumer.cpp b/score/mw/com/test/methods/non_trivial_constructors/consumer.cpp index 0bbe688f3..3304d4541 100644 --- a/score/mw/com/test/methods/non_trivial_constructors/consumer.cpp +++ b/score/mw/com/test/methods/non_trivial_constructors/consumer.cpp @@ -13,8 +13,8 @@ #include "score/mw/com/test/methods/non_trivial_constructors/consumer.h" #include "score/mw/com/test/common_test_resources/fail_test.h" -#include "score/mw/com/test/common_test_resources/process_synchronizer.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/methods/non_trivial_constructors/test_method_datatype.h" #include "score/mw/com/types.h" diff --git a/score/mw/com/test/methods/non_trivial_constructors/provider.cpp b/score/mw/com/test/methods/non_trivial_constructors/provider.cpp index ff4c51569..d326e2552 100644 --- a/score/mw/com/test/methods/non_trivial_constructors/provider.cpp +++ b/score/mw/com/test/methods/non_trivial_constructors/provider.cpp @@ -13,8 +13,8 @@ #include "score/mw/com/test/methods/non_trivial_constructors/provider.h" #include "score/mw/com/test/common_test_resources/fail_test.h" -#include "score/mw/com/test/common_test_resources/process_synchronizer.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/methods/non_trivial_constructors/test_method_datatype.h" #include "score/mw/com/types.h" From 2b5d4e4a813b94d7fc303150fe592afe68368a5e Mon Sep 17 00:00:00 2001 From: sahithinukala Date: Fri, 19 Jun 2026 19:29:26 +0530 Subject: [PATCH 13/13] mw/com: restore process_synchronizer target in common test resources --- score/mw/com/test/common_test_resources/BUILD | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/score/mw/com/test/common_test_resources/BUILD b/score/mw/com/test/common_test_resources/BUILD index 8b96b95b8..73ffefe8f 100644 --- a/score/mw/com/test/common_test_resources/BUILD +++ b/score/mw/com/test/common_test_resources/BUILD @@ -137,6 +137,22 @@ cc_library( ], ) +cc_library( + name = "process_synchronizer", + srcs = ["process_synchronizer.cpp"], + hdrs = ["process_synchronizer.h"], + features = COMPILER_WARNING_FEATURES, + visibility = ["//score/mw/com/test:__subpackages__"], + deps = [ + "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:shared_memory_object_creator", + "//score/mw/com/test/common_test_resources:shared_memory_object_guard", + "@score_baselibs//score/mw/log", + "@score_baselibs//score/os/utils/interprocess:interprocess_notification", + "@score_baselibs//score/result", + ], +) + cc_library( name = "stop_token_sig_term_handler", srcs = [