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 0db5523e7..48b1290a5 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 @@ -68,10 +69,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; diff --git a/score/mw/com/test/common_test_resources/BUILD b/score/mw/com/test/common_test_resources/BUILD index 3ceffa96f..361b6720a 100644 --- a/score/mw/com/test/common_test_resources/BUILD +++ b/score/mw/com/test/common_test_resources/BUILD @@ -15,6 +15,28 @@ load("@rules_cc//cc:defs.bzl", "cc_library") load("@score_baselibs//score/language/safecpp:toolchain_features.bzl", "COMPILER_WARNING_FEATURES") load("//quality/unit_testing:unit_testing.bzl", "cc_unit_test") +cc_library( + name = "proxy_container", + srcs = ["proxy_container.cpp"], + hdrs = ["proxy_container.h"], + features = COMPILER_WARNING_FEATURES, + visibility = ["//score/mw/com/test:__subpackages__"], + deps = [ + "//score/mw/com", + ], +) + +cc_library( + name = "skeleton_container", + srcs = ["skeleton_container.cpp"], + hdrs = ["skeleton_container.h"], + features = COMPILER_WARNING_FEATURES, + visibility = ["//score/mw/com/test:__subpackages__"], + deps = [ + "//score/mw/com", + ], +) + cc_library( name = "bigdata_type", srcs = [ diff --git a/score/mw/com/test/methods/methods_test_resources/proxy_container.cpp b/score/mw/com/test/common_test_resources/proxy_container.cpp similarity index 88% rename from score/mw/com/test/methods/methods_test_resources/proxy_container.cpp rename to score/mw/com/test/common_test_resources/proxy_container.cpp index 85019bfaa..584767aed 100644 --- a/score/mw/com/test/methods/methods_test_resources/proxy_container.cpp +++ b/score/mw/com/test/common_test_resources/proxy_container.cpp @@ -10,4 +10,4 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -#include "score/mw/com/test/methods/methods_test_resources/proxy_container.h" +#include "score/mw/com/test/common_test_resources/proxy_container.h" diff --git a/score/mw/com/test/methods/methods_test_resources/proxy_container.h b/score/mw/com/test/common_test_resources/proxy_container.h similarity index 100% rename from score/mw/com/test/methods/methods_test_resources/proxy_container.h rename to score/mw/com/test/common_test_resources/proxy_container.h diff --git a/score/mw/com/test/methods/methods_test_resources/skeleton_container.cpp b/score/mw/com/test/common_test_resources/skeleton_container.cpp similarity index 87% rename from score/mw/com/test/methods/methods_test_resources/skeleton_container.cpp rename to score/mw/com/test/common_test_resources/skeleton_container.cpp index 70f7eca86..e0a4e3508 100644 --- a/score/mw/com/test/methods/methods_test_resources/skeleton_container.cpp +++ b/score/mw/com/test/common_test_resources/skeleton_container.cpp @@ -10,4 +10,4 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -#include "score/mw/com/test/methods/methods_test_resources/skeleton_container.h" +#include "score/mw/com/test/common_test_resources/skeleton_container.h" diff --git a/score/mw/com/test/methods/methods_test_resources/skeleton_container.h b/score/mw/com/test/common_test_resources/skeleton_container.h similarity index 100% rename from score/mw/com/test/methods/methods_test_resources/skeleton_container.h rename to score/mw/com/test/common_test_resources/skeleton_container.h diff --git a/score/mw/com/test/field_initial_value/service.cpp b/score/mw/com/test/field_initial_value/service.cpp deleted file mode 100644 index b17710b43..000000000 --- a/score/mw/com/test/field_initial_value/service.cpp +++ /dev/null @@ -1,88 +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/field_initial_value/test_datatype.h" - -#include - -#include -#include -#include - -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}); - 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 = TestDataSkeleton::Create(std::move(instance_specifier)); - if (!service_result.has_value()) - { - std::cerr << "Unable to construct TestDataSkeleton: " << service_result.error() << ", bailing!\n"; - return -4; - } - - TestDataSkeleton& lola_service{service_result.value()}; - - 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; - } - 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; - } - - while (!stop_token.stop_requested()) - { - std::this_thread::sleep_for(cycle_time); - } - - lola_service.StopOfferService(); - - return 0; -} - -} // namespace - -} // namespace score::mw::com::test - -int main(int argc, const char** argv) -{ - using Parameters = score::mw::com::test::SctfTestRunner::RunParameters::Parameters; - - 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(); - - return score::mw::com::test::run_service(cycle_time, stop_token); -} diff --git a/score/mw/com/test/fields/BUILD b/score/mw/com/test/fields/BUILD new file mode 100644 index 000000000..ca5de742e --- /dev/null +++ b/score/mw/com/test/fields/BUILD @@ -0,0 +1,12 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* diff --git a/score/mw/com/test/field_initial_value/BUILD b/score/mw/com/test/fields/field_initial_value/BUILD similarity index 79% rename from score/mw/com/test/field_initial_value/BUILD rename to score/mw/com/test/fields/field_initial_value/BUILD index e68fbbd18..d32a1198b 100644 --- a/score/mw/com/test/field_initial_value/BUILD +++ b/score/mw/com/test/fields/field_initial_value/BUILD @@ -40,11 +40,13 @@ 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", - "//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", ], ) @@ -56,11 +58,12 @@ 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", "//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", ], ) @@ -75,7 +78,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 +92,6 @@ 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__", ], ) 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 87% 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..9a7a2862b 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,8 @@ *******************************************************************************/ #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/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; } @@ -122,7 +134,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 96% 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 index e0dd9c991..1bf5b0f00 100644 --- 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 @@ -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 new file mode 100644 index 000000000..56d613853 --- /dev/null +++ b/score/mw/com/test/fields/field_initial_value/service.cpp @@ -0,0 +1,94 @@ +/******************************************************************************* + * 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/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 + +namespace score::mw::com::test +{ + +namespace +{ + +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()) + { + 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()) + { + FailTest("Service: Unable to construct TestDataSkeleton: ", service_result.error()); + } + + TestDataSkeleton& lola_service{service_result.value()}; + + const auto update_result = lola_service.test_field.Update(kTestValue); + if (!update_result.has_value()) + { + FailTest("Service: Unable to update test field: ", update_result.error()); + } + const auto offer_result = lola_service.OfferService(); + if (!offer_result.has_value()) + { + FailTest("Service: Unable to offer service for TestDataSkeleton: ", offer_result.error()); + } + + if (!process_synchronizer_result->WaitWithAbort(stop_token)) + { + FailTest("Service: WaitWithAbort was stopped by stop_token instead of notification"); + } + + lola_service.StopOfferService(); +} + +} // namespace + +} // namespace score::mw::com::test + +int main(int argc, const char** argv) +{ + score::mw::com::runtime::InitializeRuntime(argc, argv); + + score::cpp::stop_source stop_source{}; + const bool sig_term_handler_setup_success = score::mw::com::SetupStopTokenSigTermHandler(stop_source); + if (!sig_term_handler_setup_success) + { + std::cerr << "Unable to set signal handler for SIGINT and/or SIGTERM, cautiously continuing\n"; + } + + score::mw::com::test::run_service(stop_source.get_token()); + return EXIT_SUCCESS; +} 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 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..6a0b0840b --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/BUILD @@ -0,0 +1,87 @@ +# ******************************************************************************* +# 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 = "provider", + srcs = ["provider.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: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 = "consumer", + srcs = ["consumer.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: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 = "provider-pkg", + app_name = "MainProviderApp", + bin = [":provider"], + 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 = "consumer-pkg", + app_name = "MainConsumerApp", + bin = [":consumer"], + 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__", + ], +) 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..a49f8cded --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/config/logging.json @@ -0,0 +1,7 @@ +{ + "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/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/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 new file mode 100644 index 000000000..36de65c78 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/BUILD @@ -0,0 +1,67 @@ +# ******************************************************************************* +# 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 = [ + "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__", + ], + 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", + "//score/mw/com/test/common_test_resources:fail_test", + "//score/mw/com/test/common_test_resources:proxy_container", + "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", + ], +) + +cc_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", + "//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 new file mode 100644 index 000000000..378eae826 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_consumer.cpp @@ -0,0 +1,281 @@ +/******************************************************************************* + * 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/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 + +namespace score::mw::com::test +{ +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) +{ + 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); + } +} + +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()) + { + FailTest("Consumer: Could not create ProcessSynchronizer"); + } + auto& process_synchronizer = process_synchronizer_result.value(); + + auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); + if (!instance_specifier_result.has_value()) + { + NotifyAndFail(process_synchronizer, "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 InitialOnlyProxy"); + } + + auto& proxy = proxy_container.GetProxy(); + 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"); + } + + const bool initial_value_received = PollForValue(proxy.test_field, kInitialValue, num_retries, retry_backoff_time); + proxy.test_field.Unsubscribe(); + + if (!initial_value_received) + { + NotifyAndFail(process_synchronizer, + "Consumer: Did not receive expected initial value ", + kInitialValue, + " in notifier scenario"); + } + + process_synchronizer.Notify(); +} + +void run_set_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(); + + auto instance_specifier_result = InstanceSpecifier::Create(std::string{kInstanceSpecifierString}); + if (!instance_specifier_result.has_value()) + { + NotifyAndFail(process_synchronizer, "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"); + } + + auto& proxy = proxy_container.GetProxy(); + 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"); + } + + const bool initial_value_received = PollForValue(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"); + } + + 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)) + { + NotifyAndFail(process_synchronizer, "Consumer: Set call failed: ", invalid_set_error); + } + + if (accepted_value != kSetAcceptedValue) + { + NotifyAndFail(process_synchronizer, + "Consumer: Set accepted value mismatch. Expected ", + kSetAcceptedValue, + " but got ", + accepted_value); + } + + const bool clamped_value_received = + PollForValue(proxy.test_field, kSetAcceptedValue, num_retries, retry_backoff_time); + proxy.test_field.Unsubscribe(); + + if (!clamped_value_received) + { + NotifyAndFail( + process_synchronizer, "Consumer: Did not receive clamped value ", kSetAcceptedValue, " 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) +{ + if (mode == "notifier") + { + run_notifier_consumer(num_retries, retry_backoff_time); + return; + } + if (mode == "set") + { + run_set_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 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..0aa22fd85 --- /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 +{ + +void run_consumer(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..9f631366b --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.cpp @@ -0,0 +1,136 @@ +/******************************************************************************* + * 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/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 + +namespace score::mw::com::test +{ +namespace +{ + +const std::string kInterprocessNotificationShmPath{"/fields_set_and_notifier_interprocess_notification"}; + +void run_notifier_provider(const score::cpp::stop_token& stop_token) +{ + auto process_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); + if (!process_synchronizer_result.has_value()) + { + FailTest("Provider: Could not create ProcessSynchronizer"); + } + + SkeletonContainer skeleton_container{kInstanceSpecifierString}; + if (!skeleton_container.CreateSkeleton()) + { + FailTest("Provider: Unable to construct InitialOnlySkeleton"); + } + + 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()); + } + if (!skeleton_container.OfferService()) + { + FailTest("Provider: Unable to offer InitialOnlySkeleton"); + } + + if (!process_synchronizer_result->WaitWithAbort(stop_token)) + { + FailTest("Provider: WaitWithAbort was stopped by stop_token instead of notification"); + } + + service.StopOfferService(); +} + +void run_set_provider(const score::cpp::stop_token& stop_token) +{ + auto process_synchronizer_result = ProcessSynchronizer::Create(kInterprocessNotificationShmPath); + if (!process_synchronizer_result.has_value()) + { + FailTest("Provider: Could not create ProcessSynchronizer"); + } + + SkeletonContainer skeleton_container{kInstanceSpecifierString}; + if (!skeleton_container.CreateSkeleton()) + { + FailTest("Provider: Unable to construct SetEnabledSkeleton"); + } + + 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; + } + }); + if (!register_handler_result.has_value()) + { + 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()) + { + FailTest("Provider: Unable to update initial field value: ", update_result.error()); + } + + if (!skeleton_container.OfferService()) + { + FailTest("Provider: Unable to offer SetEnabledSkeleton"); + } + + if (!process_synchronizer_result->WaitWithAbort(stop_token)) + { + FailTest("Provider: WaitWithAbort was stopped by stop_token instead of notification"); + } + + service.StopOfferService(); +} + +} // namespace + +void run_provider(const score::cpp::stop_token& stop_token, const std::string& mode) +{ + if (mode == "notifier") + { + run_notifier_provider(stop_token); + return; + } + if (mode == "set") + { + run_set_provider(stop_token); + return; + } + + // 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 new file mode 100644 index 000000000..95a5dc32f --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/field_provider.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_PROVIDER_H +#define SCORE_MW_COM_TEST_FIELDS_SET_AND_NOTIFIER_FIELDS_TEST_RESOURCES_FIELD_PROVIDER_H + +#include + +#include + +namespace score::mw::com::test +{ + +void run_provider(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/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.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..e26a70eb6 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/fields_test_resources/test_datatype.h @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + *******************************************************************************/ + +#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/integration_test/BUILD b/score/mw/com/test/fields/set_and_notifier/integration_test/BUILD new file mode 100644 index 000000000..77cc6f923 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/BUILD @@ -0,0 +1,48 @@ +# ******************************************************************************* +# 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: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_set_and_notifier", + timeout = "moderate", + srcs = [ + "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_set_and_notifier.py b/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_and_notifier.py new file mode 100644 index 000000000..65574c804 --- /dev/null +++ b/score/mw/com/test/fields/set_and_notifier/integration_test/test_set_and_notifier.py @@ -0,0 +1,24 @@ +# ******************************************************************************* +# 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_set_value(target): + """Test field set exchange and accepted value propagation between provider and consumer.""" + with provider(target, "set"): + with consumer(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/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/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 87fd25de9..5587f4567 100644 --- a/score/mw/com/test/methods/methods_test_resources/BUILD +++ b/score/mw/com/test/methods/methods_test_resources/BUILD @@ -14,32 +14,6 @@ load("@rules_cc//cc:defs.bzl", "cc_library") load("@score_baselibs//score/language/safecpp:toolchain_features.bzl", "COMPILER_WARNING_FEATURES") -cc_library( - name = "proxy_container", - srcs = ["proxy_container.cpp"], - hdrs = ["proxy_container.h"], - features = COMPILER_WARNING_FEATURES, - visibility = [ - "//score/mw/com/test/methods:__subpackages__", - ], - deps = [ - "//score/mw/com", - ], -) - -cc_library( - name = "skeleton_container", - srcs = ["skeleton_container.cpp"], - hdrs = ["skeleton_container.h"], - features = COMPILER_WARNING_FEATURES, - visibility = [ - "//score/mw/com/test/methods:__subpackages__", - ], - deps = [ - "//score/mw/com", - ], -) - cc_library( name = "method_provider", srcs = ["method_provider.cpp"], @@ -69,8 +43,8 @@ cc_library( "//score/mw/com", "//score/mw/com:runtime", "//score/mw/com/test/common_test_resources:assert_handler", + "//score/mw/com/test/common_test_resources:proxy_container", "//score/mw/com/test/common_test_resources:sctf_test_runner", - "//score/mw/com/test/methods/methods_test_resources:proxy_container", "@score_baselibs//score/mw/log", ], ) @@ -81,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 = [ diff --git a/score/mw/com/test/methods/methods_test_resources/method_consumer.h b/score/mw/com/test/methods/methods_test_resources/method_consumer.h index 2ce415dd4..a0f34f8ef 100644 --- a/score/mw/com/test/methods/methods_test_resources/method_consumer.h +++ b/score/mw/com/test/methods/methods_test_resources/method_consumer.h @@ -13,7 +13,7 @@ #ifndef SCORE_MW_COM_TEST_METHODS_METHODS_TEST_RESOURCES_METHOD_CONSUMER_H #define SCORE_MW_COM_TEST_METHODS_METHODS_TEST_RESOURCES_METHOD_CONSUMER_H -#include "score/mw/com/test/methods/methods_test_resources/proxy_container.h" +#include "score/mw/com/test/common_test_resources/proxy_container.h" #include diff --git a/score/mw/com/test/methods/non_trivial_constructors/BUILD b/score/mw/com/test/methods/non_trivial_constructors/BUILD index b4e596360..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:proxy_container", "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", - "//score/mw/com/test/methods/methods_test_resources:proxy_container", ], 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:skeleton_container", "//score/mw/com/test/methods/methods_test_resources:process_synchronizer", - "//score/mw/com/test/methods/methods_test_resources:skeleton_container", ], ) 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 6f7b7e321..faf4d3564 100644 --- a/score/mw/com/test/methods/non_trivial_constructors/consumer.cpp +++ b/score/mw/com/test/methods/non_trivial_constructors/consumer.cpp @@ -12,8 +12,8 @@ ********************************************************************************/ #include "score/mw/com/test/methods/non_trivial_constructors/consumer.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/methods_test_resources/proxy_container.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 5ee46c003..d4091e2df 100644 --- a/score/mw/com/test/methods/non_trivial_constructors/provider.cpp +++ b/score/mw/com/test/methods/non_trivial_constructors/provider.cpp @@ -12,8 +12,8 @@ ********************************************************************************/ #include "score/mw/com/test/methods/non_trivial_constructors/provider.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/methods_test_resources/skeleton_container.h" #include "score/mw/com/test/methods/non_trivial_constructors/test_method_datatype.h" #include