From 391eca68ea1dbf813e024cb7c3f598147317dc0f Mon Sep 17 00:00:00 2001 From: Krishna Satish Deshkulkarni Shankaranarayana Date: Tue, 2 Jun 2026 12:01:37 +0200 Subject: [PATCH 01/10] mw/com: remove unused UniqueMethodIdentifier type method_identifier.h defines a UniqueMethodIdentifier that is not referenced by any production code. the binding dependant layer uses its own UniqueMethodIdentifier. removing a spillover from previous work. --- score/mw/com/impl/method_identifier.h | 49 --------------------------- 1 file changed, 49 deletions(-) delete mode 100644 score/mw/com/impl/method_identifier.h diff --git a/score/mw/com/impl/method_identifier.h b/score/mw/com/impl/method_identifier.h deleted file mode 100644 index 367a39dc5..000000000 --- a/score/mw/com/impl/method_identifier.h +++ /dev/null @@ -1,49 +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_IMPL_METHOD_IDENTIFIER_H -#define SCORE_MW_COM_IMPL_METHOD_IDENTIFIER_H - -#include "score/mw/com/impl/method_type.h" - -#include -#include - -namespace score::mw::com::impl -{ - -/// \brief Lookup key for a method on a Proxy/Skeleton, formed from the method name and its MethodType. -/// A field's Get, a field's Set and a regular method may share the same name the type field disambiguates them. -struct UniqueMethodIdentifier -{ - std::string_view name; - MethodType type; -}; - -inline bool operator==(const UniqueMethodIdentifier& lhs, const UniqueMethodIdentifier& rhs) noexcept -{ - return (lhs.name == rhs.name) && (lhs.type == rhs.type); -} - -inline bool operator!=(const UniqueMethodIdentifier& lhs, const UniqueMethodIdentifier& rhs) noexcept -{ - return !(lhs == rhs); -} - -inline bool operator<(const UniqueMethodIdentifier& lhs, const UniqueMethodIdentifier& rhs) noexcept -{ - return std::tie(lhs.name, lhs.type) < std::tie(rhs.name, rhs.type); -} - -} // namespace score::mw::com::impl - -#endif // SCORE_MW_COM_IMPL_METHOD_IDENTIFIER_H From 9ffcc59a5f26465b2b53ecf646cdd25240880f4f Mon Sep 17 00:00:00 2001 From: Krishna Satish Deshkulkarni Shankaranarayana Date: Wed, 3 Jun 2026 12:21:20 +0200 Subject: [PATCH 02/10] mw/com: refactor proxy event/field binding factories Add a ServiceElementType parameter to ProxyEventBindingFactory::Create to avoid code duplication --- score/mw/com/impl/generic_proxy_test.cpp | 24 ++++++++++++------- score/mw/com/impl/plumbing/BUILD | 3 ++- .../plumbing/i_proxy_event_binding_factory.h | 8 +++++-- .../plumbing/proxy_event_binding_factory.h | 15 ++++++++---- .../proxy_event_binding_factory_impl.cpp | 5 ++-- .../proxy_event_binding_factory_impl.h | 11 +++++---- .../proxy_event_binding_factory_mock.h | 5 ++-- .../proxy_field_binding_factory_impl.h | 14 ++--------- .../tracing/test/proxy_event_tracing_test.cpp | 2 +- score/mw/com/impl/traits_test.cpp | 6 ++--- 10 files changed, 54 insertions(+), 39 deletions(-) diff --git a/score/mw/com/impl/generic_proxy_test.cpp b/score/mw/com/impl/generic_proxy_test.cpp index b79ca7e90..d4adaa8e2 100644 --- a/score/mw/com/impl/generic_proxy_test.cpp +++ b/score/mw/com/impl/generic_proxy_test.cpp @@ -173,7 +173,7 @@ class GenericProxyFixture : public ::testing::Test // This ideally would be an ON_CALL as we want Create to create a mock binding and return it by default. // However, we get a "unknown file: Failure" while running the test in that case. Changing it to an EXPECT_CALL // solves the problem. - EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, Create(_, _)) + EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, Create(_, _, ServiceElementType::EVENT)) .Times(AnyNumber()) .WillRepeatedly([]() { return std::make_unique(); @@ -285,7 +285,8 @@ TEST_F(GenericProxyFixture, CreatingGenericProxyWithNoGenericProxyEventBindingRe // Given a handle created from valid instance and type deployments // and that the Create call on the ProxyEventBindingFactory returns a nullptr. CreateAHandle({kEventName1, kEventName2, kEventName3}); - EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, Create(_, std::string_view{kEventName1})) + EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, + Create(_, std::string_view{kEventName1}, ServiceElementType::EVENT)) .WillRepeatedly(Return(ByMove(nullptr))); // When creating a GenericProxy @@ -311,11 +312,14 @@ TEST_F(GenericProxyFixture, GenericProxyWillCreateEventBindingsSpecifiedInHandle CreateAHandle({kEventName1, kEventName2, kEventName3}); // Then bindings are created for the provided events - EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, Create(_, std::string_view{kEventName1})) + EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, + Create(_, std::string_view{kEventName1}, ServiceElementType::EVENT)) .WillOnce(Return(ByMove(std::make_unique()))); - EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, Create(_, std::string_view{kEventName2})) + EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, + Create(_, std::string_view{kEventName2}, ServiceElementType::EVENT)) .WillOnce(Return(ByMove(std::make_unique()))); - EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, Create(_, std::string_view{kEventName3})) + EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, + Create(_, std::string_view{kEventName3}, ServiceElementType::EVENT)) .WillOnce(Return(ByMove(std::make_unique()))); // When constructing the generic proxy from the handle @@ -364,10 +368,14 @@ TEST_F(GenericProxyFixture, GenericProxyWillOnlyCreateEventBindingsForEventsProv ON_CALL(*proxy_binding_mock_, IsEventProvided(std::string_view{kEventName3})).WillByDefault(Return(true)); // Then bindings are only created for the provided events - EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, Create(_, std::string_view{kEventName1})) + EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, + Create(_, std::string_view{kEventName1}, ServiceElementType::EVENT)) .WillOnce(Return(ByMove(std::make_unique()))); - EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, Create(_, std::string_view{kEventName2})).Times(0); - EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, Create(_, std::string_view{kEventName3})) + EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, + Create(_, std::string_view{kEventName2}, ServiceElementType::EVENT)) + .Times(0); + EXPECT_CALL(generic_proxy_event_binding_guard_.factory_mock_, + Create(_, std::string_view{kEventName3}, ServiceElementType::EVENT)) .WillOnce(Return(ByMove(std::make_unique()))); // When constructing the generic proxy diff --git a/score/mw/com/impl/plumbing/BUILD b/score/mw/com/impl/plumbing/BUILD index 1b0be60ca..980824a4b 100644 --- a/score/mw/com/impl/plumbing/BUILD +++ b/score/mw/com/impl/plumbing/BUILD @@ -303,9 +303,10 @@ cc_library( tags = ["FFI"], deps = [ ":i_proxy_field_binding_factory", - ":lola_proxy_element_building_blocks", + ":proxy_event_binding_factory", ":proxy_method_binding_factory", "//score/mw/com/impl:method_type", + "//score/mw/com/impl:service_element_type", "@score_baselibs//score/language/futurecpp", ], ) diff --git a/score/mw/com/impl/plumbing/i_proxy_event_binding_factory.h b/score/mw/com/impl/plumbing/i_proxy_event_binding_factory.h index e540df5d2..4c34af9ad 100644 --- a/score/mw/com/impl/plumbing/i_proxy_event_binding_factory.h +++ b/score/mw/com/impl/plumbing/i_proxy_event_binding_factory.h @@ -18,6 +18,7 @@ #include "score/mw/com/impl/instance_identifier.h" #include "score/mw/com/impl/proxy_base.h" #include "score/mw/com/impl/proxy_event_binding.h" +#include "score/mw/com/impl/service_element_type.h" #include #include @@ -45,7 +46,9 @@ class IProxyEventBindingFactory /// \param handle The handle containing the binding information. /// \param event_name The binding unspecific name of the event inside the proxy denoted by handle. /// \return An instance of ProxyEventBinding or nullptr in case of an error. - virtual auto Create(ProxyBase& parent, const std::string_view event_name) noexcept + virtual auto Create(ProxyBase& parent, + const std::string_view event_name, + const ServiceElementType element_type) noexcept -> std::unique_ptr> = 0; }; @@ -68,7 +71,8 @@ class IGenericProxyEventBindingFactory /// \param event_name The binding unspecific name of the event inside the proxy denoted by handle. /// \return An instance of ProxyEventBinding or nullptr in case of an error. virtual std::unique_ptr Create(ProxyBase& parent, - const std::string_view event_name) noexcept = 0; + const std::string_view event_name, + const ServiceElementType element_type) noexcept = 0; }; } // namespace score::mw::com::impl diff --git a/score/mw/com/impl/plumbing/proxy_event_binding_factory.h b/score/mw/com/impl/plumbing/proxy_event_binding_factory.h index 1c97000bc..c36d844d1 100644 --- a/score/mw/com/impl/plumbing/proxy_event_binding_factory.h +++ b/score/mw/com/impl/plumbing/proxy_event_binding_factory.h @@ -18,6 +18,7 @@ #include "score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.h" #include "score/mw/com/impl/proxy_base.h" #include "score/mw/com/impl/proxy_event_binding.h" +#include "score/mw/com/impl/service_element_type.h" #include @@ -34,9 +35,12 @@ class ProxyEventBindingFactory final { public: /// \brief See documentation in IProxyEventBindingFactory. - static std::unique_ptr> Create(ProxyBase& parent, std::string_view event_name) + static std::unique_ptr> Create( + ProxyBase& parent, + std::string_view event_name, + const ServiceElementType element_type = ServiceElementType::EVENT) { - return instance().Create(parent, event_name); + return instance().Create(parent, event_name, element_type); } /// \brief Inject a mock IProxyEventBindingFactory. If a mock is injected, then all calls on @@ -57,9 +61,12 @@ class GenericProxyEventBindingFactory final { public: /// \brief See documentation in IGenericProxyEventBindingFactory. - static std::unique_ptr Create(ProxyBase& parent, std::string_view event_name) + static std::unique_ptr Create( + ProxyBase& parent, + std::string_view event_name, + const ServiceElementType element_type = ServiceElementType::EVENT) { - return instance().Create(parent, event_name); + return instance().Create(parent, event_name, element_type); } /// \brief Inject a mock IGenericProxyEventBindingFactory. If a mock is injected, then all calls on diff --git a/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.cpp b/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.cpp index f0e6d2f3a..d0c4c5654 100644 --- a/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.cpp +++ b/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.cpp @@ -33,9 +33,10 @@ namespace score::mw::com::impl // coverity[autosar_cpp14_a15_5_3_violation : FALSE] std::unique_ptr GenericProxyEventBindingFactoryImpl::Create( ProxyBase& parent, - const std::string_view event_name) noexcept + const std::string_view event_name, + const ServiceElementType element_type) noexcept { - const auto lookup = LookupLolaProxyElement(parent, event_name, ServiceElementType::EVENT); + const auto lookup = LookupLolaProxyElement(parent, event_name, element_type); if (!lookup.has_value()) { score::mw::log::LogError("lola") diff --git a/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.h b/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.h index 5aae5bf49..3ec8248c1 100644 --- a/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.h +++ b/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.h @@ -42,7 +42,8 @@ class ProxyEventBindingFactoryImpl : public IProxyEventBindingFactory> Create(ProxyBase& parent, - const std::string_view event_name) noexcept override; + const std::string_view event_name, + const ServiceElementType element_type) noexcept override; }; /// \brief Factory class that dispatches calls to the appropriate binding based on binding information in the @@ -55,7 +56,8 @@ class GenericProxyEventBindingFactoryImpl : public IGenericProxyEventBindingFact /// \param event_name The binding unspecific name of the event inside the proxy denoted by handle. /// \return An instance of ProxyEventBinding or nullptr in case of an error. std::unique_ptr Create(ProxyBase& parent, - const std::string_view event_name) noexcept override; + const std::string_view event_name, + const ServiceElementType element_type) noexcept override; }; template @@ -69,9 +71,10 @@ template // coverity[autosar_cpp14_a15_5_3_violation : FALSE] inline std::unique_ptr> ProxyEventBindingFactoryImpl::Create( ProxyBase& parent, - const std::string_view event_name) noexcept + const std::string_view event_name, + const ServiceElementType element_type) noexcept { - const auto lookup = LookupLolaProxyElement(parent, event_name, ServiceElementType::EVENT); + const auto lookup = LookupLolaProxyElement(parent, event_name, element_type); if (!lookup.has_value()) { score::mw::log::LogError("lola") diff --git a/score/mw/com/impl/plumbing/proxy_event_binding_factory_mock.h b/score/mw/com/impl/plumbing/proxy_event_binding_factory_mock.h index 6d9ff71f0..bd6560439 100644 --- a/score/mw/com/impl/plumbing/proxy_event_binding_factory_mock.h +++ b/score/mw/com/impl/plumbing/proxy_event_binding_factory_mock.h @@ -14,6 +14,7 @@ #define SCORE_MW_COM_IMPL_PLUMBING_PROXY_EVENT_BINDING_FACTORY_MOCK_H #include "score/mw/com/impl/plumbing/i_proxy_event_binding_factory.h" +#include "score/mw/com/impl/service_element_type.h" #include @@ -26,7 +27,7 @@ class ProxyEventBindingFactoryMock : public IProxyEventBindingFactory>, Create, - (ProxyBase&, const std::string_view event_name), + (ProxyBase&, const std::string_view event_name, const ServiceElementType element_type), (noexcept, override)); }; @@ -35,7 +36,7 @@ class GenericProxyEventBindingFactoryMock : public IGenericProxyEventBindingFact public: MOCK_METHOD(std::unique_ptr, Create, - (ProxyBase&, const std::string_view event_name), + (ProxyBase&, const std::string_view event_name, const ServiceElementType element_type), (noexcept, override)); }; diff --git a/score/mw/com/impl/plumbing/proxy_field_binding_factory_impl.h b/score/mw/com/impl/plumbing/proxy_field_binding_factory_impl.h index 802bf8310..312624323 100644 --- a/score/mw/com/impl/plumbing/proxy_field_binding_factory_impl.h +++ b/score/mw/com/impl/plumbing/proxy_field_binding_factory_impl.h @@ -13,11 +13,9 @@ #ifndef SCORE_MW_COM_IMPL_PLUMBING_PROXY_FIELD_BINDING_FACTORY_IMPL_H #define SCORE_MW_COM_IMPL_PLUMBING_PROXY_FIELD_BINDING_FACTORY_IMPL_H -#include "score/mw/com/impl/bindings/lola/element_fq_id.h" -#include "score/mw/com/impl/bindings/lola/proxy_event.h" #include "score/mw/com/impl/method_type.h" #include "score/mw/com/impl/plumbing/i_proxy_field_binding_factory.h" -#include "score/mw/com/impl/plumbing/lola_proxy_element_building_blocks.h" +#include "score/mw/com/impl/plumbing/proxy_event_binding_factory.h" #include "score/mw/com/impl/plumbing/proxy_method_binding_factory.h" #include "score/mw/com/impl/proxy_base.h" #include "score/mw/com/impl/proxy_event_binding.h" @@ -66,15 +64,7 @@ inline std::unique_ptr> ProxyFieldBindingFactoryIm ProxyBase& parent, const std::string_view field_name) noexcept { - const auto lookup = LookupLolaProxyElement(parent, field_name, ServiceElementType::FIELD); - if (!lookup.has_value()) - { - score::mw::log::LogError("lola") - << "ProxyField event binding could not be created for field" << field_name - << "because the parent proxy binding is not a lola binding or the element could not be resolved."; - return nullptr; - } - return std::make_unique>(lookup->parent, lookup->element_fq_id, field_name); + return ProxyEventBindingFactory::Create(parent, field_name, ServiceElementType::FIELD); } template diff --git a/score/mw/com/impl/tracing/test/proxy_event_tracing_test.cpp b/score/mw/com/impl/tracing/test/proxy_event_tracing_test.cpp index 78f6d1f99..e8151ff95 100644 --- a/score/mw/com/impl/tracing/test/proxy_event_tracing_test.cpp +++ b/score/mw/com/impl/tracing/test/proxy_event_tracing_test.cpp @@ -119,7 +119,7 @@ class ProxyEventTracingFixture : public ::testing::Test { auto proxy_event_binding_mock_ptr = std::make_unique>(); mock_proxy_event_binding_ = proxy_event_binding_mock_ptr.get(); - EXPECT_CALL(factory_mock_guard.factory_mock_, Create(_, kServiceElementName)) + EXPECT_CALL(factory_mock_guard.factory_mock_, Create(_, kServiceElementName, ServiceElementType::EVENT)) .WillOnce(Return(ByMove(std::move(proxy_event_binding_mock_ptr)))); } diff --git a/score/mw/com/impl/traits_test.cpp b/score/mw/com/impl/traits_test.cpp index 975653d5f..f6cb8ed7f 100644 --- a/score/mw/com/impl/traits_test.cpp +++ b/score/mw/com/impl/traits_test.cpp @@ -120,7 +120,7 @@ class ProxyCreationFixture : public ::testing::Test .WillByDefault(Return(ByMove(std::move(proxy_binding_mock_ptr)))); // By default the Create call on the ProxyEventBindingFactory returns valid bindings. - ON_CALL(proxy_event_binding_factory_mock_guard_.factory_mock_, Create(_, kEventName)) + ON_CALL(proxy_event_binding_factory_mock_guard_.factory_mock_, Create(_, kEventName, ServiceElementType::EVENT)) .WillByDefault(Return(ByMove(std::move(proxy_event_binding_mock_ptr)))); // By default the Create call on the ProxyFieldBindingFactory returns valid bindings. @@ -203,7 +203,7 @@ TEST_F(GeneratedProxyCreationTestFixture, ReturnGeneratedProxyWhenSuccessfullyCr // Expecting that valid bindings are created for the Proxy, ProxyEvent and ProxyField EXPECT_CALL(proxy_binding_factory_mock_guard_.factory_mock_, Create(handle_)) .WillRepeatedly(Return(ByMove(std::move(proxy_binding_mock_ptr)))); - EXPECT_CALL(proxy_event_binding_factory_mock_guard_.factory_mock_, Create(_, kEventName)) + EXPECT_CALL(proxy_event_binding_factory_mock_guard_.factory_mock_, Create(_, kEventName, ServiceElementType::EVENT)) .WillRepeatedly(Return(ByMove(std::move(proxy_event_binding_mock_ptr)))); EXPECT_CALL(proxy_field_binding_factory_mock_guard_.factory_mock_, CreateEventBinding(_, kFieldName)) .WillRepeatedly(Return(ByMove(std::move(proxy_field_binding_mock_ptr)))); @@ -249,7 +249,7 @@ TEST_F(GeneratedProxyCreationTestFixture, ReturnErrorWhenCreatingProxyWithNoProx RecordProperty("DerivationTechnique", "Analysis of requirements"); // Expecting that the Create call on the ProxyEventBindingFactory returns an invalid binding for the event. - EXPECT_CALL(proxy_event_binding_factory_mock_guard_.factory_mock_, Create(_, kEventName)) + EXPECT_CALL(proxy_event_binding_factory_mock_guard_.factory_mock_, Create(_, kEventName, ServiceElementType::EVENT)) .WillOnce(Return(ByMove(nullptr))); // When creating a MyProxy From 69c43c18c0d4450d96ae724206792de80d9e46e3 Mon Sep 17 00:00:00 2001 From: Krishna Satish Deshkulkarni Shankaranarayana Date: Thu, 11 Jun 2026 15:11:57 +0200 Subject: [PATCH 03/10] mw/com: move lola proxy-element lookup out of plumbing --- score/mw/com/impl/bindings/lola/BUILD | 18 ++++++++++++++++ .../lola/proxy_element_lookup.cpp} | 2 +- .../lola/proxy_element_lookup.h} | 6 +++--- score/mw/com/impl/plumbing/BUILD | 21 ++----------------- .../proxy_event_binding_factory_impl.cpp | 2 +- .../proxy_event_binding_factory_impl.h | 2 +- .../proxy_method_binding_factory_impl.h | 2 +- 7 files changed, 27 insertions(+), 26 deletions(-) rename score/mw/com/impl/{plumbing/lola_proxy_element_building_blocks.cpp => bindings/lola/proxy_element_lookup.cpp} (98%) rename score/mw/com/impl/{plumbing/lola_proxy_element_building_blocks.h => bindings/lola/proxy_element_lookup.h} (93%) diff --git a/score/mw/com/impl/bindings/lola/BUILD b/score/mw/com/impl/bindings/lola/BUILD index 8da631653..cf3507375 100644 --- a/score/mw/com/impl/bindings/lola/BUILD +++ b/score/mw/com/impl/bindings/lola/BUILD @@ -449,6 +449,24 @@ cc_library( ], ) +cc_library( + name = "proxy_element_lookup", + srcs = ["proxy_element_lookup.cpp"], + hdrs = ["proxy_element_lookup.h"], + features = COMPILER_WARNING_FEATURES, + tags = ["FFI"], + visibility = [ + "//score/mw/com/impl/bindings/lola:__subpackages__", + "//score/mw/com/impl/plumbing:__subpackages__", + ], + deps = [ + "//score/mw/com/impl:proxy_base", + "//score/mw/com/impl/bindings/lola", + "//score/mw/com/impl/configuration", + "@score_baselibs//score/language/futurecpp", + ], +) + cc_library( name = "sample_ptr", srcs = ["sample_ptr.cpp"], diff --git a/score/mw/com/impl/plumbing/lola_proxy_element_building_blocks.cpp b/score/mw/com/impl/bindings/lola/proxy_element_lookup.cpp similarity index 98% rename from score/mw/com/impl/plumbing/lola_proxy_element_building_blocks.cpp rename to score/mw/com/impl/bindings/lola/proxy_element_lookup.cpp index c4376c8e9..c6a479ccc 100644 --- a/score/mw/com/impl/plumbing/lola_proxy_element_building_blocks.cpp +++ b/score/mw/com/impl/bindings/lola/proxy_element_lookup.cpp @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -#include "score/mw/com/impl/plumbing/lola_proxy_element_building_blocks.h" +#include "score/mw/com/impl/bindings/lola/proxy_element_lookup.h" #include "score/mw/com/impl/configuration/binding_service_type_deployment.h" #include "score/mw/com/impl/configuration/lola_service_type_deployment.h" diff --git a/score/mw/com/impl/plumbing/lola_proxy_element_building_blocks.h b/score/mw/com/impl/bindings/lola/proxy_element_lookup.h similarity index 93% rename from score/mw/com/impl/plumbing/lola_proxy_element_building_blocks.h rename to score/mw/com/impl/bindings/lola/proxy_element_lookup.h index a5d73f654..b1e8bf2d1 100644 --- a/score/mw/com/impl/plumbing/lola_proxy_element_building_blocks.h +++ b/score/mw/com/impl/bindings/lola/proxy_element_lookup.h @@ -10,8 +10,8 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -#ifndef SCORE_MW_COM_IMPL_PLUMBING_LOLA_PROXY_ELEMENT_BUILDING_BLOCKS_H -#define SCORE_MW_COM_IMPL_PLUMBING_LOLA_PROXY_ELEMENT_BUILDING_BLOCKS_H +#ifndef SCORE_MW_COM_IMPL_BINDINGS_LOLA_PROXY_ELEMENT_LOOKUP_H +#define SCORE_MW_COM_IMPL_BINDINGS_LOLA_PROXY_ELEMENT_LOOKUP_H #include "score/mw/com/impl/bindings/lola/element_fq_id.h" #include "score/mw/com/impl/bindings/lola/proxy.h" @@ -60,4 +60,4 @@ inline std::optional LookupLolaProxyElement(Prox } // namespace score::mw::com::impl -#endif // SCORE_MW_COM_IMPL_PLUMBING_LOLA_PROXY_ELEMENT_BUILDING_BLOCKS_H +#endif // SCORE_MW_COM_IMPL_BINDINGS_LOLA_PROXY_ELEMENT_LOOKUP_H diff --git a/score/mw/com/impl/plumbing/BUILD b/score/mw/com/impl/plumbing/BUILD index 980824a4b..b669a6cd6 100644 --- a/score/mw/com/impl/plumbing/BUILD +++ b/score/mw/com/impl/plumbing/BUILD @@ -260,23 +260,6 @@ cc_library( ], ) -cc_library( - name = "lola_proxy_element_building_blocks", - srcs = ["lola_proxy_element_building_blocks.cpp"], - hdrs = ["lola_proxy_element_building_blocks.h"], - features = COMPILER_WARNING_FEATURES, - tags = ["FFI"], - visibility = [ - "//score/mw/com/impl/plumbing:__subpackages__", - ], - deps = [ - "//score/mw/com/impl:proxy_base", - "//score/mw/com/impl/bindings/lola", - "//score/mw/com/impl/configuration", - "@score_baselibs//score/language/futurecpp", - ], -) - cc_library( name = "proxy_event_binding_factory_impl", srcs = ["proxy_event_binding_factory_impl.cpp"], @@ -289,7 +272,7 @@ cc_library( ], deps = [ ":i_proxy_event_binding_factory", - ":lola_proxy_element_building_blocks", + "//score/mw/com/impl/bindings/lola:proxy_element_lookup", "@score_baselibs//score/language/futurecpp", ], ) @@ -323,7 +306,7 @@ cc_library( ], deps = [ ":i_proxy_method_binding_factory", - ":lola_proxy_element_building_blocks", + "//score/mw/com/impl/bindings/lola:proxy_element_lookup", "@score_baselibs//score/language/futurecpp", ], ) diff --git a/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.cpp b/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.cpp index d0c4c5654..4ef5341c0 100644 --- a/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.cpp +++ b/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.cpp @@ -14,8 +14,8 @@ #include "score/mw/com/impl/bindings/lola/element_fq_id.h" #include "score/mw/com/impl/bindings/lola/generic_proxy_event.h" +#include "score/mw/com/impl/bindings/lola/proxy_element_lookup.h" #include "score/mw/com/impl/generic_proxy_event_binding.h" -#include "score/mw/com/impl/plumbing/lola_proxy_element_building_blocks.h" #include "score/mw/com/impl/service_element_type.h" #include "score/mw/log/logging.h" diff --git a/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.h b/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.h index 3ec8248c1..6743c9639 100644 --- a/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.h +++ b/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.h @@ -14,10 +14,10 @@ #define SCORE_MW_COM_IMPL_PLUMBING_PROXY_EVENT_BINDING_FACTORY_IMPL_H #include "score/mw/com/impl/bindings/lola/element_fq_id.h" +#include "score/mw/com/impl/bindings/lola/proxy_element_lookup.h" #include "score/mw/com/impl/bindings/lola/proxy_event.h" #include "score/mw/com/impl/generic_proxy_event_binding.h" #include "score/mw/com/impl/plumbing/i_proxy_event_binding_factory.h" -#include "score/mw/com/impl/plumbing/lola_proxy_element_building_blocks.h" #include "score/mw/com/impl/proxy_base.h" #include "score/mw/com/impl/proxy_event_binding.h" #include "score/mw/com/impl/service_element_type.h" diff --git a/score/mw/com/impl/plumbing/proxy_method_binding_factory_impl.h b/score/mw/com/impl/plumbing/proxy_method_binding_factory_impl.h index c819f8c0d..b88ef1e15 100644 --- a/score/mw/com/impl/plumbing/proxy_method_binding_factory_impl.h +++ b/score/mw/com/impl/plumbing/proxy_method_binding_factory_impl.h @@ -17,13 +17,13 @@ #include "score/mw/com/impl/bindings/lola/methods/proxy_method_instance_identifier.h" #include "score/mw/com/impl/bindings/lola/methods/type_erased_call_queue.h" #include "score/mw/com/impl/bindings/lola/proxy.h" +#include "score/mw/com/impl/bindings/lola/proxy_element_lookup.h" #include "score/mw/com/impl/bindings/lola/proxy_method.h" #include "score/mw/com/impl/configuration/lola_method_instance_deployment.h" #include "score/mw/com/impl/configuration/service_instance_deployment.h" #include "score/mw/com/impl/handle_type.h" #include "score/mw/com/impl/methods/proxy_method_binding.h" #include "score/mw/com/impl/plumbing/i_proxy_method_binding_factory.h" -#include "score/mw/com/impl/plumbing/lola_proxy_element_building_blocks.h" #include "score/mw/com/impl/proxy_base.h" #include "score/mw/com/impl/proxy_binding.h" #include "score/mw/com/impl/service_element_type.h" From e277dc09c986974e1186dfc17496606644d3a02f Mon Sep 17 00:00:00 2001 From: Krishna Satish Deshkulkarni Shankaranarayana Date: Thu, 11 Jun 2026 15:12:40 +0200 Subject: [PATCH 04/10] mw/com: replace LoLaProxyElementBuildingBlocks with lola lookup helpers split LookupLolaProxyElement into two free functions in bindings/lola and rework all the callers --- score/mw/com/impl/bindings/lola/BUILD | 14 ++++-- .../bindings/lola/proxy_element_lookup.cpp | 45 ++++++++--------- .../impl/bindings/lola/proxy_element_lookup.h | 50 ++++++------------- score/mw/com/impl/plumbing/BUILD | 2 + .../proxy_event_binding_factory_impl.cpp | 22 ++++---- .../proxy_event_binding_factory_impl.h | 22 ++++---- .../proxy_method_binding_factory_impl.h | 17 +++++-- 7 files changed, 81 insertions(+), 91 deletions(-) diff --git a/score/mw/com/impl/bindings/lola/BUILD b/score/mw/com/impl/bindings/lola/BUILD index cf3507375..fd59f4a36 100644 --- a/score/mw/com/impl/bindings/lola/BUILD +++ b/score/mw/com/impl/bindings/lola/BUILD @@ -454,16 +454,22 @@ cc_library( srcs = ["proxy_element_lookup.cpp"], hdrs = ["proxy_element_lookup.h"], features = COMPILER_WARNING_FEATURES, + implementation_deps = [ + ":proxy", + "//score/mw/com/impl/configuration", + "@score_baselibs//score/language/futurecpp", + "@score_baselibs//score/mw/log", + ], tags = ["FFI"], visibility = [ "//score/mw/com/impl/bindings/lola:__subpackages__", "//score/mw/com/impl/plumbing:__subpackages__", ], deps = [ - "//score/mw/com/impl:proxy_base", - "//score/mw/com/impl/bindings/lola", - "//score/mw/com/impl/configuration", - "@score_baselibs//score/language/futurecpp", + ":element_fq_id", + "//score/mw/com/impl:handle_type", + "//score/mw/com/impl:proxy_binding", + "//score/mw/com/impl:service_element_type", ], ) diff --git a/score/mw/com/impl/bindings/lola/proxy_element_lookup.cpp b/score/mw/com/impl/bindings/lola/proxy_element_lookup.cpp index c6a479ccc..6a4020168 100644 --- a/score/mw/com/impl/bindings/lola/proxy_element_lookup.cpp +++ b/score/mw/com/impl/bindings/lola/proxy_element_lookup.cpp @@ -12,7 +12,9 @@ ********************************************************************************/ #include "score/mw/com/impl/bindings/lola/proxy_element_lookup.h" +#include "score/mw/com/impl/bindings/lola/proxy.h" #include "score/mw/com/impl/configuration/binding_service_type_deployment.h" +#include "score/mw/com/impl/configuration/lola_service_instance_id.h" #include "score/mw/com/impl/configuration/lola_service_type_deployment.h" #include "score/mw/log/logging.h" @@ -23,24 +25,22 @@ #include #include -namespace score::mw::com::impl +namespace score::mw::com::impl::lola { -namespace +Proxy* GetLolaProxyBinding(ProxyBinding* const parent_binding) noexcept { + return dynamic_cast(parent_binding); +} -std::optional LookupForLola(const HandleType& handle, - ProxyBinding* parent_binding, - const LolaServiceTypeDeployment& lola_type_deployment, - const std::string_view name, - const ServiceElementType element_type) noexcept +namespace { - auto* const lola_parent = dynamic_cast(parent_binding); - if (lola_parent == nullptr) - { - return std::nullopt; - } +std::optional GetElementFqIdForLola(const HandleType& handle, + const LolaServiceTypeDeployment& lola_type_deployment, + const std::string_view name, + const ServiceElementType element_type) noexcept +{ const auto instance_id = handle.GetInstanceId(); const auto* const lola_instance_id = std::get_if(&(instance_id.binding_info_)); SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE(lola_instance_id != nullptr, @@ -67,10 +67,7 @@ std::optional LookupForLola(const HandleType& ha return std::nullopt; } - const lola::ElementFqId element_fq_id{ - lola_type_deployment.service_id_, element_id, lola_instance_id->GetId(), element_type}; - - return LoLaProxyElementBuildingBlocks{*lola_parent, lola_instance_id->GetId(), element_fq_id}; + return ElementFqId{lola_type_deployment.service_id_, element_id, lola_instance_id->GetId(), element_type}; } } // namespace @@ -79,23 +76,21 @@ std::optional LookupForLola(const HandleType& ha // if the variant is valueless_by_exception, which cannot happen here because we do not throw // exceptions during construction of the alternatives. // coverity[autosar_cpp14_a15_5_3_violation : FALSE] -std::optional LookupLolaProxyElement(const HandleType& handle, - ProxyBinding* parent_binding, - const std::string_view service_element_name, - const ServiceElementType element_type) noexcept +std::optional GetElementFqId(const HandleType& handle, + const std::string_view service_element_name, + const ServiceElementType element_type) noexcept { const auto& type_deployment = handle.GetServiceTypeDeployment(); auto visitor = score::cpp::overload( - [&handle, parent_binding, service_element_name, element_type]( - const LolaServiceTypeDeployment& lola_deployment) { - return LookupForLola(handle, parent_binding, lola_deployment, service_element_name, element_type); + [&handle, service_element_name, element_type](const LolaServiceTypeDeployment& lola_deployment) { + return GetElementFqIdForLola(handle, lola_deployment, service_element_name, element_type); }, - [](const score::cpp::blank&) noexcept -> std::optional { + [](const score::cpp::blank&) noexcept -> std::optional { return std::nullopt; }); return std::visit(visitor, type_deployment.binding_info_); } -} // namespace score::mw::com::impl +} // namespace score::mw::com::impl::lola diff --git a/score/mw/com/impl/bindings/lola/proxy_element_lookup.h b/score/mw/com/impl/bindings/lola/proxy_element_lookup.h index b1e8bf2d1..e8337865f 100644 --- a/score/mw/com/impl/bindings/lola/proxy_element_lookup.h +++ b/score/mw/com/impl/bindings/lola/proxy_element_lookup.h @@ -14,50 +14,30 @@ #define SCORE_MW_COM_IMPL_BINDINGS_LOLA_PROXY_ELEMENT_LOOKUP_H #include "score/mw/com/impl/bindings/lola/element_fq_id.h" -#include "score/mw/com/impl/bindings/lola/proxy.h" -#include "score/mw/com/impl/configuration/lola_service_element_id.h" -#include "score/mw/com/impl/configuration/lola_service_instance_deployment.h" #include "score/mw/com/impl/handle_type.h" -#include "score/mw/com/impl/proxy_base.h" #include "score/mw/com/impl/proxy_binding.h" #include "score/mw/com/impl/service_element_type.h" #include #include -namespace score::mw::com::impl +namespace score::mw::com::impl::lola { -/// \brief Result of resolving a named service element against the lola deployment on the proxy side. -/// \details Carries everything a binding constructor needs that comes from deployment/handle lookup. -/// This is intentionally agnostic to what kind of binding is being built (event, field notifier, -/// method); the construction step lives with the caller. -struct LoLaProxyElementBuildingBlocks -{ - lola::Proxy& parent; - LolaServiceInstanceId::InstanceId instance_id; - lola::ElementFqId element_fq_id; -}; - -/// \brief Validate the parent is a lola proxy and resolve the element name against the lola deployment contained in the -/// given handle. -/// \return The lookup data on success, std::nullopt for non-lola bindings or a missing parent binding. -/// \note Fatally asserts on a malformed instance id or an element name that is not present in the -/// deployment, matching the previous behaviour of the per-factory inlined lookups. -std::optional LookupLolaProxyElement(const HandleType& handle, - ProxyBinding* parent_binding, - std::string_view service_element_name, - ServiceElementType element_type) noexcept; - -/// \brief Convenience overload that pulls the handle and binding out of a ProxyBase reference. -inline std::optional LookupLolaProxyElement(ProxyBase& parent, - std::string_view service_element_name, - ServiceElementType element_type) noexcept -{ - return LookupLolaProxyElement( - parent.GetHandle(), ProxyBaseView{parent}.GetBinding(), service_element_name, element_type); -} +class Proxy; + +/// \brief Returns the parent binding cast to a lola::Proxy. +/// \return The lola proxy, or nullptr if the binding is null or not a lola binding. +Proxy* GetLolaProxyBinding(ProxyBinding* parent_binding) noexcept; + +/// \brief Resolves a named service element against the lola deployment contained in the given handle. +/// \return The fully qualified element id, or std::nullopt for a non-lola (blank) deployment. +/// \note Fatally asserts on a malformed instance id, an invalid element type, or an element name that is not present +/// in the deployment. +std::optional GetElementFqId(const HandleType& handle, + std::string_view service_element_name, + ServiceElementType element_type) noexcept; -} // namespace score::mw::com::impl +} // namespace score::mw::com::impl::lola #endif // SCORE_MW_COM_IMPL_BINDINGS_LOLA_PROXY_ELEMENT_LOOKUP_H diff --git a/score/mw/com/impl/plumbing/BUILD b/score/mw/com/impl/plumbing/BUILD index b669a6cd6..f8aff6d32 100644 --- a/score/mw/com/impl/plumbing/BUILD +++ b/score/mw/com/impl/plumbing/BUILD @@ -272,6 +272,8 @@ cc_library( ], deps = [ ":i_proxy_event_binding_factory", + "//score/mw/com/impl:proxy_base", + "//score/mw/com/impl/bindings/lola", "//score/mw/com/impl/bindings/lola:proxy_element_lookup", "@score_baselibs//score/language/futurecpp", ], diff --git a/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.cpp b/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.cpp index 4ef5341c0..7ff37c178 100644 --- a/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.cpp +++ b/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.cpp @@ -23,28 +23,28 @@ namespace score::mw::com::impl { -// Suppress "AUTOSAR C++14 A15-5-3" rule finding. This rule states: "The std::terminate() function shall -// not be called implicitly.". std::visit Throws std::bad_variant_access if -// as-variant(vars_i).valueless_by_exception() is true for any variant vars_i in vars. The variant may only become -// valueless if an exception is thrown during different stages. Since we don't throw exceptions, it's not possible -// that the variant can return true from valueless_by_exception and therefore not possible that std::visit throws -// an exception. -// This suppression should be removed after fixing [Ticket-173043](broken_link_j/Ticket-173043) -// coverity[autosar_cpp14_a15_5_3_violation : FALSE] std::unique_ptr GenericProxyEventBindingFactoryImpl::Create( ProxyBase& parent, const std::string_view event_name, const ServiceElementType element_type) noexcept { - const auto lookup = LookupLolaProxyElement(parent, event_name, element_type); - if (!lookup.has_value()) + auto* const lola_proxy = lola::GetLolaProxyBinding(ProxyBaseView{parent}.GetBinding()); + if (lola_proxy == nullptr) { score::mw::log::LogError("lola") << "GenericProxyEvent binding could not be created for event" << event_name << "because the parent proxy binding is not a lola binding or the element could not be resolved."; return nullptr; } - return std::make_unique(lookup->parent, lookup->element_fq_id, event_name); + const auto element_fq_id = lola::GetElementFqId(parent.GetHandle(), event_name, element_type); + if (!element_fq_id.has_value()) + { + score::mw::log::LogError("lola") + << "GenericProxyEvent binding could not be created for event" << event_name + << "because the parent proxy binding is not a lola binding or the element could not be resolved."; + return nullptr; + } + return std::make_unique(*lola_proxy, *element_fq_id, event_name); } } // namespace score::mw::com::impl diff --git a/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.h b/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.h index 6743c9639..712e381e9 100644 --- a/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.h +++ b/score/mw/com/impl/plumbing/proxy_event_binding_factory_impl.h @@ -61,28 +61,28 @@ class GenericProxyEventBindingFactoryImpl : public IGenericProxyEventBindingFact }; template -// Suppress "AUTOSAR C++14 A15-5-3" rule finding. This rule states: "The std::terminate() function shall -// not be called implicitly.". std::visit Throws std::bad_variant_access if -// as-variant(vars_i).valueless_by_exception() is true for any variant vars_i in vars. The variant may only become -// valueless if an exception is thrown during different stages. Since we don't throw exceptions, it's not possible -// that the variant can return true from valueless_by_exception and therefore not possible that std::visit throws -// an exception. -// This suppression should be removed after fixing [Ticket-173043](broken_link_j/Ticket-173043) -// coverity[autosar_cpp14_a15_5_3_violation : FALSE] inline std::unique_ptr> ProxyEventBindingFactoryImpl::Create( ProxyBase& parent, const std::string_view event_name, const ServiceElementType element_type) noexcept { - const auto lookup = LookupLolaProxyElement(parent, event_name, element_type); - if (!lookup.has_value()) + auto* const lola_proxy = lola::GetLolaProxyBinding(ProxyBaseView{parent}.GetBinding()); + if (lola_proxy == nullptr) { score::mw::log::LogError("lola") << "ProxyEvent binding could not be created for event" << event_name << "because the parent proxy binding is not a lola binding or the element could not be resolved."; return nullptr; } - return std::make_unique>(lookup->parent, lookup->element_fq_id, event_name); + const auto element_fq_id = lola::GetElementFqId(parent.GetHandle(), event_name, element_type); + if (!element_fq_id.has_value()) + { + score::mw::log::LogError("lola") + << "ProxyEvent binding could not be created for event" << event_name + << "because the parent proxy binding is not a lola binding or the element could not be resolved."; + return nullptr; + } + return std::make_unique>(*lola_proxy, *element_fq_id, event_name); } } // namespace score::mw::com::impl diff --git a/score/mw/com/impl/plumbing/proxy_method_binding_factory_impl.h b/score/mw/com/impl/plumbing/proxy_method_binding_factory_impl.h index b88ef1e15..99dcd6c74 100644 --- a/score/mw/com/impl/plumbing/proxy_method_binding_factory_impl.h +++ b/score/mw/com/impl/plumbing/proxy_method_binding_factory_impl.h @@ -105,8 +105,16 @@ std::unique_ptr ProxyMethodBindingFactoryImpl ProxyMethodBindingFactoryImplparent.GetProxyInstanceIdentifier(), {lookup->element_fq_id.element_id_, method_type}}; + lola_proxy->GetProxyInstanceIdentifier(), {element_fq_id->element_id_, method_type}}; - return std::make_unique( - lookup->parent, proxy_method_instance_identifier, type_erased_element_info); + return std::make_unique(*lola_proxy, proxy_method_instance_identifier, type_erased_element_info); } } // namespace score::mw::com::impl From d0259b63d5d0e3cdc934a8e3847cc8a24d4c2b80 Mon Sep 17 00:00:00 2001 From: Krishna Satish Deshkulkarni Shankaranarayana Date: Tue, 9 Jun 2026 11:44:53 +0200 Subject: [PATCH 05/10] mw/com: rename VerifyAllMethodsRegistered to VerifyAllMethodHandlersRegistered --- score/mw/com/impl/bindings/lola/skeleton.cpp | 2 +- score/mw/com/impl/bindings/lola/skeleton.h | 2 +- score/mw/com/impl/bindings/lola/skeleton_test.cpp | 12 ++++++------ score/mw/com/impl/bindings/mock_binding/skeleton.h | 6 +++--- score/mw/com/impl/generic_skeleton_event_test.cpp | 2 +- score/mw/com/impl/generic_skeleton_test.cpp | 6 +++--- score/mw/com/impl/skeleton_base.cpp | 2 +- score/mw/com/impl/skeleton_base_test.cpp | 10 +++++----- score/mw/com/impl/skeleton_binding.h | 2 +- score/mw/com/impl/skeleton_binding_test.cpp | 2 +- score/mw/com/impl/traits_test.cpp | 8 ++++---- 11 files changed, 27 insertions(+), 27 deletions(-) diff --git a/score/mw/com/impl/bindings/lola/skeleton.cpp b/score/mw/com/impl/bindings/lola/skeleton.cpp index 11dc9e098..21de63d92 100644 --- a/score/mw/com/impl/bindings/lola/skeleton.cpp +++ b/score/mw/com/impl/bindings/lola/skeleton.cpp @@ -558,7 +558,7 @@ void Skeleton::RegisterMethod(const UniqueMethodIdentifier method_id, SkeletonMe SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE(was_inserted, "Method IDs must be unique!"); } -bool Skeleton::VerifyAllMethodsRegistered() const +bool Skeleton::VerifyAllMethodHandlersRegistered() const { for (const auto& [method_id, method_reference] : skeleton_methods_) { diff --git a/score/mw/com/impl/bindings/lola/skeleton.h b/score/mw/com/impl/bindings/lola/skeleton.h index 9035dc93b..bdd0a9895 100644 --- a/score/mw/com/impl/bindings/lola/skeleton.h +++ b/score/mw/com/impl/bindings/lola/skeleton.h @@ -170,7 +170,7 @@ class Skeleton final : public SkeletonBinding /// constructor of Skeleton) without locking a mutex. void RegisterMethod(const UniqueMethodIdentifier method_id, SkeletonMethod& skeleton_method); - bool VerifyAllMethodsRegistered() const override; + bool VerifyAllMethodHandlersRegistered() const override; private: /// \brief Strategies for handling shared memory during PrepareOffer diff --git a/score/mw/com/impl/bindings/lola/skeleton_test.cpp b/score/mw/com/impl/bindings/lola/skeleton_test.cpp index 90f3aaf91..2be834b15 100644 --- a/score/mw/com/impl/bindings/lola/skeleton_test.cpp +++ b/score/mw/com/impl/bindings/lola/skeleton_test.cpp @@ -129,7 +129,7 @@ TEST_F(SkeletonTestMockedSharedMemoryFixture, GetBindingType) EXPECT_EQ(skeleton_->GetBindingType(), BindingType::kLoLa); } -TEST_F(SkeletonTestMockedSharedMemoryFixture, VerifyAllMethodsRegisteredSucceedsWhenAllMethodsAreRegistered) +TEST_F(SkeletonTestMockedSharedMemoryFixture, VerifyAllMethodHandlersRegisteredSucceedsWhenAllMethodsAreRegistered) { GivenASkeletonWithTwoMethods(); @@ -142,11 +142,11 @@ TEST_F(SkeletonTestMockedSharedMemoryFixture, VerifyAllMethodsRegisteredSucceeds std::ignore = fooo_method_->RegisterHandler(fooo_callback); std::ignore = dumb_method_->RegisterHandler(dumb_callback); - // Then VerifyAllMethodsRegistered succeeds - EXPECT_EQ(skeleton_->VerifyAllMethodsRegistered(), true); + // Then VerifyAllMethodHandlersRegistered succeeds + EXPECT_EQ(skeleton_->VerifyAllMethodHandlersRegistered(), true); } -TEST_F(SkeletonTestMockedSharedMemoryFixture, VerifyAllMethodsRegisteredFailsWhenNotAllMethodsAreRegistered) +TEST_F(SkeletonTestMockedSharedMemoryFixture, VerifyAllMethodHandlersRegisteredFailsWhenNotAllMethodsAreRegistered) { GivenASkeletonWithTwoMethods(); @@ -155,8 +155,8 @@ TEST_F(SkeletonTestMockedSharedMemoryFixture, VerifyAllMethodsRegisteredFailsWhe std::ignore = fooo_method_->RegisterHandler(fooo_callback); - // Then VerifyAllMethodsRegistered fails with kBindingFailure - EXPECT_EQ(skeleton_->VerifyAllMethodsRegistered(), false); + // Then VerifyAllMethodHandlersRegistered fails with kBindingFailure + EXPECT_EQ(skeleton_->VerifyAllMethodHandlersRegistered(), false); } TEST_F(SkeletonTestMockedSharedMemoryFixture, StopOfferCallsUnregisterShmObjectTraceCallback) diff --git a/score/mw/com/impl/bindings/mock_binding/skeleton.h b/score/mw/com/impl/bindings/mock_binding/skeleton.h index 4a2cf3339..3fbbc6fca 100644 --- a/score/mw/com/impl/bindings/mock_binding/skeleton.h +++ b/score/mw/com/impl/bindings/mock_binding/skeleton.h @@ -34,7 +34,7 @@ class Skeleton : public SkeletonBinding (noexcept, override, final)); MOCK_METHOD(void, PrepareStopOffer, (std::optional), (noexcept, override, final)); MOCK_METHOD(BindingType, GetBindingType, (), (const, noexcept, override, final)); - MOCK_METHOD(bool, VerifyAllMethodsRegistered, (), (const, override)); + MOCK_METHOD(bool, VerifyAllMethodHandlersRegistered, (), (const, override)); }; class SkeletonFacade : public SkeletonBinding @@ -60,9 +60,9 @@ class SkeletonFacade : public SkeletonBinding return skeleton_.GetBindingType(); } - bool VerifyAllMethodsRegistered() const override final + bool VerifyAllMethodHandlersRegistered() const override final { - return skeleton_.VerifyAllMethodsRegistered(); + return skeleton_.VerifyAllMethodHandlersRegistered(); } private: diff --git a/score/mw/com/impl/generic_skeleton_event_test.cpp b/score/mw/com/impl/generic_skeleton_event_test.cpp index f1e8ea41a..3a8e35e64 100644 --- a/score/mw/com/impl/generic_skeleton_event_test.cpp +++ b/score/mw/com/impl/generic_skeleton_event_test.cpp @@ -333,7 +333,7 @@ TEST_F(GenericSkeletonEventTest, NotifyDispatchesToBindingAfterOffer) auto* event = &skeleton.GetEvents().find(event_name)->second; // And Given the service is Offered - EXPECT_CALL(*skeleton_binding_mock_, VerifyAllMethodsRegistered()).WillRepeatedly(Return(true)); + EXPECT_CALL(*skeleton_binding_mock_, VerifyAllMethodHandlersRegistered()).WillRepeatedly(Return(true)); EXPECT_CALL(*mock_event_binding_ptr, PrepareOffer()).WillOnce(Return(score::Result{})); ASSERT_TRUE(skeleton.OfferService().has_value()); diff --git a/score/mw/com/impl/generic_skeleton_test.cpp b/score/mw/com/impl/generic_skeleton_test.cpp index cf2aeafa1..f2f6c2ab4 100644 --- a/score/mw/com/impl/generic_skeleton_test.cpp +++ b/score/mw/com/impl/generic_skeleton_test.cpp @@ -263,7 +263,7 @@ TEST_F(GenericSkeletonTest, OfferServicePropagatesToBindingAndDiscovery) auto skeleton = GenericSkeleton::Create(identifier, {}).value(); // Expecting OfferService to trigger binding and discovery - EXPECT_CALL(*skeleton_binding_mock_, VerifyAllMethodsRegistered()).WillRepeatedly(Return(true)); + EXPECT_CALL(*skeleton_binding_mock_, VerifyAllMethodHandlersRegistered()).WillRepeatedly(Return(true)); EXPECT_CALL(*skeleton_binding_mock_, PrepareOffer(_, _, _)).WillOnce(Return(score::Result{})); EXPECT_CALL(service_discovery_mock_, OfferService(identifier)).WillOnce(Return(score::Result{})); @@ -284,7 +284,7 @@ TEST_F(GenericSkeletonTest, StopOfferServicePropagatesToBindingAndDiscovery) auto skeleton = GenericSkeleton::Create(identifier, {}).value(); // And given the service is already Offered - EXPECT_CALL(*skeleton_binding_mock_, VerifyAllMethodsRegistered()).WillRepeatedly(Return(true)); + EXPECT_CALL(*skeleton_binding_mock_, VerifyAllMethodHandlersRegistered()).WillRepeatedly(Return(true)); EXPECT_CALL(*skeleton_binding_mock_, PrepareOffer(_, _, _)).WillOnce(Return(score::Result{})); EXPECT_CALL(service_discovery_mock_, OfferService(identifier)).WillOnce(Return(score::Result{})); ASSERT_TRUE(skeleton.OfferService().has_value()); @@ -309,7 +309,7 @@ TEST_F(GenericSkeletonTest, OfferServiceReturnsErrorIfBindingFails) auto skeleton = GenericSkeleton::Create(identifier, {}).value(); // Expecting Binding to fail - EXPECT_CALL(*skeleton_binding_mock_, VerifyAllMethodsRegistered()).WillRepeatedly(Return(true)); + EXPECT_CALL(*skeleton_binding_mock_, VerifyAllMethodHandlersRegistered()).WillRepeatedly(Return(true)); EXPECT_CALL(*skeleton_binding_mock_, PrepareOffer(_, _, _)) .WillOnce(Return(MakeUnexpected(ComErrc::kBindingFailure))); diff --git a/score/mw/com/impl/skeleton_base.cpp b/score/mw/com/impl/skeleton_base.cpp index 19b79cca5..c3ce2b63a 100644 --- a/score/mw/com/impl/skeleton_base.cpp +++ b/score/mw/com/impl/skeleton_base.cpp @@ -192,7 +192,7 @@ auto SkeletonBase::OfferService() noexcept -> Result auto register_shm_object_callback = tracing::CreateRegisterShmObjectCallback(instance_id_, events_, fields_, *binding_); - if (!binding_->VerifyAllMethodsRegistered()) + if (!binding_->VerifyAllMethodHandlersRegistered()) { constexpr std::string_view msg = "Not all methods have been registered! Call Register(...) with an appropriate callback on each mehtod."; diff --git a/score/mw/com/impl/skeleton_base_test.cpp b/score/mw/com/impl/skeleton_base_test.cpp index 377d63ee0..d379f255a 100644 --- a/score/mw/com/impl/skeleton_base_test.cpp +++ b/score/mw/com/impl/skeleton_base_test.cpp @@ -133,7 +133,7 @@ class SkeletonBaseFixture : public ::testing::Test binding_mock_ = GetMockBinding(*skeleton_); ASSERT_NE(binding_mock_, nullptr); ON_CALL(*binding_mock_, GetBindingType()).WillByDefault(Return(BindingType::kLoLa)); - ON_CALL(*binding_mock_, VerifyAllMethodsRegistered()).WillByDefault(Return(true)); + ON_CALL(*binding_mock_, VerifyAllMethodHandlersRegistered()).WillByDefault(Return(true)); } void ExpectOfferService() noexcept @@ -223,8 +223,8 @@ TEST_F(SkeletonBaseOfferFixture, OfferServiceFailsIfAllMethodsHaveNotBeenRegiste // Given a constructed Skeleton with a valid identifier with two events and a field registered with the skeleton CreateSkeleton(GetInstanceIdentifierWithValidBinding()); - // When VerifyAllMethodsRegistered returns false - EXPECT_CALL(*binding_mock_, VerifyAllMethodsRegistered()).WillOnce(Return(false)); + // When VerifyAllMethodHandlersRegistered returns false + EXPECT_CALL(*binding_mock_, VerifyAllMethodHandlersRegistered()).WillOnce(Return(false)); // When offering a Service const auto offer_result = skeleton_->OfferService(); @@ -489,7 +489,7 @@ TEST_F(SkeletonBaseOfferFixture, ServiceCanBeReOfferedAfterMoveConstructingServi mock_binding::Skeleton* const binding_mock = GetMockBinding(skeleton); ON_CALL(*binding_mock, GetBindingType()).WillByDefault(Return(BindingType::kLoLa)); - ON_CALL(*binding_mock, VerifyAllMethodsRegistered()).WillByDefault(Return(true)); + ON_CALL(*binding_mock, VerifyAllMethodHandlersRegistered()).WillByDefault(Return(true)); ASSERT_NE(binding_mock, nullptr); @@ -542,7 +542,7 @@ TEST_F(SkeletonBaseOfferFixture, ServiceCanBeReOfferedAfterCallingStopOfferServi mock_binding::Skeleton* const binding_mock = GetMockBinding(skeleton); ON_CALL(*binding_mock, GetBindingType()).WillByDefault(Return(BindingType::kLoLa)); - ON_CALL(*binding_mock, VerifyAllMethodsRegistered()).WillByDefault(Return(true)); + ON_CALL(*binding_mock, VerifyAllMethodHandlersRegistered()).WillByDefault(Return(true)); ASSERT_NE(binding_mock, nullptr); diff --git a/score/mw/com/impl/skeleton_binding.h b/score/mw/com/impl/skeleton_binding.h index 79bfe9890..c7fd30b30 100644 --- a/score/mw/com/impl/skeleton_binding.h +++ b/score/mw/com/impl/skeleton_binding.h @@ -96,7 +96,7 @@ class SkeletonBinding /// \brief Gets the binding type of the binding virtual BindingType GetBindingType() const noexcept = 0; - virtual bool VerifyAllMethodsRegistered() const = 0; + virtual bool VerifyAllMethodHandlersRegistered() const = 0; }; } // namespace score::mw::com::impl diff --git a/score/mw/com/impl/skeleton_binding_test.cpp b/score/mw/com/impl/skeleton_binding_test.cpp index 777b6cbc9..e164020d9 100644 --- a/score/mw/com/impl/skeleton_binding_test.cpp +++ b/score/mw/com/impl/skeleton_binding_test.cpp @@ -34,7 +34,7 @@ class MySkeleton final : public SkeletonBinding { return BindingType::kFake; }; - bool VerifyAllMethodsRegistered() const override + bool VerifyAllMethodHandlersRegistered() const override { return true; } diff --git a/score/mw/com/impl/traits_test.cpp b/score/mw/com/impl/traits_test.cpp index f6cb8ed7f..a1f7e4200 100644 --- a/score/mw/com/impl/traits_test.cpp +++ b/score/mw/com/impl/traits_test.cpp @@ -646,7 +646,7 @@ class SkeletonCreationFixture : public ::testing::Test ON_CALL(runtime_mock, resolve(kInstanceSpecifier)).WillByDefault(Return(resolved_instance_identifiers_)); // By default the skeleton binding will report that all methods were correctly registered - ON_CALL(skeleton_binding_mock_, VerifyAllMethodsRegistered()).WillByDefault(Return(true)); + ON_CALL(skeleton_binding_mock_, VerifyAllMethodHandlersRegistered()).WillByDefault(Return(true)); // By default the skeleton and service element bindings will report that offer service preparation succeeded ON_CALL(skeleton_binding_mock_, PrepareOffer(_, _, _)).WillByDefault(Return(score::Result{})); @@ -959,8 +959,8 @@ TEST_F(GeneratedSkeletonCreationInstanceIdentifierTestFixture, CanInterpretAsSke EXPECT_CALL(skeleton_event_binding_mock_, Send(event_value, _)); EXPECT_CALL(skeleton_field_binding_mock_, Send(field_value, _)); - // and that VerifyAllMethodsRegistered returns true because there are no methods to register - EXPECT_CALL(skeleton_binding_mock_, VerifyAllMethodsRegistered()).WillOnce(Return(true)); + // and that VerifyAllMethodHandlersRegistered returns true because there are no methods to register + EXPECT_CALL(skeleton_binding_mock_, VerifyAllMethodHandlersRegistered()).WillOnce(Return(true)); // And that PrepareOffer is called on the skeleton binding and event / field EXPECT_CALL(skeleton_binding_mock_, PrepareOffer(_, _, _)) @@ -1037,7 +1037,7 @@ class GeneratedSkeletonStopOfferServiceRaiiFixture : public SkeletonCreationFixt })); // By default the skeleton binding will report that all methods were correctly registered - ON_CALL(skeleton_binding_mock_2_, VerifyAllMethodsRegistered()).WillByDefault(Return(true)); + ON_CALL(skeleton_binding_mock_2_, VerifyAllMethodHandlersRegistered()).WillByDefault(Return(true)); // By default the skeleton and service element bindings will report that offer service preparation succeeded ON_CALL(skeleton_binding_mock_2_, PrepareOffer(_, _, _)).WillByDefault(Return(score::Result{})); From 9cd4d376e225b3e4936b066af7b2a8db42505e01 Mon Sep 17 00:00:00 2001 From: Krishna Satish Deshkulkarni Shankaranarayana Date: Tue, 9 Jun 2026 15:24:00 +0200 Subject: [PATCH 06/10] mw::com: refactor GetMethodIdAndQueueSizeForEnabledMethods refactor to reduce code duplication with generic helper methods and also, SetupMethods hardcoded kUseGetIfAvailable/kUseSetIfAvailable to true and ignored the parsed useGetIfAvailable/useSetIfAvailable deployment config. --- score/mw/com/impl/bindings/lola/proxy.cpp | 126 ++++++++++++++-------- 1 file changed, 81 insertions(+), 45 deletions(-) diff --git a/score/mw/com/impl/bindings/lola/proxy.cpp b/score/mw/com/impl/bindings/lola/proxy.cpp index 599bba740..958a6c49a 100644 --- a/score/mw/com/impl/bindings/lola/proxy.cpp +++ b/score/mw/com/impl/bindings/lola/proxy.cpp @@ -244,6 +244,83 @@ score::Result ExecutePartialRestartLogic(const QualityType quality_type, return {}; } +template +struct ServiceElementTypeFor; + +template <> +struct ServiceElementTypeFor +{ + static constexpr ServiceElementType kType = ServiceElementType::METHOD; +}; + +template <> +struct ServiceElementTypeFor +{ + static constexpr ServiceElementType kType = ServiceElementType::FIELD; +}; + +constexpr LolaMethodInstanceDeployment::QueueSize kFieldMethodQueueSize{1U}; + +template +constexpr bool always_false_v = false; + +template +std::vector> GetEnabledMethodEntries( + const LolaInstanceDeploymentType& deployment) +{ + std::vector> entries; + + if constexpr (std::is_same_v) + { + for (const auto& [use_if_available, method_type] : + {std::pair{deployment.use_get_if_available_, MethodType::kGet}, + std::pair{deployment.use_set_if_available_, MethodType::kSet}}) + { + if (use_if_available.value_or(false)) + { + entries.emplace_back(method_type, kFieldMethodQueueSize); + } + } + } + else if constexpr (std::is_same_v) + { + if (deployment.enabled_.value_or(false)) + { + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE( + deployment.queue_size_.has_value(), + "Method instance deployment must contain queue_size on proxy side!"); + entries.emplace_back(MethodType::kMethod, deployment.queue_size_.value()); + } + } + else + { + // Defensive programming: This branch should never be hit as this function is only instantiated for + // LolaFieldInstanceDeployment and LolaMethodInstanceDeployment. + static_assert(always_false_v, + "GetEnabledMethodEntries is not implemented for this type"); + } + return entries; +} + +template +void AppendEnabledMethodIds( + const DeploymentMap& deployment_map, + std::vector>& result, + const LolaServiceTypeDeployment& service_type_deployment) +{ + using ElementDeployment = typename DeploymentMap::mapped_type; + constexpr auto kElementType = ServiceElementTypeFor::kType; + + for (const auto& [name, deployment] : deployment_map) + { + const auto element_id = GetServiceElementId(service_type_deployment, name); + for (const auto& [method_type, queue_size] : GetEnabledMethodEntries(deployment)) + { + result.emplace_back(UniqueMethodIdentifier{element_id, method_type}, queue_size); + } + } +} + } // namespace namespace detail_proxy @@ -630,35 +707,6 @@ score::Result Proxy::SetupMethods() { auto enabled_method_data = GetMethodIdAndQueueSizeForEnabledMethods(); - // Add field Get/Set methods to the enabled method data. - // TODO(Ticket-250429): Replace these constants with actual per-field configuration flags - // once the field get/set availability is added to the deployment configuration. - constexpr bool kUseGetIfAvailable = true; - constexpr bool kUseSetIfAvailable = true; - - // TODO : This would also be replaced with the actual queue size configuration from the config files once we support - // queue size > 1. - constexpr LolaMethodInstanceDeployment::QueueSize kFieldMethodQueueSize{1U}; - - const auto& lola_service_type_deployment = GetLoLaServiceTypeDeployment(handle_); - const auto& lola_service_instance_deployment = GetLoLaInstanceDeployment(handle_); - { - std::lock_guard lock{proxy_method_registration_mutex_}; - for (const auto& [field_name, field_instance_deployment] : lola_service_instance_deployment.fields_) - { - const auto field_id = - GetServiceElementId(lola_service_type_deployment, field_name); - - if ((kUseGetIfAvailable) && (proxy_methods_.count({field_id, MethodType::kGet}) != 0U)) - { - enabled_method_data.push_back({{field_id, MethodType::kGet}, kFieldMethodQueueSize}); - } - if ((kUseSetIfAvailable) && (proxy_methods_.count({field_id, MethodType::kSet}) != 0U)) - { - enabled_method_data.push_back({{field_id, MethodType::kSet}, kFieldMethodQueueSize}); - } - } - } // This check has be done after looping over the fields to add the field methods to the enabled method data because, // if we did this before then even when the fields are configured and when the enabled_method_names are empty we // would do an early return and miss setting up the fields shm. @@ -790,23 +838,11 @@ Proxy::GetMethodIdAndQueueSizeForEnabledMethods() const const auto& lola_service_instance_deployment = GetLoLaInstanceDeployment(handle_); const auto& lola_service_type_deployment = GetLoLaServiceTypeDeployment(handle_); - // Get enabled methods from config and build method data - for (const auto& [method_name, method_deployment] : lola_service_instance_deployment.methods_) - { - if (method_deployment.enabled_.has_value() && method_deployment.enabled_.value()) - { - const auto method_id = - GetServiceElementId(lola_service_type_deployment, method_name); - - SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE( - method_deployment.queue_size_.has_value(), - "Method instance deployment must contain queue_size on proxy side!"); - const auto queue_size = method_deployment.queue_size_.value(); + AppendEnabledMethodIds( + lola_service_instance_deployment.methods_, enabled_method_ids_and_queue_sizes, lola_service_type_deployment); - std::ignore = enabled_method_ids_and_queue_sizes.emplace_back( - UniqueMethodIdentifier{method_id, MethodType::kMethod}, queue_size); - } - } + AppendEnabledMethodIds( + lola_service_instance_deployment.fields_, enabled_method_ids_and_queue_sizes, lola_service_type_deployment); return enabled_method_ids_and_queue_sizes; } From ede3c51a0dae1da0ffcc7eb2868e543967c048af Mon Sep 17 00:00:00 2001 From: Krishna Satish Deshkulkarni Shankaranarayana Date: Thu, 11 Jun 2026 15:36:22 +0200 Subject: [PATCH 07/10] mw::com: make WithRegisteredProxyMethods register field get/set methods The proxy method test helper now takes a MethodType per registered entry instead of always kMethod, so field Get and Set methods can be registered too. Existing method call sites pass MethodType::kMethod. --- .../lola/proxy_method_handling_test.cpp | 262 +++++++++++------- 1 file changed, 159 insertions(+), 103 deletions(-) diff --git a/score/mw/com/impl/bindings/lola/proxy_method_handling_test.cpp b/score/mw/com/impl/bindings/lola/proxy_method_handling_test.cpp index 9f21cb43b..8e51a2f31 100644 --- a/score/mw/com/impl/bindings/lola/proxy_method_handling_test.cpp +++ b/score/mw/com/impl/bindings/lola/proxy_method_handling_test.cpp @@ -212,12 +212,13 @@ class ProxyMethodHandlingFixture : public ProxyMockedMemoryFixture } ProxyMethodHandlingFixture& WithRegisteredProxyMethods( - std::vector> methods_to_register) + std::vector> + methods_to_register) { - for (auto& [method_id, type_erased_element_info] : methods_to_register) + for (auto& [method_id, type_erased_element_info, method_type] : methods_to_register) { const ProxyMethodInstanceIdentifier proxy_method_instance_identifier{proxy_->GetProxyInstanceIdentifier(), - {method_id, MethodType::kMethod}}; + {method_id, method_type}}; proxy_method_storage_.emplace_back(*proxy_, proxy_method_instance_identifier, type_erased_element_info); } return *this; @@ -286,7 +287,8 @@ TEST_F(ProxyMethodHandlingFixture, SuccessfullyCreatingSharedMemoryReturnsSucces .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that the shared memory creation succeeds EXPECT_CALL(shared_memory_factory_mock_guard_.mock_, Create(StartsWith(kMethodChannelPrefix), _, _, _, _)) @@ -308,7 +310,8 @@ TEST_F(ProxyMethodHandlingFixture, FailingToCreateSharedMemoryReturnsError) .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that the shared memory creation fails and returns a nullptr EXPECT_CALL(shared_memory_factory_mock_guard_.mock_, Create(StartsWith(kMethodChannelPrefix), _, _, _, _)) @@ -331,10 +334,12 @@ TEST_F(ProxyMethodHandlingFixture, CreatesMethodCallQueueForEachMethodInShm) .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}, + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}, {kDummyMethodId1, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo1, kValidReturnTypeTypeErasedDataInfo1, kDummyQueueSize1}}}); + kValidInArgsTypeErasedDataInfo1, kValidReturnTypeTypeErasedDataInfo1, kDummyQueueSize1}, + MethodType::kMethod}}); // When calling SetupMethods with the name of the registered ProxyMethod score::cpp::ignore = proxy_->SetupMethods(); @@ -358,10 +363,12 @@ TEST_F(ProxyMethodHandlingFixture, SetsInArgsAndReturnStoragesForEachMethodInShm .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}, + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}, {kDummyMethodId1, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo1, kValidReturnTypeTypeErasedDataInfo1, kDummyQueueSize1}}}); + kValidInArgsTypeErasedDataInfo1, kValidReturnTypeTypeErasedDataInfo1, kDummyQueueSize1}, + MethodType::kMethod}}); // When calling SetupMethods with the name of the registered ProxyMethod score::cpp::ignore = proxy_->SetupMethods(); @@ -385,7 +392,8 @@ TEST_F(ProxyMethodHandlingFixture, CreatesSharedMemoryWithUserPermissionsContain .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that the shared memory creation is called with read and write permissions for the skeleton's // uid @@ -424,7 +432,8 @@ TEST_F(ProxySetupMethodsPartialRestartFixture, RemovesStaleArtefactsIfShmFileAlr .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that we check if the shm file already exists in the filesystem // which returns that it already exists (indicating that a previous Proxy was created which then crashed). @@ -448,7 +457,8 @@ TEST_F(ProxySetupMethodsPartialRestartFixture, ReturnsErrorWhenCheckingIfShmFile .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that we check if the shm file already exists in the filesystem which returns an error EXPECT_CALL(filesystem_fake_.GetStandard(), Exists(StartsWith(kMethodShmChannelPrefix))) @@ -472,7 +482,8 @@ TEST_F(ProxySetupMethodsProxyAutoReconnectFixture, .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that SubscribeServiceMethod will never be called EXPECT_CALL(*mock_service_, SubscribeServiceMethod(_, _, _, _)).Times(0); @@ -496,7 +507,8 @@ TEST_F(ProxySetupMethodsProxyAutoReconnectFixture, ResendsSubscribeMethodEveryTi .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that SubscribeServiceMethod will be called three times: once in SetupMethods and once for every time // the find service handler is called when the service has been reoffered @@ -525,10 +537,12 @@ TEST_F(ProxySetupMethodsProxyAutoReconnectFixture, MarksProxyMethodsUnsubscribed .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}, + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}, {kDummyMethodId1, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize1}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize1}, + MethodType::kMethod}}); // Given that SetupMethods was called which should mark the ProxyMethods as subscribed score::cpp::ignore = proxy_->SetupMethods(); @@ -555,10 +569,12 @@ TEST_F(ProxySetupMethodsProxyAutoReconnectFixture, .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}, + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}, {kDummyMethodId1, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize1}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize1}, + MethodType::kMethod}}); // Expecting that SubscribeServiceMethod will be called once in SetupMethods and a second time in the find service // handler when the service has been reoffered which succeeds @@ -590,10 +606,12 @@ TEST_F(ProxySetupMethodsProxyAutoReconnectFixture, .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}, + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}, {kDummyMethodId1, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize1}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize1}, + MethodType::kMethod}}); // Expecting that SubscribeServiceMethod will be called once in SetupMethods Sequence subscribe_service_method_sequence{}; @@ -628,7 +646,8 @@ TEST_F(ProxySetupMethodsProxyAutoReconnectFixture, DoesNotResendSubscribeMethodI .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that SubscribeServiceMethod will be called only once in SetupMethods EXPECT_CALL(*mock_service_, SubscribeServiceMethod(_, _, _, _)).Times(1); @@ -648,7 +667,8 @@ TEST_F(ProxySetupMethodsProxyAutoReconnectFixture, DoesNotResendSubscribeMethodI .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that SubscribeServiceMethod will be called only once in SetupMethods EXPECT_CALL(*mock_service_, SubscribeServiceMethod(_, _, _, _)).Times(1); @@ -673,7 +693,8 @@ TEST_F(ProxySetupMethodsMessagePassingFixture, MethodsWithArgsOrReturnTypesCalls .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that SubscribeServiceMethod will be called EXPECT_CALL(*mock_service_, SubscribeServiceMethod(_, _, _, _)) @@ -698,7 +719,8 @@ TEST_F(ProxySetupMethodsMessagePassingFixture, MethodsWithArgsOrReturnTypesForwa .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that SubscribeServiceMethod will be called which returns an error const auto call_service_method_subscribed_error_code = ComErrc::kCallQueueFull; @@ -722,10 +744,12 @@ TEST_F(ProxySetupMethodsMessagePassingFixture, ProxyMethodsMarkedAsSubscribedWhe .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}, + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}, {kDummyMethodId1, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize1}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize1}, + MethodType::kMethod}}); // Expecting that SubscribeServiceMethod will be called and returns a valid result EXPECT_CALL(*mock_service_, SubscribeServiceMethod(_, _, _, _)).WillOnce(Return(score::Result{})); @@ -748,10 +772,12 @@ TEST_F(ProxySetupMethodsMessagePassingFixture, .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}, + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}, {kDummyMethodId1, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize1}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize1}, + MethodType::kMethod}}); // Expecting that SubscribeServiceMethod will be called which returns an error const auto call_service_method_subscribed_error_code = ComErrc::kCallQueueFull; @@ -784,7 +810,8 @@ TEST_F(ProxySetupMethodsMessagePassingFixture, MethodsWithoutArgsOrReturnTypesFo GivenAConfigurationWithEnabledMethods({kDummyMethodName0, kDummyMethodName1}) .GivenAProxy() .GivenAMockedSharedMemoryResource() - .WithRegisteredProxyMethods({{kDummyMethodId0, kEmptyTypeErasedInfo}, {kDummyMethodId1, kEmptyTypeErasedInfo}}); + .WithRegisteredProxyMethods({{kDummyMethodId0, kEmptyTypeErasedInfo, MethodType::kMethod}, + {kDummyMethodId1, kEmptyTypeErasedInfo, MethodType::kMethod}}); // Expecting that SubscribeServiceMethod will be called which returns an error const auto call_service_method_subscribed_error_code = ComErrc::kCallQueueFull; @@ -805,7 +832,8 @@ TEST_F(ProxySetupMethodsMessagePassingFixture, EnablingMethodsWithoutArgsOrRetur GivenAConfigurationWithEnabledMethods({kDummyMethodName0, kDummyMethodName1}) .GivenAProxy() .GivenAMockedSharedMemoryResource() - .WithRegisteredProxyMethods({{kDummyMethodId0, kEmptyTypeErasedInfo}, {kDummyMethodId1, kEmptyTypeErasedInfo}}); + .WithRegisteredProxyMethods({{kDummyMethodId0, kEmptyTypeErasedInfo, MethodType::kMethod}, + {kDummyMethodId1, kEmptyTypeErasedInfo, MethodType::kMethod}}); // Expecting that SubscribeServiceMethod will be called EXPECT_CALL(*mock_service_, SubscribeServiceMethod(_, _, _, _)) @@ -830,7 +858,8 @@ TEST_F(ProxySetupMethodsMessagePassingFixture, FailingToGetLolaRuntimeTerminates .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that GetBindingRuntime is called on the impl runtime which returns // a nullptr @@ -843,9 +872,9 @@ TEST_F(ProxySetupMethodsMessagePassingFixture, FailingToGetLolaRuntimeTerminates class ProxySetupMethodsShmSizeParamaterizedFixture : public ProxyMethodHandlingFixture, - public ::testing::WithParamInterface< - std::pair, - std::vector>>> + public ::testing::WithParamInterface, + std::vector>>> { }; @@ -855,85 +884,102 @@ INSTANTIATE_TEST_SUITE_P( ::testing::Values( // Single method containing InArgs and Return Type - std::make_pair, - std::vector>>( + std::make_pair< + std::vector, + std::vector>>( {kDummyMethodName0}, - {std::make_pair(kDummyMethodId0, - TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{24, 8}}, - std::optional{{32, 16}}, - 5U})}), + {std::make_tuple(kDummyMethodId0, + TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{24, 8}}, + std::optional{{32, 16}}, + 5U}, + MethodType::kMethod)}), // Multiple methods containing InArgs and Return Type - std::make_pair, - std::vector>>( + std::make_pair< + std::vector, + std::vector>>( {kDummyMethodName0, kDummyMethodName1}, - {std::make_pair(kDummyMethodId0, - TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 8}}, - std::optional{{32, 16}}, - 3U}), - std::make_pair(kDummyMethodId1, - TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 16}}, - std::optional{{104, 8}}, - 4U})}), + {std::make_tuple(kDummyMethodId0, + TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 8}}, + std::optional{{32, 16}}, + 3U}, + MethodType::kMethod), + std::make_tuple(kDummyMethodId1, + TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 16}}, + std::optional{{104, 8}}, + 4U}, + MethodType::kMethod)}), // Multiple methods containing InArgs and Return Type with different padding // to previous test (The actual location of the padding will be determined // by the size of MethodData and its elements which are allocated before the // InArgs / Return types. However, the amount of padding between Method0 and // Method1 will be different to the test above). - std::make_pair, - std::vector>>( + std::make_pair< + std::vector, + std::vector>>( {kDummyMethodName0, kDummyMethodName1}, - {std::make_pair(kDummyMethodId0, - TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{24, 8}}, - std::optional{{32, 16}}, - 4U}), - std::make_pair(kDummyMethodId1, - TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 16}}, - std::optional{{104, 8}}, - 6U})}), + {std::make_tuple(kDummyMethodId0, + TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{24, 8}}, + std::optional{{32, 16}}, + 4U}, + MethodType::kMethod), + std::make_tuple(kDummyMethodId1, + TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 16}}, + std::optional{{104, 8}}, + 6U}, + MethodType::kMethod)}), // Method with empty InArgs - std::make_pair, - std::vector>>( + std::make_pair< + std::vector, + std::vector>>( {kDummyMethodName0, kDummyMethodName1}, - {std::make_pair(kDummyMethodId0, - TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 8}}, - std::optional{{32, 16}}, - 3U}), - std::make_pair(kDummyMethodId1, - TypeErasedCallQueue::TypeErasedElementInfo{kEmptyInArgsTypeErasedDataInfo, - std::optional{{104, 8}}, - 5U})}), + {std::make_tuple(kDummyMethodId0, + TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 8}}, + std::optional{{32, 16}}, + 3U}, + MethodType::kMethod), + std::make_tuple(kDummyMethodId1, + TypeErasedCallQueue::TypeErasedElementInfo{kEmptyInArgsTypeErasedDataInfo, + std::optional{{104, 8}}, + 5U}, + MethodType::kMethod)}), // Method with empty Return type - std::make_pair, - std::vector>>( + std::make_pair< + std::vector, + std::vector>>( {kDummyMethodName0, kDummyMethodName1}, - {std::make_pair(kDummyMethodId0, - TypeErasedCallQueue::TypeErasedElementInfo{ - std::optional{{32, 8}}, - kEmptyReturnTypeTypeErasedDataInfo, - 7U}), // Adjust if needed based on actual structure - std::make_pair(kDummyMethodId1, - TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 16}}, - std::optional{{104, 8}}, - 8U})}), + {std::make_tuple(kDummyMethodId0, + TypeErasedCallQueue::TypeErasedElementInfo{ + std::optional{{32, 8}}, + kEmptyReturnTypeTypeErasedDataInfo, + 7U}, // Adjust if needed based on actual structure + MethodType::kMethod), + std::make_tuple(kDummyMethodId1, + TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 16}}, + std::optional{{104, 8}}, + 8U}, + MethodType::kMethod)}), // Method with empty InArg and Return type (this method will be ignored in // size calculations) - std::make_pair, - std::vector>>( + std::make_pair< + std::vector, + std::vector>>( {kDummyMethodName0, kDummyMethodName1, kDummyMethodName2}, - {std::make_pair(kDummyMethodId0, - TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 8}}, - std::optional{{32, 16}}, - 3U}), - std::make_pair(kDummyMethodId1, kEmptyTypeErasedInfo), - std::make_pair(kDummyMethodId2, - TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 16}}, - std::optional{{104, 8}}, - 5U})}))); + {std::make_tuple(kDummyMethodId0, + TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 8}}, + std::optional{{32, 16}}, + 3U}, + MethodType::kMethod), + std::make_tuple(kDummyMethodId1, kEmptyTypeErasedInfo, MethodType::kMethod), + std::make_tuple(kDummyMethodId2, + TypeErasedCallQueue::TypeErasedElementInfo{std::optional{{32, 16}}, + std::optional{{104, 8}}, + 5U}, + MethodType::kMethod)}))); /// Note. This test assumes that the allocation behaviour of /// fake_method_memory_resource_ (i.e. MyBoundedSharedMemoryResource) behaves the @@ -977,7 +1023,7 @@ TEST_F(ProxyMethodHandlingFixture, EnabledMethodWithoutRegisteredProxyMethodTerm GivenAConfigurationWithEnabledMethods({kDummyMethodName1}) .GivenAProxy() .GivenAMockedSharedMemoryResource() - .WithRegisteredProxyMethods({{kDummyMethodId0, kEmptyTypeErasedInfo}}); + .WithRegisteredProxyMethods({{kDummyMethodId0, kEmptyTypeErasedInfo, MethodType::kMethod}}); // When calling SetupMethods with a ProxyMethod name which does not correspond // to the registered ProxyMethod Then the program terminates @@ -1056,7 +1102,8 @@ TEST_F(ProxyMethodHandlingFixture, EnablingMethodThatDoesNotContainQueueSizeInCo InitialiseProxyWithCreate(configuration_store.GetInstanceIdentifier()); SCORE_LANGUAGE_FUTURECPP_ASSERT(proxy_ != nullptr); - GivenAMockedSharedMemoryResource().WithRegisteredProxyMethods({{kDummyMethodId0, kEmptyTypeErasedInfo}}); + GivenAMockedSharedMemoryResource().WithRegisteredProxyMethods( + {{kDummyMethodId0, kEmptyTypeErasedInfo, MethodType::kMethod}}); // When calling SetupMethods with a ProxyMethod name which corresponds to the // registered ProxyMethod Then the program terminates @@ -1074,7 +1121,8 @@ TEST_F(ProxyCleanupMethodsFixture, DestroyingProxyWithoutCallingSetupMethodsDoes .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that UnsubscribeServiceMethod is never called when methods were not set up EXPECT_CALL(*mock_service_, UnsubscribeServiceMethod(_, _, _, _)).Times(0); @@ -1092,7 +1140,8 @@ TEST_F(ProxyCleanupMethodsFixture, DestroyingProxyAfterSetupMethodsCallsUnsubscr .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that UnsubscribeServiceMethod is called exactly once on destruction EXPECT_CALL(*mock_service_, UnsubscribeServiceMethod(_, _, _, _)).Times(1); @@ -1112,7 +1161,8 @@ TEST_F(ProxyCleanupMethodsFixture, DestroyingProxyCallsUnsubscribeServiceMethodW .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that UnsubscribeServiceMethod is called with the SkeletonInstanceIdentifier derived from the // configuration (service_id = kLolaServiceId, instance_id = kLolaInstanceId) and the skeleton pid from shared @@ -1139,7 +1189,8 @@ TEST_F(ProxyCleanupMethodsFixture, DestroyingProxyCompletesNormallyEvenWhenUnsub .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Given that UnsubscribeServiceMethod returns an error (e.g. skeleton already stopped offering) EXPECT_CALL(*mock_service_, UnsubscribeServiceMethod(_, _, _, _)) @@ -1163,7 +1214,8 @@ TEST_F(ProxyCleanupMethodsFixture, .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that UnsubscribeServiceMethod is never called because the ProxyMethods are not subscribed EXPECT_CALL(*mock_service_, SubscribeServiceMethod(_, _, _, _)) @@ -1185,7 +1237,8 @@ TEST_F(ProxyCleanupMethodsFixture, DestroyingProxyAfterSetupMethodsRemovesShmReg .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that Remove is called exactly once on destruction to unlink the method SHM. EXPECT_CALL(shared_memory_factory_mock_guard_.mock_, Remove(StartsWith(kMethodChannelPrefix))).Times(1); @@ -1205,7 +1258,8 @@ TEST_F(ProxyCleanupMethodsFixture, DestroyingProxyWithoutCallingSetupMethodsDoes .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that Remove and RemoveStaleArtefacts are never called because the SHM was never created EXPECT_CALL(shared_memory_factory_mock_guard_.mock_, Remove(_)).Times(0); @@ -1223,7 +1277,8 @@ TEST_F(ProxyCleanupMethodsFixture, DestroyingProxyAfterSkeletonStopOfferedDoesNo .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that UnsubscribeServiceMethod is NOT called on destruction because the skeleton already // cleaned up its side when it stopped offering (the subscribed flag was cleared by StopOffer). @@ -1244,7 +1299,8 @@ TEST_F(ProxyCleanupMethodsFixture, DestroyingProxyAfterSetupMethodsWithFailedSub .WithRegisteredProxyMethods( {{kDummyMethodId0, TypeErasedCallQueue::TypeErasedElementInfo{ - kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}}}); + kValidInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kMethod}}); // Expecting that Remove is still called to clean up the SHM even though subscription failed, // because the SHM was successfully created during SetupMethods. From a23c9c6505e0a425515b453dc30270c7805d1b1f Mon Sep 17 00:00:00 2001 From: Krishna Satish Deshkulkarni Shankaranarayana Date: Thu, 11 Jun 2026 15:36:30 +0200 Subject: [PATCH 08/10] mw::com: add unit tests for field method setup in the proxy covers field Get/Set handling in Proxy::SetupMethods --- .../lola/proxy_method_handling_test.cpp | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/score/mw/com/impl/bindings/lola/proxy_method_handling_test.cpp b/score/mw/com/impl/bindings/lola/proxy_method_handling_test.cpp index 8e51a2f31..f0e639b49 100644 --- a/score/mw/com/impl/bindings/lola/proxy_method_handling_test.cpp +++ b/score/mw/com/impl/bindings/lola/proxy_method_handling_test.cpp @@ -20,6 +20,8 @@ #include "score/mw/com/impl/bindings/lola/proxy_method.h" #include "score/mw/com/impl/bindings/lola/test/proxy_event_test_resources.h" #include "score/mw/com/impl/com_error.h" +#include "score/mw/com/impl/configuration/lola_event_instance_deployment.h" +#include "score/mw/com/impl/configuration/lola_field_instance_deployment.h" #include "score/mw/com/impl/configuration/lola_method_instance_deployment.h" #include "score/mw/com/impl/configuration/lola_service_element_id.h" #include "score/mw/com/impl/configuration/lola_service_id.h" @@ -113,6 +115,18 @@ const LolaServiceTypeDeployment kLolaServiceTypeDeploymentWithMethods{ {}, {{kDummyMethodName0, kDummyMethodId0}, {kDummyMethodName1, kDummyMethodId1}, {kDummyMethodName2, kDummyMethodId2}}}; +const std::string kDummyFieldName0{"my_dummy_field_0"}; +constexpr LolaServiceElementId kDummyFieldId0{20U}; +const LolaEventInstanceDeployment kFieldEventInstanceDeployment(LolaEventInstanceDeployment::SampleSlotCountType{1U}, + LolaEventInstanceDeployment::SubscriberCountType{1U}, + std::uint8_t{1U}, + true, + LolaEventInstanceDeployment::TracingSlotSizeType{0U}); +const LolaServiceTypeDeployment kLolaServiceTypeDeploymentWithField{kLolaServiceId, + {}, + {{kDummyFieldName0, kDummyFieldId0}}, + {}}; + const std::optional kEmptyInArgsTypeErasedDataInfo{}; const std::optional kEmptyReturnTypeTypeErasedDataInfo{}; const DataTypeSizeInfo kValidInArgsTypeErasedDataInfo{16U, 16U}; @@ -224,6 +238,24 @@ class ProxyMethodHandlingFixture : public ProxyMockedMemoryFixture return *this; } + ProxyMethodHandlingFixture& GivenAConfigurationWithField(const std::optional use_get_if_available, + const std::optional use_set_if_available) + { + configuration_store_ = std::make_unique( + ConfigurationStore{InstanceSpecifier::Create(std::string{"my_instance_spec"}).value(), + make_ServiceIdentifierType("foo"), + QualityType::kASIL_B, + kLolaServiceTypeDeploymentWithField, + LolaServiceInstanceDeployment{ + kLolaInstanceId, + {}, + {{kDummyFieldName0, + LolaFieldInstanceDeployment{ + kFieldEventInstanceDeployment, use_get_if_available, use_set_if_available}}}, + {}}}); + return *this; + } + void StopOfferService() { ASSERT_TRUE(find_service_handler_.has_value()); @@ -381,6 +413,108 @@ TEST_F(ProxyMethodHandlingFixture, SetsInArgsAndReturnStoragesForEachMethodInShm } } +TEST_F(ProxyMethodHandlingFixture, RegisteredFieldGetAndSetAreCreatedInShmWhenEnabledInDeployment) +{ + // Given a field whose Get and Set are enabled in config and registered as proxy methods + auto use_get_if_available = true; + auto use_set_if_available = true; + GivenAConfigurationWithField(use_get_if_available, use_set_if_available) + .GivenAProxy() + .GivenAFakeSharedMemoryResource() + .WithRegisteredProxyMethods( + {{kDummyFieldId0, + TypeErasedCallQueue::TypeErasedElementInfo{ + kEmptyInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kGet}, + {kDummyFieldId0, + TypeErasedCallQueue::TypeErasedElementInfo{ + kValidInArgsTypeErasedDataInfo, kEmptyReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kSet}}); + + // When setting up methods + score::cpp::ignore = proxy_->SetupMethods(); + + // Then the shm contains both the field Get and Set method call queues + const auto& method_data = GetMethodDataFromShm(); + EXPECT_THAT(method_data.method_call_queues_, + UnorderedElementsAre(Pair(UniqueMethodIdentifier{kDummyFieldId0, MethodType::kGet}, _), + Pair(UniqueMethodIdentifier{kDummyFieldId0, MethodType::kSet}, _))); +} + +TEST_F(ProxyMethodHandlingFixture, FieldGetDisabledInDeploymentConfigIsExcludedEvenWhenRegistered) +{ + // Given a field whose Get is disabled in config (useGetIfAvailable=false) but Set enabled, both registered + auto use_get_if_available = false; + auto use_set_if_available = true; + GivenAConfigurationWithField(use_get_if_available, use_set_if_available) + .GivenAProxy() + .GivenAFakeSharedMemoryResource() + .WithRegisteredProxyMethods( + {{kDummyFieldId0, + TypeErasedCallQueue::TypeErasedElementInfo{ + kEmptyInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kGet}, + {kDummyFieldId0, + TypeErasedCallQueue::TypeErasedElementInfo{ + kValidInArgsTypeErasedDataInfo, kEmptyReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kSet}}); + + // When setting up methods + score::cpp::ignore = proxy_->SetupMethods(); + + // Then only the Set method is created; the config-disabled Get is excluded even though it was registered + const auto& method_data = GetMethodDataFromShm(); + EXPECT_THAT(method_data.method_call_queues_, + UnorderedElementsAre(Pair(UniqueMethodIdentifier{kDummyFieldId0, MethodType::kSet}, _))); +} + +TEST_F(ProxyMethodHandlingFixture, FieldSetDisabledInDeploymentConfigIsExcludedEvenWhenRegistered) +{ + // Given a field whose Get is enabled in config (useGetIfAvailable=true) but Set disabled, both registered + auto use_get_if_available = true; + auto use_set_if_available = false; + GivenAConfigurationWithField(use_get_if_available, use_set_if_available) + .GivenAProxy() + .GivenAFakeSharedMemoryResource() + .WithRegisteredProxyMethods( + {{kDummyFieldId0, + TypeErasedCallQueue::TypeErasedElementInfo{ + kEmptyInArgsTypeErasedDataInfo, kValidReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kGet}, + {kDummyFieldId0, + TypeErasedCallQueue::TypeErasedElementInfo{ + kValidInArgsTypeErasedDataInfo, kEmptyReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kSet}}); + + // When setting up methods + score::cpp::ignore = proxy_->SetupMethods(); + + // Then only the Get method is created; the config-disabled Set is excluded even though it was registered + const auto& method_data = GetMethodDataFromShm(); + EXPECT_THAT(method_data.method_call_queues_, + UnorderedElementsAre(Pair(UniqueMethodIdentifier{kDummyFieldId0, MethodType::kGet}, _))); +} + +TEST_F(ProxyMethodHandlingFixture, FieldGetNotRegisteredDoesAbort) +{ + // Given a field whose Get and Set are enabled in config, but only the Set was registered (Get unregistered + // showcasing a programming bug). + auto use_get_if_available = true; + auto use_set_if_available = true; + GivenAConfigurationWithField(use_get_if_available, use_set_if_available) + .GivenAProxy() + .GivenAFakeSharedMemoryResource() + .WithRegisteredProxyMethods( + {{kDummyFieldId0, + TypeErasedCallQueue::TypeErasedElementInfo{ + kValidInArgsTypeErasedDataInfo, kEmptyReturnTypeTypeErasedDataInfo, kDummyQueueSize0}, + MethodType::kSet}}); + + // When setting up methods. + // Then the program terminates. + SCORE_LANGUAGE_FUTURECPP_EXPECT_CONTRACT_VIOLATED(proxy_->SetupMethods()); +} + TEST_F(ProxyMethodHandlingFixture, CreatesSharedMemoryWithUserPermissionsContainingSkeletonApplicationId) { // Given that a ProxyMethod is registered which is connected to a Fake ServiceDataStorage which stores kDummyUid as From 7efd7844e6264932b8e4bc78196c3ce5509a65f4 Mon Sep 17 00:00:00 2001 From: Krishna Satish Deshkulkarni Shankaranarayana Date: Tue, 9 Jun 2026 15:24:43 +0200 Subject: [PATCH 09/10] mw::com: remove outdated skip checks in verify method --- score/mw/com/impl/bindings/lola/skeleton.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/score/mw/com/impl/bindings/lola/skeleton.cpp b/score/mw/com/impl/bindings/lola/skeleton.cpp index 21de63d92..144cbf49e 100644 --- a/score/mw/com/impl/bindings/lola/skeleton.cpp +++ b/score/mw/com/impl/bindings/lola/skeleton.cpp @@ -560,13 +560,8 @@ void Skeleton::RegisterMethod(const UniqueMethodIdentifier method_id, SkeletonMe bool Skeleton::VerifyAllMethodHandlersRegistered() const { - for (const auto& [method_id, method_reference] : skeleton_methods_) + for (const auto& [_, method_reference] : skeleton_methods_) { - // TODO: Remove this skip once the field Get handler is auto-registered in SkeletonField. - if (method_id.method_type == ::score::mw::com::impl::MethodType::kGet) - { - continue; - } if (!method_reference.get().IsRegistered()) { return false; From 11c46d60f3d1d9e60398f4927a3a9c06dc633b32 Mon Sep 17 00:00:00 2001 From: Krishna Satish Deshkulkarni Shankaranarayana Date: Tue, 9 Jun 2026 15:47:28 +0200 Subject: [PATCH 10/10] mw::com: remove unreachable checks and update doc string --- score/mw/com/impl/bindings/lola/skeleton.cpp | 28 +++++--------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/score/mw/com/impl/bindings/lola/skeleton.cpp b/score/mw/com/impl/bindings/lola/skeleton.cpp index 144cbf49e..e93ccf9fb 100644 --- a/score/mw/com/impl/bindings/lola/skeleton.cpp +++ b/score/mw/com/impl/bindings/lola/skeleton.cpp @@ -734,28 +734,14 @@ auto Skeleton::SubscribeMethods(const MethodData& method_data, { auto& [unique_method_identifier, type_erased_call_queue] = method_call_queues[method_idx]; - if (skeleton_methods_.count(unique_method_identifier) == 0U) - { - // A proxy may register a Get or Set method for a field that has been disabled in the skeleton's - // interface definition. In that case, the skeleton has no handler for it. - if ((unique_method_identifier.method_type == MethodType::kGet) || - (unique_method_identifier.method_type == MethodType::kSet)) - { - score::mw::log::LogInfo("lola") - << "Proxy registered a field Get/Set method that is not available on the skeleton side. Skipping."; - continue; - } + // Defensive check for skeleton method population. + // The skeleton_methods_ map is populated at skeleton construction time + // by the lola::SkeletonMethod constructor calling Skeleton::RegisterMethod(). + // Under normal circumstances, this condition is never reached. + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE( + (skeleton_methods_.count(unique_method_identifier) != 0U), + "Each regular method stored in shared memory by the proxy must be registered with the Skeleton!"); - // This means that one misconfigured proxy can crash the skeleton and all other correctly configured proxies - // that are trying to subscribe to the same skeleton instance. However, since this is a configuration error, - // we consider it better to fail fast and loudly instead of silently ignoring the misconfiguration and - // potentially leaving the user wondering why their method calls are not working. - score::mw::log::LogFatal("lola") - << "Each regular method stored in shared memory by the proxy must be registered with the Skeleton!"; - SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE( - false, - "Each regular method stored in shared memory by the proxy must be registered with the Skeleton!"); - } auto& skeleton_method = skeleton_methods_.at(unique_method_identifier); const ProxyMethodInstanceIdentifier proxy_method_instance_identifier{proxy_instance_identifier, unique_method_identifier};