From f3bd44a47a199a2ecc0b1a004efbbdeaf2f91292 Mon Sep 17 00:00:00 2001 From: Manuel Fehlhammer Date: Mon, 9 Mar 2026 14:29:09 +0100 Subject: [PATCH] mw/com/impl: Add get/set to field Added Get/Set support to ProxyField. Issue: SWP-249574 --- score/mw/com/impl/BUILD | 2 + .../proxy_method_with_in_args_and_return.h | 33 ++ .../methods/proxy_method_with_return_type.h | 31 ++ .../impl/mocking/proxy_event_mock_test.cpp | 11 +- .../proxy_wrapper_class_test_view_test.cpp | 4 +- score/mw/com/impl/plumbing/BUILD | 1 + .../plumbing/i_proxy_field_binding_factory.h | 15 + .../plumbing/proxy_field_binding_factory.h | 13 + .../proxy_field_binding_factory_impl.h | 40 ++- .../proxy_field_binding_factory_mock.h | 8 + ...oxy_service_element_binding_factory_impl.h | 18 +- score/mw/com/impl/proxy_event.h | 11 +- score/mw/com/impl/proxy_field.h | 337 +++++++++++++++++- score/mw/com/impl/proxy_field_test.cpp | 152 +++++++- score/mw/com/impl/traits.h | 22 +- 15 files changed, 634 insertions(+), 64 deletions(-) diff --git a/score/mw/com/impl/BUILD b/score/mw/com/impl/BUILD index 1f78b91aa..fb26aafe7 100644 --- a/score/mw/com/impl/BUILD +++ b/score/mw/com/impl/BUILD @@ -208,6 +208,7 @@ cc_library( ":proxy_event", ":proxy_event_binding", ":proxy_field_base", + "//score/mw/com/impl/methods:proxy_method", "//score/mw/com/impl/mocking:i_proxy_event", "//score/mw/com/impl/plumbing:field", "@score_baselibs//score/language/futurecpp", @@ -964,6 +965,7 @@ cc_gtest_unit_test( deps = [ ":impl", ":runtime_mock", + "//score/mw/com/impl/mocking:proxy_event_mock", "//score/mw/com/impl/plumbing:proxy_field_binding_factory_mock", "//score/mw/com/impl/test:binding_factory_resources", "//score/mw/com/impl/test:proxy_resources", diff --git a/score/mw/com/impl/methods/proxy_method_with_in_args_and_return.h b/score/mw/com/impl/methods/proxy_method_with_in_args_and_return.h index 6bec0ff22..1743e40da 100644 --- a/score/mw/com/impl/methods/proxy_method_with_in_args_and_return.h +++ b/score/mw/com/impl/methods/proxy_method_with_in_args_and_return.h @@ -39,6 +39,9 @@ namespace score::mw::com::impl { +template +class ProxyField; + /// \brief Partial specialization of ProxyMethod for function signatures with arguments and non-void return /// \tparam ReturnType return type of the method /// \tparam ArgTypes argument types of the method @@ -51,6 +54,16 @@ class ProxyMethod final : public ProxyMethodBase // coverity[autosar_cpp14_a11_3_1_violation] friend class ProxyMethodView; + friend class ProxyField; + friend class ProxyField; + friend class ProxyField; + friend class ProxyField; + + // Empty struct that is used to make the non-registering ctor only accessible to ProxyField (as it is a friend). + struct FieldOnlyConstructorEnabler + { + }; + public: ProxyMethod(ProxyBase& proxy_base, std::string_view method_name) noexcept : ProxyMethodBase( @@ -85,6 +98,26 @@ class ProxyMethod final : public ProxyMethodBase } } + /// \brief Ctor for ProxyMethod that is used by ProxyField for the "dispatch method" of a field-setter. This method + /// does not register the method in the ProxyBase's method map, since registration in the correct field map is done + /// by ProxyField ctor. This is achieved by the FieldOnlyConstructorEnabler tag type, which makes clear, that this + /// ctor should only be used by ProxyField (this is enforced by FieldOnlyConstructorEnabler only visible to + /// ProxyField due to it being a friend). + ProxyMethod(ProxyBase& proxy_base, + std::unique_ptr proxy_method_binding, + std::string_view method_name, + FieldOnlyConstructorEnabler) noexcept + : ProxyMethodBase(proxy_base, std::move(proxy_method_binding), method_name), + are_in_arg_ptrs_active_(kCallQueueSize) + { + auto proxy_base_view = ProxyBaseView{proxy_base}; + if (binding_ == nullptr) + { + proxy_base_view.MarkServiceElementBindingInvalid(); + return; + } + } + ~ProxyMethod() final = default; /// \brief A ProxyMethod shall not be copyable. diff --git a/score/mw/com/impl/methods/proxy_method_with_return_type.h b/score/mw/com/impl/methods/proxy_method_with_return_type.h index dc60e7936..412214ef0 100644 --- a/score/mw/com/impl/methods/proxy_method_with_return_type.h +++ b/score/mw/com/impl/methods/proxy_method_with_return_type.h @@ -35,6 +35,9 @@ namespace score::mw::com::impl { +template +class ProxyField; + /// \brief Partial specialization of ProxyMethod for function signatures with no arguments and non-void return /// \tparam ReturnType return type of the method template @@ -45,6 +48,15 @@ class ProxyMethod final : public ProxyMethodBase // This enables us to hide unnecessary internals from the end-user. // coverity[autosar_cpp14_a11_3_1_violation] friend class ProxyMethodView; + friend class ProxyField; + friend class ProxyField; + friend class ProxyField; + friend class ProxyField; + + // Empty struct that is used to make the non-registering ctor only accessible to ProxyField (as it is a friend). + struct FieldOnlyConstructorEnabler + { + }; public: ProxyMethod(ProxyBase& proxy_base, std::string_view method_name) noexcept @@ -77,6 +89,25 @@ class ProxyMethod final : public ProxyMethodBase } } + /// \brief Ctor for ProxyMethod that is used by ProxyField for the "dispatch method" of a field-getter. This method + /// does not register the method in the ProxyBase's method map, since registration in the correct field map is done + /// by ProxyField ctor. This is achieved by the FieldOnlyConstructorEnabler tag type, which makes clear, that this + /// ctor should only be used by ProxyField (this is enforced by FieldOnlyConstructorEnabler only visible to + /// ProxyField due to it being a friend). + ProxyMethod(ProxyBase& proxy_base, + std::unique_ptr proxy_method_binding, + std::string_view method_name, + FieldOnlyConstructorEnabler) noexcept + : ProxyMethodBase(proxy_base, std::move(proxy_method_binding), method_name) + { + auto proxy_base_view = ProxyBaseView{proxy_base}; + if (binding_ == nullptr) + { + proxy_base_view.MarkServiceElementBindingInvalid(); + return; + } + } + ~ProxyMethod() final = default; /// \brief A ProxyMethod shall not be copyable. diff --git a/score/mw/com/impl/mocking/proxy_event_mock_test.cpp b/score/mw/com/impl/mocking/proxy_event_mock_test.cpp index 485f7748f..4307efb90 100644 --- a/score/mw/com/impl/mocking/proxy_event_mock_test.cpp +++ b/score/mw/com/impl/mocking/proxy_event_mock_test.cpp @@ -29,7 +29,6 @@ namespace score::mw::com::impl { namespace { - using TestSampleType = std::uint32_t; auto kDummyEventFieldName = "MyDummyEventField"; @@ -46,7 +45,14 @@ class ProxyEventFieldMockFixture : public ::testing::Test ProxyEventFieldMockFixture() { - unit_.InjectMock(proxy_service_element_mock_); + if constexpr (std::is_same_v>) + { + unit_.InjectMock(proxy_service_element_mock_); + } + else + { + unit_.InjectEventMock(proxy_service_element_mock_); + } } ProxyEventFieldMock proxy_service_element_mock_{}; @@ -273,6 +279,5 @@ TYPED_TEST(ProxyEventFieldMockFixture, GetNewSamplesReturnsErrorWhenMockReturnsE ASSERT_FALSE(result.has_value()); EXPECT_EQ(result.error(), error_code); } - } // namespace } // namespace score::mw::com::impl diff --git a/score/mw/com/impl/mocking/proxy_wrapper_class_test_view_test.cpp b/score/mw/com/impl/mocking/proxy_wrapper_class_test_view_test.cpp index 674527449..415b80745 100644 --- a/score/mw/com/impl/mocking/proxy_wrapper_class_test_view_test.cpp +++ b/score/mw/com/impl/mocking/proxy_wrapper_class_test_view_test.cpp @@ -170,7 +170,7 @@ TEST_F(ProxyWrapperTestClassCreateFixture, CallingFunctionsOnMockProxyDispatches auto& proxy_field_mock = std::get<0>(fields_tuple).mock; proxy.some_event.InjectMock(proxy_event_mock); proxy.some_event_2.InjectMock(proxy_event_mock_2); - proxy.some_field.InjectMock(proxy_field_mock); + proxy.some_field.InjectEventMock(proxy_field_mock); // Expecting that OfferService will be called on the Proxy mock and Unsubscribe on the event and field mocks EXPECT_CALL(proxy_event_mock, Unsubscribe()); @@ -254,7 +254,7 @@ TEST_F(ProxyWrapperTestClassFieldsOnlyCreateFixture, CallingFunctionsOnMockProxy // and given a mocked proxy was created auto proxy = ProxyWrapperClassTestView::Create(fields_tuple); auto& proxy_field_mock = (std::get<0>(fields_tuple).mock); - proxy.some_field.InjectMock(proxy_field_mock); + proxy.some_field.InjectEventMock(proxy_field_mock); // Expecting that Unsubscribe is called on the field EXPECT_CALL(proxy_field_mock, Unsubscribe()); diff --git a/score/mw/com/impl/plumbing/BUILD b/score/mw/com/impl/plumbing/BUILD index 86f8d29c4..4dc5a4d7d 100644 --- a/score/mw/com/impl/plumbing/BUILD +++ b/score/mw/com/impl/plumbing/BUILD @@ -302,6 +302,7 @@ cc_library( tags = ["FFI"], deps = [ ":i_proxy_field_binding_factory", + ":proxy_method_binding_factory", ":proxy_service_element_binding_factory_impl", "@score_baselibs//score/language/futurecpp", ], diff --git a/score/mw/com/impl/plumbing/i_proxy_field_binding_factory.h b/score/mw/com/impl/plumbing/i_proxy_field_binding_factory.h index b9cf348c9..b6c067e00 100644 --- a/score/mw/com/impl/plumbing/i_proxy_field_binding_factory.h +++ b/score/mw/com/impl/plumbing/i_proxy_field_binding_factory.h @@ -14,6 +14,7 @@ #define SCORE_MW_COM_IMPL_PLUMBING_I_PROXY_FIELD_BINDING_FACTORY_H #include "score/mw/com/impl/instance_identifier.h" +#include "score/mw/com/impl/methods/proxy_method_binding.h" #include "score/mw/com/impl/proxy_base.h" #include "score/mw/com/impl/proxy_event_binding.h" @@ -45,6 +46,20 @@ class IProxyFieldBindingFactory /// \return An instance of ProxyEventBinding or nullptr in case of an error. virtual auto CreateEventBinding(ProxyBase& parent, const std::string_view field_name) noexcept -> std::unique_ptr> = 0; + + /// + /// @param parent + /// @param field_name + /// @return + virtual auto CreateGetMethodBinding(ProxyBase& parent, const std::string_view field_name) noexcept + -> std::unique_ptr = 0; + + /// + /// @param parent + /// @param field_name + /// @return + virtual auto CreateSetMethodBinding(ProxyBase& parent, const std::string_view field_name) noexcept + -> std::unique_ptr = 0; }; } // namespace score::mw::com::impl diff --git a/score/mw/com/impl/plumbing/proxy_field_binding_factory.h b/score/mw/com/impl/plumbing/proxy_field_binding_factory.h index da6fc488f..e0a66f99f 100644 --- a/score/mw/com/impl/plumbing/proxy_field_binding_factory.h +++ b/score/mw/com/impl/plumbing/proxy_field_binding_factory.h @@ -13,6 +13,7 @@ #ifndef SCORE_MW_COM_IMPL_PLUMBING_PROXY_FIELD_BINDING_FACTORY_H #define SCORE_MW_COM_IMPL_PLUMBING_PROXY_FIELD_BINDING_FACTORY_H +#include "score/mw/com/impl/methods/proxy_method_binding.h" #include "score/mw/com/impl/plumbing/i_proxy_field_binding_factory.h" #include "score/mw/com/impl/plumbing/proxy_field_binding_factory_impl.h" #include "score/mw/com/impl/proxy_base.h" @@ -39,6 +40,18 @@ class ProxyFieldBindingFactory final return instance().CreateEventBinding(parent, field_name); } + static std::unique_ptr CreateGetMethodBinding(ProxyBase& parent, + std::string_view field_name) noexcept + { + return instance().CreateGetMethodBinding(parent, field_name); + } + + static std::unique_ptr CreateSetMethodBinding(ProxyBase& parent, + std::string_view field_name) noexcept + { + return instance().CreateSetMethodBinding(parent, field_name); + } + /// \brief Inject a mock IProxyFieldBindingFactory. If a mock is injected, then all calls on /// ProxyFieldBindingFactory will be dispatched to the mock. static void InjectMockBinding(IProxyFieldBindingFactory* const mock) noexcept 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 d0bfd2c58..d444ea3b0 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,21 +13,25 @@ #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/plumbing/i_proxy_field_binding_factory.h" +#include "score/mw/com/impl/plumbing/proxy_method_binding_factory.h" #include "score/mw/com/impl/plumbing/proxy_service_element_binding_factory_impl.h" #include "score/mw/com/impl/proxy_base.h" #include "score/mw/com/impl/proxy_event_binding.h" -#include - #include #include namespace score::mw::com::impl { +namespace detail +{ +constexpr char kGetMethodName[] = "Get"; +constexpr char kSetMethodName[] = "Set"; +} // namespace detail + /// \brief Factory class that dispatches calls to the appropriate binding based on binding information in the /// deployment configuration. template @@ -42,11 +46,17 @@ class ProxyFieldBindingFactoryImpl final : public IProxyFieldBindingFactory> CreateEventBinding( ProxyBase& parent, const std::string_view field_name) noexcept override; + + std::unique_ptr CreateGetMethodBinding(ProxyBase& parent, + const std::string_view field_name) noexcept override; + + std::unique_ptr CreateSetMethodBinding(ProxyBase& parent, + const std::string_view field_name) noexcept override; }; 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 +// 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 @@ -62,6 +72,28 @@ inline std::unique_ptr> ProxyFieldBindingFactoryIm ServiceElementType::FIELD>(parent, field_name); } +template +inline std::unique_ptr ProxyFieldBindingFactoryImpl::CreateGetMethodBinding( + ProxyBase& parent, + const std::string_view field_name) noexcept +{ + // \todo: when the extension in methods are there, where we have an additional method-type enum (get/set/normal + // method) this call needs to be updated -> method name shoud then be field name and get/set is distinguished by the + // additional enum + return ProxyMethodBindingFactory::Create( + parent.GetHandle(), ProxyBaseView{parent}.GetBinding(), detail::kGetMethodName); +} + +template +inline std::unique_ptr ProxyFieldBindingFactoryImpl::CreateSetMethodBinding( + ProxyBase& parent, + const std::string_view field_name) noexcept +{ + // \todo: see above. + return ProxyMethodBindingFactory::Create( + parent.GetHandle(), ProxyBaseView{parent}.GetBinding(), detail::kSetMethodName); +} + } // namespace score::mw::com::impl #endif // SCORE_MW_COM_IMPL_PLUMBING_PROXY_FIELD_BINDING_FACTORY_IMPL_H diff --git a/score/mw/com/impl/plumbing/proxy_field_binding_factory_mock.h b/score/mw/com/impl/plumbing/proxy_field_binding_factory_mock.h index 7ca83ed59..403c5967d 100644 --- a/score/mw/com/impl/plumbing/proxy_field_binding_factory_mock.h +++ b/score/mw/com/impl/plumbing/proxy_field_binding_factory_mock.h @@ -29,6 +29,14 @@ class ProxyFieldBindingFactoryMock : public IProxyFieldBindingFactory, + CreateGetMethodBinding, + (ProxyBase&, std::string_view), + (noexcept, override)); + MOCK_METHOD(std::unique_ptr, + CreateSetMethodBinding, + (ProxyBase&, std::string_view), + (noexcept, override)); }; } // namespace score::mw::com::impl diff --git a/score/mw/com/impl/plumbing/proxy_service_element_binding_factory_impl.h b/score/mw/com/impl/plumbing/proxy_service_element_binding_factory_impl.h index 79b96637c..43dd342dd 100644 --- a/score/mw/com/impl/plumbing/proxy_service_element_binding_factory_impl.h +++ b/score/mw/com/impl/plumbing/proxy_service_element_binding_factory_impl.h @@ -35,25 +35,27 @@ namespace score::mw::com::impl { -template +template // "AUTOSAR C++14 A15-5-3" triggered by std::bad_variant_access. -// Additionally the variant might be valueless_by_exception, which would also cause a std::bad_variant_access, this +// Additionally, the variant might be valueless_by_exception, which would also cause a std::bad_variant_access, this // can only happen if any of the variants throw exception during construction. Since we do not throw exceptions, // this can not happen, and therefore it is not possible for std::visit to throw an exception. // // The return type of the template function does not depend on the type of parameters. // // -// "AUTOSAR C++14 A8-2-1" This is not a safetey issue. The rationall only outlines code style improvements, which would +// "AUTOSAR C++14 A8-2-1" This is not a safety issue. The rational only outlines code style improvements, which would // not be present here. // // coverity[autosar_cpp14_a15_5_3_violation] // coverity[autosar_cpp14_a8_2_1_violation] -std::unique_ptr CreateProxyServiceElement( +std::unique_ptr CreateProxyServiceElement( ProxyBase& parent, const std::string_view service_element_name) noexcept { - using ReturnType = std::unique_ptr; + using ReturnType = std::unique_ptr; const HandleType& handle = parent.GetHandle(); const auto& type_deployment = handle.GetServiceTypeDeployment(); @@ -64,7 +66,7 @@ std::unique_ptr CreateProxyServiceElement( if (lola_parent == nullptr) { score::mw::log::LogError("lola") << "Proxy service element could not be created because parent proxy " - "binding is a nullptr."; + "binding is a nullptr."; return nullptr; } @@ -72,7 +74,7 @@ std::unique_ptr CreateProxyServiceElement( const auto* const lola_service_instance_id = std::get_if(&(instance_id.binding_info_)); SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE(lola_service_instance_id != nullptr, - "ServiceInstanceId does not contain lola binding."); + "ServiceInstanceId does not contain lola binding."); const auto lola_service_element_id = GetServiceElementId(lola_type_deployment, std::string{service_element_name}); @@ -80,7 +82,7 @@ std::unique_ptr CreateProxyServiceElement( lola_service_element_id, lola_service_instance_id->GetId(), element_type}; - return std::make_unique(*lola_parent, element_fq_id, service_element_name); + return std::make_unique(*lola_parent, element_fq_id, service_element_name); }, [](const score::cpp::blank&) noexcept -> ReturnType { return nullptr; diff --git a/score/mw/com/impl/proxy_event.h b/score/mw/com/impl/proxy_event.h index 4b42cefb8..6cccece51 100644 --- a/score/mw/com/impl/proxy_event.h +++ b/score/mw/com/impl/proxy_event.h @@ -40,7 +40,7 @@ namespace score::mw::com::impl // False Positive: this is a normal forward declaration. // Which is used to avoid cyclic dependency with proxy_field.h // coverity[autosar_cpp14_m3_2_3_violation] -template +template class ProxyField; /// \brief This is the user-visible class of an event that is part of a proxy. It contains ProxyEvent functionality that @@ -54,15 +54,16 @@ template class ProxyEvent final : public ProxyEventBase { template - // Design decission: This friend class provides a view on the internals of ProxyEvent. - // This enables us to hide unncecessary internals from the enduser. + // Design decision: This friend class provides a view on the internals of ProxyEvent. + // This enables us to hide unnecessary internals from the end user. // coverity[autosar_cpp14_a11_3_1_violation] friend class ProxyEventView; - // Design decission: ProxyField uses composition pattern to reuse code from ProxyEvent. These two classes also have + // Design decision: ProxyField uses composition pattern to reuse code from ProxyEvent. These two classes also have // shared private APIs which necessitates the use of the friend keyword. // coverity[autosar_cpp14_a11_3_1_violation] - friend class ProxyField; + template + friend class ProxyField; // Empty struct that is used to make the second constructor only accessible to ProxyField (as it is a friend). struct FieldOnlyConstructorEnabler diff --git a/score/mw/com/impl/proxy_field.h b/score/mw/com/impl/proxy_field.h index 93d47eeca..b41d5576f 100644 --- a/score/mw/com/impl/proxy_field.h +++ b/score/mw/com/impl/proxy_field.h @@ -13,6 +13,7 @@ #ifndef SCORE_MW_COM_IMPL_PROXY_FIELD_H #define SCORE_MW_COM_IMPL_PROXY_FIELD_H +#include "score/mw/com/impl/methods/proxy_method_with_return_type.h" #include "score/mw/com/impl/plumbing/proxy_field_binding_factory.h" #include "score/mw/com/impl/plumbing/sample_ptr.h" #include "score/mw/com/impl/proxy_event.h" @@ -33,6 +34,22 @@ namespace score::mw::com::impl { +namespace detail +{ +/// Tag types for constructor overload disambiguation based on EnableGet/EnableSet template parameters +struct EnableBothTag +{ +}; +struct EnableGetOnlyTag +{ +}; +struct EnableSetOnlyTag +{ +}; +struct EnableNeitherTag +{ +}; +} // namespace detail // Suppress "AUTOSAR C++14 M3-2-3" rule finding. This rule states: "An identifier with external linkage shall have // exactly one definition". This a forward class declaration. @@ -44,11 +61,18 @@ class ProxyFieldAttorney; /// ProxyEvent. /// /// \tparam SampleDataType Type of data that is transferred by the event. -template +/// \tparam EnableGet Whether the get method shall be enabled for this field. If true, a Get() method will be available. +/// \tparam EnableSet Whether the set method shall be enabled for this field. If true, a Set() method will be available. +/// \tparam EnableNotifier Whether the notifier functionality shall be enabled for this field. Whether this has an +/// effect, depends on the binding that is used. The LoLa/shm-binding ignores this template parameter. +template class ProxyField final : public ProxyFieldBase { // Suppress "AUTOSAR C++14 A11-3-1", The rule declares: "Friend declarations shall not be used". - // Design dessision: The "*Attorney" class is a helper, which sets the internal state of this class accessing + // Design decision: The "*Attorney" class is a helper, which sets the internal state of this class accessing // private members and used for testing purposes only. // coverity[autosar_cpp14_a11_3_1_violation] friend class ProxyFieldAttorney; @@ -56,26 +80,211 @@ class ProxyField final : public ProxyFieldBase public: using FieldType = SampleDataType; - /// Constructor that allows to set the binding directly. + /// Constructor that allows to set the binding directly (both EnableGet and EnableSet are true). /// - /// This is used for testing only. Allows for directly setting the binding, and usually the mock binding is used + /// This is used for testing only. Allows for directly setting the bindings, and usually the mock binding is used /// here. /// - /// \param proxy_binding The binding that shall be associated with this proxy. + /// \param proxy_base Proxy that contains this field + /// \param event_binding The binding that shall be associated with this proxy. + /// \param get_method_binding The get method binding that shall be associated with this proxy. + /// \param set_method_binding The set method binding that shall be associated with this proxy. + /// \param field_name Field name of the field. + /// \param detail::EnableBothTag This parameter is only used for constructor overload disambiguation and has no + /// semantic meaning. The tag has been introduced to disambiguate the ctor for just get enabled or just set enabled, + /// as otherwise we would have multiple ctors with the same signature. We use the same approach for this ctor, + /// although the signature is already different due to the additional set_method_binding parameter, to keep the + /// structure of the ctors consistent. + template > ProxyField(ProxyBase& proxy_base, - std::unique_ptr> proxy_binding, - const std::string_view field_name) + std::unique_ptr> event_binding, + std::unique_ptr get_method_binding, + std::unique_ptr set_method_binding, + const std::string_view field_name, + detail::EnableBothTag = {}) : ProxyField{proxy_base, - std::make_unique>(proxy_base, std::move(proxy_binding), field_name), + std::make_unique>(proxy_base, std::move(event_binding), field_name), + std::make_unique>(proxy_base, std::move(get_method_binding)), + std::make_unique>(proxy_base, std::move(set_method_binding)), field_name} { } - /// \brief Constructs a ProxyField + /// Constructor that allows to set the binding directly (only EnableGet is true). + /// + /// This is used for testing only. Allows for directly setting the bindings, and usually the mock binding is used + /// here. /// /// \param proxy_base Proxy that contains this field - /// \param field_name Field name of the field, taken from the AUTOSAR model - ProxyField(ProxyBase& proxy_base, const std::string_view field_name) + /// \param event_binding The binding that shall be associated with this proxy. + /// \param get_method_binding The get method binding that shall be associated with this proxy. + /// \param field_name Field name of the field. + /// \param detail::EnableGetOnlyTag This parameter is only used for constructor overload disambiguation and has no + /// semantic meaning. The tag has been introduced to disambiguate this ctor for just get enabled from the ctor with + /// just set enabled, as otherwise we would have multiple ctors with the same signature. + template > + ProxyField(ProxyBase& proxy_base, + std::unique_ptr> event_binding, + std::unique_ptr get_method_binding, + const std::string_view field_name, + detail::EnableGetOnlyTag = {}) + : ProxyField{proxy_base, + std::make_unique>(proxy_base, std::move(event_binding), field_name), + std::make_unique>(proxy_base, std::move(get_method_binding)), + field_name} + { + } + + /// Constructor that allows to set the binding directly (only EnableSet is true). + /// + /// This is used for testing only. Allows for directly setting the bindings, and usually the mock binding is used + /// here. + /// + /// \param proxy_base Proxy that contains this field + /// \param event_binding The binding that shall be associated with this proxy. + /// \param set_method_binding The set method binding that shall be associated with this proxy. + /// \param field_name Field name of the field. + /// \param detail::EnableGetOnlyTag This parameter is only used for constructor overload disambiguation and has no + /// semantic meaning. The tag has been introduced to disambiguate this ctor for just set enabled from the ctor with + /// just get enabled, as otherwise we would have multiple ctors with the same signature. + template > + ProxyField(ProxyBase& proxy_base, + std::unique_ptr> event_binding, + std::unique_ptr set_method_binding, + const std::string_view field_name, + detail::EnableSetOnlyTag = {}) + : ProxyField{proxy_base, + std::make_unique>(proxy_base, std::move(event_binding), field_name), + std::make_unique>(proxy_base, std::move(set_method_binding)), + field_name} + { + } + + /// Constructor that allows to set the binding directly (both EnableGet and EnableSet are false). + /// + /// This is used for testing only. Allows for directly setting the bindings, and usually the mock binding is used + /// here. + /// + /// \param proxy_base Proxy that contains this field + /// \param event_binding The binding that shall be associated with this proxy. + /// \param field_name Field name of the field. + /// \param detail::EnableBothTag This parameter is only used for constructor overload disambiguation and has no + /// semantic meaning. The tag has been introduced to disambiguate the ctor for just get enabled or just set enabled, + /// as otherwise we would have multiple ctors with the same signature. We use the same approach for this ctor, + /// although the signature is already different due to the additional set_method_binding parameter, to keep the + /// structure of the ctors consistent. + template > + ProxyField(ProxyBase& proxy_base, + std::unique_ptr> event_binding, + const std::string_view field_name, + detail::EnableNeitherTag = {}) + : ProxyField{proxy_base, + std::make_unique>(proxy_base, std::move(event_binding), field_name), + field_name} + { + } + + /// \brief Constructs a ProxyField (both EnableGet and EnableSet are true). Normal ctor that is used in production + /// code. + /// + /// \param proxy_base Proxy that contains this field + /// \param field_name Field name of the field. + /// \param detail::EnableBothTag This parameter is only used for constructor overload disambiguation and has no + /// semantic meaning. + template > + ProxyField(ProxyBase& proxy_base, const std::string_view field_name, detail::EnableBothTag = {}) + : ProxyField{proxy_base, + // we are using a special ctor for the ProxyEvent which does not register the event in the + // ProxyBase's event map, since registration in the correct field map is done by ProxyField ctor. + // Additionally, this ctor initializes the IPC tracing config for the "field-event" correctly. + std::make_unique>( + proxy_base, + ProxyFieldBindingFactory::CreateEventBinding(proxy_base, field_name), + field_name, + typename ProxyEvent::FieldOnlyConstructorEnabler{}), + // we are using a special ctor for the ProxyMethod, which does not register the method in the + // ProxyBase's method map, since registration in the correct field map is done by ProxyField ctor. + // We don't want a field get-method to be registered in the ProxyBase's method map. + std::make_unique>( + proxy_base, + ProxyFieldBindingFactory::CreateGetMethodBinding(proxy_base, field_name), + field_name, + typename ProxyMethod::FieldOnlyConstructorEnabler{}), + // we are using a special ctor for the ProxyMethod, which does not register the method in the + // ProxyBase's method map, since registration in the correct field map is done by ProxyField ctor. + // We don't want a field set-method to be registered in the ProxyBase's method map. + std::make_unique>( + proxy_base, + ProxyFieldBindingFactory::CreateSetMethodBinding(proxy_base, field_name), + field_name, + typename ProxyMethod::FieldOnlyConstructorEnabler{}), + field_name} + { + } + + /// \brief Constructs a ProxyField (only EnableGet is true). Normal ctor that is used in production + /// code. + /// + /// \param proxy_base Proxy that contains this field + /// \param field_name Field name of the field. + /// \param detail::EnableGetOnlyTag This parameter is only used for constructor overload disambiguation and has no + /// semantic meaning. + template > + ProxyField(ProxyBase& proxy_base, const std::string_view field_name, detail::EnableGetOnlyTag = {}) + : ProxyField{proxy_base, + std::make_unique>( + proxy_base, + ProxyFieldBindingFactory::CreateEventBinding(proxy_base, field_name), + field_name, + typename ProxyEvent::FieldOnlyConstructorEnabler{}), + // we are using a special ctor for the ProxyMethod, which does not register the method in the + // ProxyBase's method map, since registration in the correct field map is done by ProxyField ctor. + // We don't want a field get-method to be registered in the ProxyBase's method map. + std::make_unique>( + proxy_base, + ProxyFieldBindingFactory::CreateGetMethodBinding(proxy_base, field_name), + field_name, + typename ProxyMethod::FieldOnlyConstructorEnabler{}), + field_name} + { + } + + /// \brief Constructs a ProxyField (only EnableSet is true). Normal ctor that is used in production + /// code. + /// + /// \param proxy_base Proxy that contains this field + /// \param field_name Field name of the field. + /// \param detail::EnableSetOnlyTag This parameter is only used for constructor overload disambiguation and has no + /// semantic meaning. + template > + ProxyField(ProxyBase& proxy_base, const std::string_view field_name, detail::EnableSetOnlyTag = {}) + : ProxyField{proxy_base, + std::make_unique>( + proxy_base, + ProxyFieldBindingFactory::CreateEventBinding(proxy_base, field_name), + field_name, + typename ProxyEvent::FieldOnlyConstructorEnabler{}), + // we are using a special ctor for the ProxyMethod, which does not register the method in the + // ProxyBase's method map, since registration in the correct field map is done by ProxyField ctor. + // We don't want a field set-method to be registered in the ProxyBase's method map. + std::make_unique>( + proxy_base, + ProxyFieldBindingFactory::CreateSetMethodBinding(proxy_base, field_name), + field_name, + typename ProxyMethod::FieldOnlyConstructorEnabler{}), + field_name} + { + } + + /// \brief Constructs a ProxyField (both EnableGet and EnableSet are false). Normal ctor that is used in production + /// code. + /// + /// \param proxy_base Proxy that contains this field + /// \param field_name Field name of the field. + /// \param detail::EnableNeitherTag This parameter is only used for constructor overload disambiguation and has no + /// semantic meaning. + template > + ProxyField(ProxyBase& proxy_base, const std::string_view field_name, detail::EnableNeitherTag = {}) : ProxyField{proxy_base, std::make_unique>( proxy_base, @@ -88,10 +297,12 @@ class ProxyField final : public ProxyFieldBase /// \brief A ProxyField shall not be copyable ProxyField(const ProxyField&) = delete; + ProxyField& operator=(const ProxyField&) = delete; /// \brief A ProxyField shall be moveable ProxyField(ProxyField&&) noexcept; + ProxyField& operator=(ProxyField&&) & noexcept; ~ProxyField() noexcept = default; @@ -115,7 +326,21 @@ class ProxyField final : public ProxyFieldBase return proxy_event_dispatch_->GetNewSamples(std::forward(receiver), max_num_samples); } - void InjectMock(IProxyEvent& proxy_event_mock) + template ::value>> + score::Result> Get() noexcept + { + return proxy_method_get_dispatch_->operator()(); + } + + template ::value>> + score::Result> Set(SampleDataType& new_field_value) noexcept + { + return proxy_method_set_dispatch_->operator()(new_field_value); + } + + void InjectEventMock(IProxyEvent& proxy_event_mock) { proxy_event_dispatch_->InjectMock(proxy_event_mock); } @@ -126,6 +351,62 @@ class ProxyField final : public ProxyFieldBase /// /// By adding this additional constructor, we can pass a pointer to the proxy_event_dispatch to the base class /// before storing it in this class. + /// + /// This overload is used when both EnableGet and EnableSet are true. + template > + ProxyField(ProxyBase& proxy_base, + std::unique_ptr> proxy_event_dispatch, + std::unique_ptr> proxy_method_get_dispatch, + std::unique_ptr> proxy_method_set_dispatch, + const std::string_view field_name) + : ProxyFieldBase{proxy_base, proxy_event_dispatch.get(), field_name}, + proxy_event_dispatch_{std::move(proxy_event_dispatch)}, + proxy_method_get_dispatch_{std::move(proxy_method_get_dispatch)}, + proxy_method_set_dispatch_{std::move(proxy_method_set_dispatch)} + { + // Defensive programming: This assertion is also in the constructor of ProxyFieldBase. + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(proxy_event_dispatch_ != nullptr); + + ProxyBaseView proxy_base_view{proxy_base}; + proxy_base_view.RegisterField(field_name, *this); + } + + /// \brief Private constructor overload for when only EnableGet is true. + template > + ProxyField(ProxyBase& proxy_base, + std::unique_ptr> proxy_event_dispatch, + std::unique_ptr> proxy_method_get_dispatch, + const std::string_view field_name) + : ProxyFieldBase{proxy_base, proxy_event_dispatch.get(), field_name}, + proxy_event_dispatch_{std::move(proxy_event_dispatch)}, + proxy_method_get_dispatch_{std::move(proxy_method_get_dispatch)} + { + // Defensive programming: This assertion is also in the constructor of ProxyFieldBase. + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(proxy_event_dispatch_ != nullptr); + + ProxyBaseView proxy_base_view{proxy_base}; + proxy_base_view.RegisterField(field_name, *this); + } + + /// \brief Private constructor overload for when only EnableSet is true. + template > + ProxyField(ProxyBase& proxy_base, + std::unique_ptr> proxy_event_dispatch, + std::unique_ptr> proxy_method_set_dispatch, + const std::string_view field_name) + : ProxyFieldBase{proxy_base, proxy_event_dispatch.get(), field_name}, + proxy_event_dispatch_{std::move(proxy_event_dispatch)}, + proxy_method_set_dispatch_{std::move(proxy_method_set_dispatch)} + { + // Defensive programming: This assertion is also in the constructor of ProxyFieldBase. + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(proxy_event_dispatch_ != nullptr); + + ProxyBaseView proxy_base_view{proxy_base}; + proxy_base_view.RegisterField(field_name, *this); + } + + /// \brief Private constructor overload for when both EnableGet and EnableSet are false. + template > ProxyField(ProxyBase& proxy_base, std::unique_ptr> proxy_event_dispatch, const std::string_view field_name) @@ -144,13 +425,35 @@ class ProxyField final : public ProxyFieldBase // avoid dangling references. std::unique_ptr> proxy_event_dispatch_; + struct empty + { + }; + + using ProxyGetMethodType = std::conditional_t>, empty>; + using ProxySetMethodType = std::conditional_t>, empty>; + + // Public ProxyField getter calls will be dispatched to proxy_method_get_dispatch_. The get-method signature is + // FieldType(void). i.e. no in-arg and FieldType return type. + // in case getter is disabled (EnableGet = false) the type of proxy_method_get_dispatch_ is empty + // When switching to C++20, we can use the [[no_unique_address]] attribute for the empty struct to avoid any + // memory overhead in case the getter/setter is disabled. + ProxyGetMethodType proxy_method_get_dispatch_; + // Public ProxyField setter calls will be dispatched to proxy_method_set_dispatch_. The set-method signature is + // FieldType(FieldType). i.e. FieldType in-arg and also FieldType return type -> which represents the new value of + // the field after the set call (provider side may have decided to adjust the provided value, e.g. to fit to a + // certain range or to apply some transformation). + // in case setter is disabled (EnableSet = false) the type of proxy_method_set_dispatch_ is empty + // When switching to C++20, we can use the [[no_unique_address]] attribute for the empty struct to avoid any + // memory overhead in case the getter/setter is disabled. + ProxySetMethodType proxy_method_set_dispatch_; + static_assert(std::is_same>>::value, "proxy_event_dispatch_ needs to be a unique_ptr since we pass a pointer to it to ProxyFieldBase, so " "we must ensure that it doesn't move when the ProxyField is moved to avoid dangling references. "); }; -template -ProxyField::ProxyField(ProxyField&& other) noexcept +template +ProxyField::ProxyField(ProxyField&& other) noexcept : ProxyFieldBase(std::move(static_cast(other))), proxy_event_dispatch_(std::move(other.proxy_event_dispatch_)) { @@ -159,13 +462,14 @@ ProxyField::ProxyField(ProxyField&& other) noexcept proxy_base_view.UpdateField(field_name_, *this); } -template +template // Suppress "AUTOSAR C++14 A6-2-1" rule violation. The rule states "Move and copy assignment operators shall either move // or respectively copy base classes and data members of a class, without any side effects." // Rationale: The parent proxy stores a reference to the ProxyEvent. The address that is pointed to must be // updated when the ProxyField is moved. Therefore, side effects are required. // coverity[autosar_cpp14_a6_2_1_violation] -auto ProxyField::operator=(ProxyField&& other) & noexcept -> ProxyField& +auto ProxyField::operator=(ProxyField&& other) & noexcept + -> ProxyField& { if (this != &other) { @@ -178,7 +482,6 @@ auto ProxyField::operator=(ProxyField&& other) & noexcept -> ProxyFie } return *this; } - } // namespace score::mw::com::impl #endif // SCORE_MW_COM_IMPL_PROXY_FIELD_H diff --git a/score/mw/com/impl/proxy_field_test.cpp b/score/mw/com/impl/proxy_field_test.cpp index e637d19fd..da1ea69a8 100644 --- a/score/mw/com/impl/proxy_field_test.cpp +++ b/score/mw/com/impl/proxy_field_test.cpp @@ -19,6 +19,7 @@ #include "score/mw/com/impl/proxy_field.h" +#include "score/mw/com/impl/mocking/proxy_event_mock.h" #include "score/mw/com/impl/runtime.h" #include "score/mw/com/impl/runtime_mock.h" #include "score/mw/com/impl/test/binding_factory_resources.h" @@ -33,26 +34,88 @@ namespace score::mw::com::impl namespace { +const ServiceTypeDeployment kEmptyTypeDeployment{score::cpp::blank{}}; +const ServiceIdentifierType kFooservice{make_ServiceIdentifierType("foo")}; +const auto kInstanceSpecifier = InstanceSpecifier::Create(std::string{"abc/abc/TirePressurePort"}).value(); +const ServiceInstanceDeployment kEmptyInstanceDeployment{kFooservice, + LolaServiceInstanceDeployment{LolaServiceInstanceId{10U}}, + QualityType::kASIL_QM, + kInstanceSpecifier}; +const auto kFieldName{"DummyField"}; + using namespace ::testing; using TestSampleType = std::uint8_t; -TEST(ProxyFieldTest, NotCopyable) +// Type list containing all 8 combinations of EnableGet, EnableSet, EnableNotifier +using ProxyFieldTypes = ::testing::Types, + ProxyField, + ProxyField, + ProxyField, + ProxyField, + ProxyField, + ProxyField, + ProxyField>; + +template +class ProxyFieldTypedTest : public ::testing::Test { - RecordProperty("Verifies", "SCR-17397027"); - RecordProperty("Description", "Checks copy semantics for ProxyField"); - RecordProperty("TestType", "Requirements-based test"); - RecordProperty("Priority", "1"); - RecordProperty("DerivationTechnique", "Analysis of requirements"); +}; + +TYPED_TEST_SUITE(ProxyFieldTypedTest, ProxyFieldTypes); - static_assert(!std::is_copy_constructible>::value, "Is wrongly copyable"); - static_assert(!std::is_copy_assignable>::value, "Is wrongly copyable"); +// Helper trait to detect if a type has a Get() resp. Set() method +template +struct HasGetMethod : std::false_type +{ +}; + +template +struct HasGetMethod().template Get())>> : std::true_type +{ +}; + +template +struct HasSetMethod : std::false_type +{ +}; + +template +struct HasSetMethod().template Set( + std::declval()))>> : std::true_type +{ +}; + +TYPED_TEST(ProxyFieldTypedTest, NotCopyable) +{ + this->RecordProperty("Verifies", "SCR-17397027"); + this->RecordProperty("Description", "Checks copy semantics for ProxyField"); + this->RecordProperty("TestType", "Requirements-based test"); + this->RecordProperty("Priority", "1"); + this->RecordProperty("DerivationTechnique", "Analysis of requirements"); + + static_assert(!std::is_copy_constructible::value, "Is wrongly copyable"); + static_assert(!std::is_copy_assignable::value, "Is wrongly copyable"); +} + +TYPED_TEST(ProxyFieldTypedTest, IsMoveable) +{ + static_assert(std::is_move_constructible::value, "Is not move constructible"); + static_assert(std::is_move_assignable::value, "Is not move assignable"); } -TEST(ProxyFieldTest, IsMoveable) +TYPED_TEST(ProxyFieldTypedTest, ProxyFieldContainsPublicFieldType) { - static_assert(std::is_move_constructible>::value, "Is not move constructible"); - static_assert(std::is_move_assignable>::value, "Is not move assignable"); + this->RecordProperty("Verifies", "SCR-17291997"); + this->RecordProperty("Description", + "A ProxyField contains a public member type FieldType which denotes the type of the field."); + this->RecordProperty("TestType", "Requirements-based test"); + this->RecordProperty("Priority", "1"); + this->RecordProperty("DerivationTechnique", "Analysis of requirements"); + + using CustomFieldType = TestSampleType; + static_assert(std::is_same::value, "Incorrect FieldType."); } TEST(ProxyFieldTest, ClassTypeDependsOnFieldDataType) @@ -69,18 +132,71 @@ TEST(ProxyFieldTest, ClassTypeDependsOnFieldDataType) "Class type does not depend on field data type"); } -TEST(ProxyFieldTest, ProxyFieldContainsPublicFieldType) +TEST(ProxyFieldTest, GetMethodExistsWhenEnabled) +{ + RecordProperty("Verifies", "ToDo - link to requirement"); + RecordProperty("Description", "ProxyFields with enabled getter should contain a Get() method."); + RecordProperty("TestType", "Requirements-based test"); + RecordProperty("Priority", "1"); + RecordProperty("DerivationTechnique", "Analysis of requirements"); + + using ProxyFieldWithGet = ProxyField; + + static_assert(HasGetMethod::value, "Get() method does not exist when getter is enabled."); +} + +TEST(ProxyFieldTest, GetMethodDoesNotExistWhenDisabled) { - RecordProperty("Verifies", "SCR-17291997"); - RecordProperty("Description", - "A ProxyField contains a public member type FieldType which denotes the type of the field."); + RecordProperty("Verifies", "ToDo - link to requirement"); + RecordProperty("Description", "ProxyFields with disabled getter should NOT contain a Get() method."); RecordProperty("TestType", "Requirements-based test"); RecordProperty("Priority", "1"); RecordProperty("DerivationTechnique", "Analysis of requirements"); - using CustomFieldType = std::uint16_t; - static_assert(std::is_same::FieldType, CustomFieldType>::value, - "Incorrect FieldType."); + using ProxyFieldWithoutGet = ProxyField; + + static_assert(!HasGetMethod::value, "Get() method should not exist when getter is disabled."); +} + +TEST(ProxyFieldTest, SetMethodExistsWhenEnabled) +{ + RecordProperty("Verifies", "ToDo - link to requirement"); + RecordProperty("Description", "ProxyFields with enabled setter should contain a Set() method."); + RecordProperty("TestType", "Requirements-based test"); + RecordProperty("Priority", "1"); + RecordProperty("DerivationTechnique", "Analysis of requirements"); + + using ProxyFieldWithSet = ProxyField; + + static_assert(HasSetMethod::value, "Set() method does not exist when setter is enabled."); +} + +TEST(ProxyFieldTest, SetMethodDoesNotExistWhenDisabled) +{ + RecordProperty("Verifies", "ToDo - link to requirement"); + RecordProperty("Description", "ProxyFields with disabled setter should NOT contain a Set() method."); + RecordProperty("TestType", "Requirements-based test"); + RecordProperty("Priority", "1"); + RecordProperty("DerivationTechnique", "Analysis of requirements"); + + using ProxyFieldWithoutSet = ProxyField; + + static_assert(!HasSetMethod::value, "Set() method should not exist when setter is disabled."); +} + +TEST(ProxyFieldTest, EventRelatedCallsGetDispatchedToMockProxyEvent) +{ + ProxyBase empty_proxy{std::make_unique(), + make_HandleType(make_InstanceIdentifier(kEmptyInstanceDeployment, kEmptyTypeDeployment))}; + + ProxyField unit{ + empty_proxy, std::make_unique>>(), kFieldName}; + ProxyEventMock proxy_event_mock{}; + unit.InjectEventMock(proxy_event_mock); + + EXPECT_CALL(proxy_event_mock, GetNewSamples(_, _)).WillOnce(Return(Result{1U})); + auto result = unit.GetNewSamples([](SamplePtr sample_ptr) {}, 1U); + ASSERT_TRUE(result.has_value()); } } // namespace diff --git a/score/mw/com/impl/traits.h b/score/mw/com/impl/traits.h index 2da82d454..469adc1ab 100644 --- a/score/mw/com/impl/traits.h +++ b/score/mw/com/impl/traits.h @@ -33,8 +33,8 @@ #include "score/mw/com/impl/skeleton_event.h" #include "score/mw/com/impl/skeleton_field.h" -#include "score/result/result.h" #include "score/mw/log/logging.h" +#include "score/result/result.h" #include @@ -100,14 +100,19 @@ class ProxyWrapperClassTestView; /// typename Trait::template Event struct_event_1_{*this, event_name_0}; /// typename Trait::template Event struct_event_2_{*this, event_name_1}; /// -/// typename Trait::template Field struct_field_1_{*this, field_name_0}; -/// typename Trait::template Field struct_field_2_{*this, field_name_1}; +/// typename Trait::template Field struct_field_1_{*this, +/// field_name_0}; typename Trait::template Field +/// struct_field_2_{*this, field_name_1}; /// /// typename Trait::template Method struct_method_1_{*this, method_name_0}; /// typename Trait::template Method struct_method_2_{*this, method_name_1}; /// /// }; /// +/// Note: enable_getter, enable_setter and enable_notifier are bool template args and only relevant for fields. The +/// enable_notifier template parameter is only relevant for certain bindings, e.g. the LoLa binding does not distinguish +/// between true/false of this template parameter. +/// /// It is then possible to interpret this interface as proxy or skeleton as `using TheProxy = AsProxy`. /// It shall be noted, that the data types used, need to by PolymorphicOffsetPtrAllocator aware. @@ -215,8 +220,9 @@ class SkeletonWrapperClass : public Interface SkeletonWrapperClass skeleton_wrapper(instance_identifier, std::move(skeleton_binding)); if (!skeleton_wrapper.AreBindingsValid()) { - ::score::mw::log::LogError("lola") << "Could not create SkeletonWrapperClass as Skeleton binding or service " - "element bindings could not be created."; + ::score::mw::log::LogError("lola") + << "Could not create SkeletonWrapperClass as Skeleton binding or service " + "element bindings could not be created."; return MakeUnexpected(ComErrc::kBindingFailure); } @@ -267,8 +273,10 @@ class SkeletonWrapperClass : public Interface std::unordered_map>> instance_identifier_creation_results) { - score::cpp::ignore = instance_specifier_creation_results_.emplace(std::move(instance_specifier_creation_results)); - score::cpp::ignore = instance_identifier_creation_results_.emplace(std::move(instance_identifier_creation_results)); + score::cpp::ignore = + instance_specifier_creation_results_.emplace(std::move(instance_specifier_creation_results)); + score::cpp::ignore = + instance_identifier_creation_results_.emplace(std::move(instance_identifier_creation_results)); } static void ClearCreationResults()