diff --git a/score/mw/com/impl/skeleton_base_test.cpp b/score/mw/com/impl/skeleton_base_test.cpp index 5f2138b2b..377d63ee0 100644 --- a/score/mw/com/impl/skeleton_base_test.cpp +++ b/score/mw/com/impl/skeleton_base_test.cpp @@ -659,6 +659,9 @@ class DummyField : public SkeletonFieldBase { public: using SkeletonFieldBase::SkeletonFieldBase; + + void UpdateSkeletonReference(SkeletonBase& skeleton_base) noexcept override {} + bool IsInitialValueSaved() const noexcept override { return false; @@ -668,7 +671,7 @@ class DummyField : public SkeletonFieldBase return Result{}; }; - bool IsSetHandlerRegistered() const noexcept override + bool IsSetHandlerMissing() const noexcept override { return false; } diff --git a/score/mw/com/impl/skeleton_field.h b/score/mw/com/impl/skeleton_field.h index 228ab650d..ad9784c18 100644 --- a/score/mw/com/impl/skeleton_field.h +++ b/score/mw/com/impl/skeleton_field.h @@ -118,18 +118,18 @@ class SkeletonField : public SkeletonFieldBase // // \tparam CallableType Any callable (std::function, score::cpp::callback, lambda, ...) with the signature: // void(FieldType& new_value) - // - new_value : the value requested by the proxy. + // - new_value : the value requested by the proxy. This value will be modified in place by the registered handler + // and the new value will be used to update the field. template ::type = 0, typename CallableType> - Result RegisterSetHandler(CallableType&& handler) + Result RegisterSetHandler(CallableType&& set_handler) { static_assert(std::is_invocable_v, "RegisterSetHandler: handler must be callable as void(FieldType& value). " "The argument initially holds the proxy-requested value and may be modified in-place."); - set_handler_ = std::move(handler); - auto wrapped_callback = [this](FieldType& new_value) -> FieldType { + auto wrapped_callback = [this, set_handler = std::move(set_handler)](FieldType& new_value) -> FieldType { // Allow user to validate/modify the value in-place - set_handler_(new_value); + set_handler(new_value); // Store the (possibly modified) value as the latest field value auto update_result = this->Update(new_value); @@ -143,10 +143,41 @@ class SkeletonField : public SkeletonFieldBase }; is_set_handler_registered_ = true; - return set_method_.get()->RegisterHandler(std::move(wrapped_callback)); + return set_method_->RegisterHandler(std::move(wrapped_callback)); + } + + /// \brief Updates the reference to SkeletonBase held by this SkeletonField and also the owned methods. + /// + /// This is necessary when a Skeleton (which owns its events, fields and methods) is moved to a new address. When + /// this happens, the references to the SkeletonBase are pointing to the old address and must be updated. This must + /// be done also for the get and set method since they call a SkeletonMethod constructor which does not register + /// them with the SkeletonBase. Rather, they're considered as part of the SkeletonField and it's the field's + /// responsibility to update their SkeletonBase reference when it's moved. + void UpdateSkeletonReference(SkeletonBase& skeleton_base) noexcept override + { + skeleton_base_ = skeleton_base; + + if (set_method_ != nullptr) + { + set_method_->UpdateSkeletonReference(skeleton_base); + } + if (get_method_ != nullptr) + { + get_method_->UpdateSkeletonReference(skeleton_base); + } } private: + using SetMethodSignature = FieldType(FieldType); + using GetMethodSignature = FieldType(); + + /// \brief Private delegating constructor used by the no-setter public ctor and testing ctor. + SkeletonField(SkeletonBase& parent, + std::unique_ptr> skeleton_event_dispatch, + std::unique_ptr> skeleton_set_method_dispatch, + std::unique_ptr> skeleton_get_method_dispatch, + const std::string_view field_name); + bool IsInitialValueSaved() const noexcept override { return initial_field_value_ != nullptr; @@ -159,59 +190,23 @@ class SkeletonField : public SkeletonFieldBase SkeletonEvent* GetTypedEvent() const noexcept; - std::unique_ptr initial_field_value_; - ISkeletonField* skeleton_field_mock_; - - // Zero-cost conditional storage: unique_ptr when EnableSet=true, zero-size tag when false. - using SetMethodSignature = FieldType(FieldType); - using SetMethodType = - std::conditional_t>, detail::EnableSetOnlyTag>; - SetMethodType set_method_; - - // Stores the user-provided set handler. Kept as a member so that the wrapped - // callback can invoke it via this->set_handler_. The concrete storage type is - // score::cpp::callback with the expected signature so that any callable provided - // to RegisterSetHandler is type-erased here. - // Zero-cost when EnableSet=false. - using SetHandlerStorageType = - std::conditional_t, detail::EnableSetOnlyTag>; - SetHandlerStorageType set_handler_{}; - - // Tracks whether RegisterSetHandler() has been called. Zero-cost when EnableSet=false. - using IsSetHandlerRegisteredType = std::conditional_t; - IsSetHandlerRegisteredType is_set_handler_registered_{}; - - // EnableSet=true: checks the flag; EnableSet=false: no setter, no handler required. - bool IsSetHandlerRegistered() const noexcept override + bool IsSetHandlerMissing() const noexcept override { - if constexpr (EnableSet) + if constexpr (!EnableSet) { - return is_set_handler_registered_; + return false; } - return true; + return !is_set_handler_registered_; } - /// \brief Private delegating constructor used by the setter-enabled public ctor. - template > - SkeletonField(SkeletonBase& parent, - std::unique_ptr> skeleton_event_dispatch, - const std::string_view field_name, - detail::EnableSetOnlyTag); + std::unique_ptr initial_field_value_; + ISkeletonField* skeleton_field_mock_; - /// \brief Private delegating constructor used by the no-setter public ctor and testing ctor. - SkeletonField(SkeletonBase& parent, - std::unique_ptr> skeleton_event_dispatch, - const std::string_view field_name); + // Tracks whether RegisterSetHandler() has been called. + bool is_set_handler_registered_; - // TODO: Move get_method_ initialization into the delegating constructors (like set_method_) once the - // Get handler is implemented. - using GetMethodSignature = FieldType(); - std::unique_ptr> get_method_{ - std::make_unique>( - skeleton_base_.get(), - field_name_, - ::score::mw::com::impl::MethodType::kGet, - typename SkeletonMethod::FieldOnlyConstructorEnabler{})}; + std::unique_ptr> set_method_; + std::unique_ptr> get_method_; }; /// \brief Public ctor — EnableSet=true: delegates to the private ctor that also creates the set method. @@ -229,8 +224,19 @@ SkeletonField::SkeletonField(Skeleton parent, field_name), typename SkeletonEvent::FieldOnlyConstructorEnabler{}), - field_name, - detail::EnableSetOnlyTag{}} + std::make_unique>( + parent, + field_name, + ::score::mw::com::impl::MethodType::kSet, + typename SkeletonMethod::FieldOnlyConstructorEnabler{}), + // TODO: Move get_method_ initialization into the delegating constructors (like set_method_) once the + // Get handler is implemented. + std::make_unique>( + parent, + field_name, + ::score::mw::com::impl::MethodType::kGet, + typename SkeletonMethod::FieldOnlyConstructorEnabler{}), + field_name} { } @@ -249,6 +255,8 @@ SkeletonField::SkeletonField(Skeleton parent, field_name), typename SkeletonEvent::FieldOnlyConstructorEnabler{}), + nullptr, + nullptr, field_name} { } @@ -261,40 +269,25 @@ SkeletonField::SkeletonField( std::unique_ptr> binding) : SkeletonField{skeleton_base, std::make_unique>(skeleton_base, field_name, std::move(binding)), + nullptr, + nullptr, field_name} { } -/// \brief Private delegating ctor — setter enabled. -template -template -SkeletonField::SkeletonField( - SkeletonBase& parent, - std::unique_ptr> skeleton_event_dispatch, - const std::string_view field_name, - detail::EnableSetOnlyTag) - : SkeletonFieldBase{parent, field_name, std::move(skeleton_event_dispatch)}, - initial_field_value_{nullptr}, - skeleton_field_mock_{nullptr} -{ - set_method_ = std::make_unique>( - parent, - field_name_, - ::score::mw::com::impl::MethodType::kSet, - typename SkeletonMethod::FieldOnlyConstructorEnabler{}); - SkeletonBaseView skeleton_base_view{parent}; - skeleton_base_view.RegisterField(field_name, *this); -} - -/// \brief Private delegating ctor — no setter. Receives the already-constructed event. template SkeletonField::SkeletonField( SkeletonBase& parent, std::unique_ptr> skeleton_event_dispatch, + std::unique_ptr> skeleton_set_method_dispatch, + std::unique_ptr> skeleton_get_method_dispatch, const std::string_view field_name) : SkeletonFieldBase{parent, field_name, std::move(skeleton_event_dispatch)}, initial_field_value_{nullptr}, - skeleton_field_mock_{nullptr} + skeleton_field_mock_{nullptr}, + is_set_handler_registered_{false}, + set_method_{std::move(skeleton_set_method_dispatch)}, + get_method_{std::move(skeleton_get_method_dispatch)} { SkeletonBaseView skeleton_base_view{parent}; skeleton_base_view.RegisterField(field_name, *this); @@ -310,9 +303,8 @@ SkeletonField::SkeletonField(Skeleton // coverity[autosar_cpp14_a12_8_3_violation] This is a false-positive. initial_field_value_{std::move(other.initial_field_value_)}, skeleton_field_mock_{other.skeleton_field_mock_}, - set_method_{std::move(other.set_method_)}, - set_handler_{std::move(other.set_handler_)}, is_set_handler_registered_{std::move(other.is_set_handler_registered_)}, + set_method_{std::move(other.set_method_)}, get_method_{std::move(other.get_method_)} { SkeletonBaseView skeleton_base_view{skeleton_base_.get()}; @@ -329,9 +321,8 @@ auto SkeletonField::operator=(Skeleto initial_field_value_ = std::move(other.initial_field_value_); skeleton_field_mock_ = std::move(other.skeleton_field_mock_); - set_method_ = std::move(other.set_method_); - set_handler_ = std::move(other.set_handler_); is_set_handler_registered_ = std::move(other.is_set_handler_registered_); + set_method_ = std::move(other.set_method_); get_method_ = std::move(other.get_method_); SkeletonBaseView skeleton_base_view{skeleton_base_.get()}; skeleton_base_view.UpdateField(field_name_, *this); diff --git a/score/mw/com/impl/skeleton_field_base.h b/score/mw/com/impl/skeleton_field_base.h index 0e0097b11..efe640931 100644 --- a/score/mw/com/impl/skeleton_field_base.h +++ b/score/mw/com/impl/skeleton_field_base.h @@ -50,10 +50,11 @@ class SkeletonFieldBase virtual ~SkeletonFieldBase() = default; - void UpdateSkeletonReference(SkeletonBase& skeleton_base) noexcept - { - skeleton_base_ = skeleton_base; - } + /// \brief Updates the reference to SkeletonBase held by the SkeletonField and also the owned methods. + /// + /// This must happen in the derived class since the derived class owns the methods (this is required since they are + /// templated with the FieldType, which SkeletonFieldBase doesn't know). + virtual void UpdateSkeletonReference(SkeletonBase& skeleton_base) noexcept = 0; /// \brief Used to indicate that the field shall be available to consumer (e.g. binding specific preparation) Result PrepareOffer() noexcept @@ -63,8 +64,8 @@ class SkeletonFieldBase if (!was_prepare_offer_called_) { // If the field is configured with a setter, the application must register - // a set handler before calling OfferService(), otherwise Offer() shall fail. - if (!IsSetHandlerRegistered()) + // a set handler via RegisterSetHandler before calling OfferService(), otherwise Offer() shall fail. + if (IsSetHandlerMissing()) { score::mw::log::LogWarn("lola") << "Set handler must be registered before offering field: " << field_name_; @@ -131,8 +132,9 @@ class SkeletonFieldBase /// \brief Returns whether the initial value has been saved by the user to be used by DoDeferredUpdate virtual bool IsInitialValueSaved() const noexcept = 0; - /// \brief Returns whether a set handler has been registered. - virtual bool IsSetHandlerRegistered() const noexcept = 0; + /// \brief Returns true if a setter has been enabled in the interface and a set handler was not registered via + /// RegisterSetHandler. Otherwise, returns false. + virtual bool IsSetHandlerMissing() const noexcept = 0; /// \brief Sets the initial value of the field. /// diff --git a/score/mw/com/impl/skeleton_field_base_test.cpp b/score/mw/com/impl/skeleton_field_base_test.cpp index c43a501cb..a141d7e36 100644 --- a/score/mw/com/impl/skeleton_field_base_test.cpp +++ b/score/mw/com/impl/skeleton_field_base_test.cpp @@ -64,6 +64,8 @@ class MyDummyField : public SkeletonFieldBase { } + void UpdateSkeletonReference(SkeletonBase& skeleton_base) noexcept override {} + StrictMock* GetMockEventBinding() noexcept { auto* const skeleton_field_base_binding = SkeletonFieldBaseView{*this}.GetEventBinding(); @@ -83,9 +85,9 @@ class MyDummyField : public SkeletonFieldBase return {}; } - bool IsSetHandlerRegistered() const noexcept override + bool IsSetHandlerMissing() const noexcept override { - return true; + return false; } bool was_deferred_update_called_{false}; @@ -95,14 +97,16 @@ class MyDummyField : public SkeletonFieldBase class MyDummyFieldFailingDeferredUpdate final : public MyDummyField { public: + void UpdateSkeletonReference(SkeletonBase& skeleton_base) noexcept override {} + Result DoDeferredUpdate() noexcept override { return MakeUnexpected(ComErrc::kCommunicationLinkError); } - bool IsSetHandlerRegistered() const noexcept override + bool IsSetHandlerMissing() const noexcept override { - return true; + return false; } }; diff --git a/score/mw/com/impl/skeleton_field_test.cpp b/score/mw/com/impl/skeleton_field_test.cpp index 1967b65c0..c62242ac3 100644 --- a/score/mw/com/impl/skeleton_field_test.cpp +++ b/score/mw/com/impl/skeleton_field_test.cpp @@ -12,6 +12,7 @@ ********************************************************************************/ #include "score/mw/com/impl/skeleton_field.h" +#include "method_type.h" #include "score/mw/com/impl/bindings/mock_binding/skeleton_method.h" #include "score/mw/com/impl/method_type.h" #include "score/mw/com/impl/methods/skeleton_method.h" @@ -48,6 +49,7 @@ using ::testing::StrictMock; using ::testing::WithArg; constexpr std::string_view kFieldName{"Field1"}; +const TestSampleType kDummyInitialValue{42}; ServiceIdentifierType kServiceIdentifier{make_ServiceIdentifierType("foo", 1U, 0U)}; std::uint16_t kInstanceId{23U}; @@ -68,6 +70,64 @@ class MyDummySkeleton : public SkeletonBase SkeletonField my_dummy_field_{*this, kFieldName}; }; +class SkeletonFieldTestFixture : public ::testing::Test +{ + protected: + void SetUp() override + { + ON_CALL(skeleton_field_binding_factory_mock_guard_.factory_mock_, + CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) + .WillByDefault(InvokeWithoutArgs([this]() { + return std::make_unique>( + skeleton_field_binding_mock_); + })); + + ON_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(kInstanceIdWithLolaBinding, _, _, MethodType::kGet)) + .WillByDefault(InvokeWithoutArgs([this]() { + return std::make_unique(skeleton_field_get_binding_mock_); + })); + + ON_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(kInstanceIdWithLolaBinding, _, _, MethodType::kSet)) + .WillByDefault(InvokeWithoutArgs([this]() { + return std::make_unique(skeleton_field_set_binding_mock_); + })); + + ON_CALL(skeleton_field_set_binding_mock_, RegisterHandler(_)).WillByDefault(Return(Result{})); + } + + /// \brief Returns a span pointing to storage containing the provided field value + std::pair, score::cpp::span> CreateFieldSetterInArgAndReturnSpans( + const TestSampleType in_arg_value, + const TestSampleType return_value) + { + SCORE_LANGUAGE_FUTURECPP_ASSERT(!in_arg_storage_.has_value()); + SCORE_LANGUAGE_FUTURECPP_ASSERT(!return_storage_.has_value()); + score::cpp::ignore = in_arg_storage_.emplace(in_arg_value); + score::cpp::ignore = return_storage_.emplace(return_value); + + score::cpp::span in_span{reinterpret_cast(&(in_arg_storage_.value())), + sizeof(TestSampleType)}; + score::cpp::span out_span{reinterpret_cast(&(return_storage_.value())), + sizeof(TestSampleType)}; + + return {in_span, out_span}; + } + + RuntimeMockGuard runtime_mock_guard_{}; + + SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard_{}; + SkeletonMethodBindingFactoryMockGuard skeleton_method_binding_factory_mock_guard_{}; + + mock_binding::SkeletonEvent skeleton_field_binding_mock_{}; + mock_binding::SkeletonMethod skeleton_field_get_binding_mock_{}; + mock_binding::SkeletonMethod skeleton_field_set_binding_mock_{}; + + std::optional in_arg_storage_{}; + std::optional return_storage_{}; +}; + TEST(SkeletonFieldTest, NotCopyable) { RecordProperty("Verifies", "SCR-18221574"); @@ -115,7 +175,8 @@ TEST(SkeletonFieldTest, SkeletonFieldContainsPublicSampleType) // When Ticket-104261 is implemented, the Update call does not have to be deferred until OfferService is called. This // test can be reworked to remove the call to PrepareOffer() and simply test Update() before PrepareOffer() is called. -TEST(SkeletonFieldCopyUpdateTest, CallingUpdateBeforeOfferServiceDefersCallToOfferService) +using SkeletonFieldCopyUpdateTest = SkeletonFieldTestFixture; +TEST_F(SkeletonFieldCopyUpdateTest, CallingUpdateBeforeOfferServiceDefersCallToOfferService) { RecordProperty("Verifies", "SCR-17434775, SCR-17563743, SCR-21553554"); RecordProperty("Description", "Checks that calling Update before offer service defers the call to OfferService()."); @@ -123,26 +184,13 @@ TEST(SkeletonFieldCopyUpdateTest, CallingUpdateBeforeOfferServiceDefersCallToOff RecordProperty("Priority", "1"); RecordProperty("DerivationTechnique", "Analysis of requirements"); - const TestSampleType initial_value{42}; bool is_send_called_on_binding{false}; - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - - // Expecting that a SkeletonField binding is created - auto skeleton_field_binding_mock_ptr = std::make_unique>(); - auto& skeleton_field_binding_mock = *skeleton_field_binding_mock_ptr; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); - // and that PrepareOffer() will be called on the event binding - EXPECT_CALL(skeleton_field_binding_mock, PrepareOffer()).WillOnce(Return(score::Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(score::Result{})); // and Send will be called on the event binding with the initial value and returns an empty result - EXPECT_CALL(skeleton_field_binding_mock, Send(initial_value, _)) + EXPECT_CALL(skeleton_field_binding_mock_, Send(kDummyInitialValue, _)) .WillOnce(InvokeWithoutArgs([&is_send_called_on_binding]() noexcept -> Result { is_send_called_on_binding = true; return {}; @@ -152,7 +200,7 @@ TEST(SkeletonFieldCopyUpdateTest, CallingUpdateBeforeOfferServiceDefersCallToOff MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // When the initial value is set via an Update call - const auto update_result = unit.my_dummy_field_.Update(initial_value); + const auto update_result = unit.my_dummy_field_.Update(kDummyInitialValue); // then it does not return an error ASSERT_TRUE(update_result.has_value()); @@ -173,7 +221,7 @@ TEST(SkeletonFieldCopyUpdateTest, CallingUpdateBeforeOfferServiceDefersCallToOff // When Ticket-104261 is implemented, the Update call does not have to be deferred until OfferService is called. This // test can be reworked to remove the call to PrepareOffer() and the deferred processing of Update() and simply test // Update() before PrepareOffer() is called. -TEST(SkeletonFieldCopyUpdateTest, CallingUpdateBeforeOfferServicePropagatesBindingFailureToOfferService) +TEST_F(SkeletonFieldCopyUpdateTest, CallingUpdateBeforeOfferServicePropagatesBindingFailureToOfferService) { RecordProperty("Verifies", "SCR-17434775, SCR-21553554"); RecordProperty("Description", "Checks that calling Update before offer service defers the call to OfferService()."); @@ -181,26 +229,13 @@ TEST(SkeletonFieldCopyUpdateTest, CallingUpdateBeforeOfferServicePropagatesBindi RecordProperty("Priority", "1"); RecordProperty("DerivationTechnique", "Analysis of requirements"); - const TestSampleType initial_value{42}; bool is_send_called_on_binding{false}; - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - - // Expecting that a SkeletonField binding is created - auto skeleton_field_binding_mock_ptr = std::make_unique>(); - auto& skeleton_field_binding_mock = *skeleton_field_binding_mock_ptr; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); - // and that PrepareOffer() will be called on the event binding - EXPECT_CALL(skeleton_field_binding_mock, PrepareOffer()).WillOnce(Return(score::Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(score::Result{})); // and Send will be called on the event binding with the initial value and returns an error - EXPECT_CALL(skeleton_field_binding_mock, Send(initial_value, _)) + EXPECT_CALL(skeleton_field_binding_mock_, Send(kDummyInitialValue, _)) .WillOnce(InvokeWithoutArgs([&is_send_called_on_binding] { is_send_called_on_binding = true; return MakeUnexpected(ComErrc::kInvalidBindingInformation); @@ -210,7 +245,7 @@ TEST(SkeletonFieldCopyUpdateTest, CallingUpdateBeforeOfferServicePropagatesBindi MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // When the initial value is set via an Update call - const auto update_result = unit.my_dummy_field_.Update(initial_value); + const auto update_result = unit.my_dummy_field_.Update(kDummyInitialValue); // then it does not return an error ASSERT_TRUE(update_result.has_value()); @@ -229,7 +264,7 @@ TEST(SkeletonFieldCopyUpdateTest, CallingUpdateBeforeOfferServicePropagatesBindi EXPECT_TRUE(is_send_called_on_binding); } -TEST(SkeletonFieldCopyUpdateTest, CallingUpdateAfterOfferServiceDispatchesToBinding) +TEST_F(SkeletonFieldCopyUpdateTest, CallingUpdateAfterOfferServiceDispatchesToBinding) { RecordProperty("Verifies", "SCR-17434775, SCR-21553375"); RecordProperty("Description", "Checks that calling Update after offer service dispatches to the binding."); @@ -237,35 +272,22 @@ TEST(SkeletonFieldCopyUpdateTest, CallingUpdateAfterOfferServiceDispatchesToBind RecordProperty("Priority", "1"); RecordProperty("DerivationTechnique", "Analysis of requirements"); - const TestSampleType initial_value{42}; - const TestSampleType updated_value{43}; - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - - // Expecting that a SkeletonField binding is created - auto skeleton_field_binding_mock_ptr = std::make_unique>(); - auto& skeleton_field_binding_mock = *skeleton_field_binding_mock_ptr; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); + const TestSampleType updated_value{kDummyInitialValue + 1U}; // and that PrepareOffer() will be called on the event binding - EXPECT_CALL(skeleton_field_binding_mock, PrepareOffer()).WillOnce(Return(score::Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(score::Result{})); // and Send will be called on the event binding with the initial value and returns an empty result - EXPECT_CALL(skeleton_field_binding_mock, Send(initial_value, _)).WillOnce(Return(score::Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, Send(kDummyInitialValue, _)).WillOnce(Return(score::Result{})); // and Send will be called a second time on the event binding with the updated value and returns an empty result - EXPECT_CALL(skeleton_field_binding_mock, Send(updated_value, _)).WillOnce(Return(score::Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, Send(updated_value, _)).WillOnce(Return(score::Result{})); // Given a skeleton created based on a Lola binding MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // When the initial value is set via an Update call - const auto update_result = unit.my_dummy_field_.Update(initial_value); + const auto update_result = unit.my_dummy_field_.Update(kDummyInitialValue); // then it does not return an error ASSERT_TRUE(update_result.has_value()); @@ -283,7 +305,7 @@ TEST(SkeletonFieldCopyUpdateTest, CallingUpdateAfterOfferServiceDispatchesToBind ASSERT_TRUE(update_result_2.has_value()); } -TEST(SkeletonFieldCopyUpdateTest, CallingUpdateAfterOfferServicePropagatesBindingFail) +TEST_F(SkeletonFieldCopyUpdateTest, CallingUpdateAfterOfferServicePropagatesBindingFail) { RecordProperty("Verifies", "SCR-17434775, SCR-21553375"); RecordProperty("Description", @@ -293,36 +315,23 @@ TEST(SkeletonFieldCopyUpdateTest, CallingUpdateAfterOfferServicePropagatesBindin RecordProperty("Priority", "1"); RecordProperty("DerivationTechnique", "Analysis of requirements"); - const TestSampleType initial_value{42}; - const TestSampleType updated_value{43}; - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - - // Expecting that a SkeletonField binding is created - auto skeleton_field_binding_mock_ptr = std::make_unique>(); - auto& skeleton_field_binding_mock = *skeleton_field_binding_mock_ptr; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); + const TestSampleType updated_value{kDummyInitialValue + 1U}; // and that PrepareOffer() will be called on the event binding - EXPECT_CALL(skeleton_field_binding_mock, PrepareOffer()).WillOnce(Return(score::Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(score::Result{})); // and Send will be called on the event binding with the initial value and returns an empty result - EXPECT_CALL(skeleton_field_binding_mock, Send(initial_value, _)).WillOnce(Return(score::Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, Send(kDummyInitialValue, _)).WillOnce(Return(score::Result{})); // and Send will be called a second time on the event binding with the updated value and returns an error - EXPECT_CALL(skeleton_field_binding_mock, Send(updated_value, _)) + EXPECT_CALL(skeleton_field_binding_mock_, Send(updated_value, _)) .WillOnce(Return(MakeUnexpected(ComErrc::kInvalidBindingInformation))); // Given a skeleton created based on a Lola binding MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // When the initial value is set via an Update call - const auto update_result = unit.my_dummy_field_.Update(initial_value); + const auto update_result = unit.my_dummy_field_.Update(kDummyInitialValue); // then it does not return an error ASSERT_TRUE(update_result.has_value()); @@ -342,25 +351,15 @@ TEST(SkeletonFieldCopyUpdateTest, CallingUpdateAfterOfferServicePropagatesBindin } // This test can be removed when Ticket-104261 is implemented. -TEST(SkeletonFieldAllocateTest, CallingAllocateBeforePrepareOfferDoesNotReturnValidSlot) -{ - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); +using SkeletonFieldAllocateTest = SkeletonFieldTestFixture; - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - - // Expecting that a SkeletonField binding is created - auto skeleton_field_binding_mock_ptr = std::make_unique>(); - auto& skeleton_field_binding_mock = *skeleton_field_binding_mock_ptr; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); - - // and that PrepareOffer() will be called on the event binding - EXPECT_CALL(skeleton_field_binding_mock, PrepareOffer()).Times(0); +TEST_F(SkeletonFieldAllocateTest, CallingAllocateBeforePrepareOfferDoesNotReturnValidSlot) +{ + // and that PrepareOffer() will not be called on the event binding + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).Times(0); // and Allocate will not be called on the event binding - EXPECT_CALL(skeleton_field_binding_mock, Allocate()).Times(0); + EXPECT_CALL(skeleton_field_binding_mock_, Allocate()).Times(0); // Given a skeleton created based on a Lola binding MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; @@ -373,7 +372,7 @@ TEST(SkeletonFieldAllocateTest, CallingAllocateBeforePrepareOfferDoesNotReturnVa EXPECT_EQ(slot_result.error(), ComErrc::kBindingFailure); } -TEST(SkeletonFieldAllocateTest, CallingAllocateAfterPrepareOfferDispatchesToBinding) +TEST_F(SkeletonFieldAllocateTest, CallingAllocateAfterPrepareOfferDispatchesToBinding) { RecordProperty("Verifies", "SCR-17434933, SCR-21470600"); RecordProperty("Description", "Checks that calling allocate after prepare offer dispatches to the binding."); @@ -381,35 +380,21 @@ TEST(SkeletonFieldAllocateTest, CallingAllocateAfterPrepareOfferDispatchesToBind RecordProperty("Priority", "1"); RecordProperty("DerivationTechnique", "Analysis of requirements"); - const TestSampleType initial_value{42}; - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - - // Expecting that a SkeletonField binding is created - auto skeleton_field_binding_mock_ptr = std::make_unique>(); - auto& skeleton_field_binding_mock = *skeleton_field_binding_mock_ptr; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); - // and that PrepareOffer() will be called on the event binding - EXPECT_CALL(skeleton_field_binding_mock, PrepareOffer()).WillOnce(Return(score::Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(score::Result{})); // and Send will be called on the event binding with the initial value - EXPECT_CALL(skeleton_field_binding_mock, Send(initial_value, _)); + EXPECT_CALL(skeleton_field_binding_mock_, Send(kDummyInitialValue, _)); // and Allocate will be called again which returns a valid SampleAllocateePtr - EXPECT_CALL(skeleton_field_binding_mock, Allocate()) + EXPECT_CALL(skeleton_field_binding_mock_, Allocate()) .WillOnce(Return(ByMove(MakeSampleAllocateePtr(std::make_unique())))); // Given a skeleton created based on a Lola binding MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // When the initial value is set via an Update call - const auto update_result = unit.my_dummy_field_.Update(initial_value); + const auto update_result = unit.my_dummy_field_.Update(kDummyInitialValue); // which does not return an error EXPECT_TRUE(update_result.has_value()); @@ -427,7 +412,7 @@ TEST(SkeletonFieldAllocateTest, CallingAllocateAfterPrepareOfferDispatchesToBind ASSERT_TRUE(slot_result.has_value()); } -TEST(SkeletonFieldAllocateTest, CallingAllocateAfterPrepareOfferFailsWhenBindingReturnsError) +TEST_F(SkeletonFieldAllocateTest, CallingAllocateAfterPrepareOfferFailsWhenBindingReturnsError) { RecordProperty("Verifies", "SCR-17434933"); RecordProperty("Description", @@ -436,35 +421,21 @@ TEST(SkeletonFieldAllocateTest, CallingAllocateAfterPrepareOfferFailsWhenBinding RecordProperty("Priority", "1"); RecordProperty("DerivationTechnique", "Analysis of requirements"); - const TestSampleType initial_value{42}; - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - - // Expecting that a SkeletonField binding is created - auto skeleton_field_binding_mock_ptr = std::make_unique>(); - auto& skeleton_field_binding_mock = *skeleton_field_binding_mock_ptr; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); - // and that PrepareOffer() will be called on the event binding - EXPECT_CALL(skeleton_field_binding_mock, PrepareOffer()).WillOnce(Return(score::Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(score::Result{})); // and Send will be called on the event binding with the initial value - EXPECT_CALL(skeleton_field_binding_mock, Send(initial_value, _)); + EXPECT_CALL(skeleton_field_binding_mock_, Send(kDummyInitialValue, _)); // and Allocate will be called again which returns a nullptr - EXPECT_CALL(skeleton_field_binding_mock, Allocate()) + EXPECT_CALL(skeleton_field_binding_mock_, Allocate()) .WillOnce(Return(ByMove(MakeUnexpected(ComErrc::kInvalidConfiguration)))); // Given a skeleton created based on a Lola binding MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // When the initial value is set via an Update call - const auto update_result = unit.my_dummy_field_.Update(initial_value); + const auto update_result = unit.my_dummy_field_.Update(kDummyInitialValue); // which does not return an error EXPECT_TRUE(update_result.has_value()); @@ -483,7 +454,9 @@ TEST(SkeletonFieldAllocateTest, CallingAllocateAfterPrepareOfferFailsWhenBinding EXPECT_EQ(slot_result.error(), ComErrc::kBindingFailure); } -TEST(SkeletonFieldZeroCopyUpdateTest, CallingZeroCopyUpdateAfterOfferServiceDispatchesToBinding) +using SkeletonFieldZeroCopyUpdateTest = SkeletonFieldTestFixture; + +TEST_F(SkeletonFieldZeroCopyUpdateTest, CallingZeroCopyUpdateAfterOfferServiceDispatchesToBinding) { RecordProperty("Verifies", "SCR-17434778, SCR-21553623"); RecordProperty("Description", @@ -492,33 +465,20 @@ TEST(SkeletonFieldZeroCopyUpdateTest, CallingZeroCopyUpdateAfterOfferServiceDisp RecordProperty("Priority", "1"); RecordProperty("DerivationTechnique", "Analysis of requirements"); - const TestSampleType initial_value{42}; - const TestSampleType new_value{52}; - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - - // Expecting that a SkeletonField binding is created - auto skeleton_field_binding_mock_ptr = std::make_unique>(); - auto& skeleton_field_binding_mock = *skeleton_field_binding_mock_ptr; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); + const TestSampleType new_value{kDummyInitialValue + 1U}; // and that PrepareOffer() will be called on the event binding - EXPECT_CALL(skeleton_field_binding_mock, PrepareOffer()).WillOnce(Return(score::Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(score::Result{})); // and Send will be called on the event binding with the initial value - EXPECT_CALL(skeleton_field_binding_mock, Send(initial_value, _)); + EXPECT_CALL(skeleton_field_binding_mock_, Send(kDummyInitialValue, _)); // and Allocate will be called again which returns a valid SampleAllocateePtr - EXPECT_CALL(skeleton_field_binding_mock, Allocate()) + EXPECT_CALL(skeleton_field_binding_mock_, Allocate()) .WillOnce(Return(ByMove(MakeSampleAllocateePtr(std::make_unique())))); // and Send will be called a second time on the event binding with a new value which returns an empty result - EXPECT_CALL(skeleton_field_binding_mock, Send(An>(), _)) + EXPECT_CALL(skeleton_field_binding_mock_, Send(An>(), _)) .WillOnce(WithArg<0>(Invoke([new_value](SampleAllocateePtr sample_ptr) -> Result { EXPECT_EQ(*sample_ptr, new_value); return {}; @@ -528,7 +488,7 @@ TEST(SkeletonFieldZeroCopyUpdateTest, CallingZeroCopyUpdateAfterOfferServiceDisp MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // When the initial value is set via an Update call - const auto update_result = unit.my_dummy_field_.Update(initial_value); + const auto update_result = unit.my_dummy_field_.Update(kDummyInitialValue); // which does not return an error EXPECT_TRUE(update_result.has_value()); @@ -556,7 +516,7 @@ TEST(SkeletonFieldZeroCopyUpdateTest, CallingZeroCopyUpdateAfterOfferServiceDisp EXPECT_TRUE(new_update_result.has_value()); } -TEST(SkeletonFieldZeroCopyUpdateTest, CallingZeroCopyUpdateAfterOfferServicePropagatesBindingFail) +TEST_F(SkeletonFieldZeroCopyUpdateTest, CallingZeroCopyUpdateAfterOfferServicePropagatesBindingFail) { RecordProperty("Verifies", "SCR-17434778"); RecordProperty( @@ -567,33 +527,20 @@ TEST(SkeletonFieldZeroCopyUpdateTest, CallingZeroCopyUpdateAfterOfferServiceProp RecordProperty("Priority", "1"); RecordProperty("DerivationTechnique", "Analysis of requirements"); - const TestSampleType initial_value{42}; - const TestSampleType new_value{52}; - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - - // Expecting that a SkeletonField binding is created - auto skeleton_field_binding_mock_ptr = std::make_unique>(); - auto& skeleton_field_binding_mock = *skeleton_field_binding_mock_ptr; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); + const TestSampleType new_value{kDummyInitialValue + 1U}; // and that PrepareOffer() will be called on the event binding - EXPECT_CALL(skeleton_field_binding_mock, PrepareOffer()).WillOnce(Return(score::Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(score::Result{})); // and Send will be called on the event binding with the initial value - EXPECT_CALL(skeleton_field_binding_mock, Send(initial_value, _)); + EXPECT_CALL(skeleton_field_binding_mock_, Send(kDummyInitialValue, _)); // and Allocate will be called again which returns a valid SampleAllocateePtr - EXPECT_CALL(skeleton_field_binding_mock, Allocate()) + EXPECT_CALL(skeleton_field_binding_mock_, Allocate()) .WillOnce(Return(ByMove(MakeSampleAllocateePtr(std::make_unique())))); // and Send will be called a second time on the event binding with a new value which returns an error - EXPECT_CALL(skeleton_field_binding_mock, Send(An>(), _)) + EXPECT_CALL(skeleton_field_binding_mock_, Send(An>(), _)) .WillOnce(WithArg<0>(Invoke([new_value](SampleAllocateePtr sample_ptr) -> Result { EXPECT_EQ(*sample_ptr, new_value); return MakeUnexpected(ComErrc::kInvalidBindingInformation); @@ -603,7 +550,7 @@ TEST(SkeletonFieldZeroCopyUpdateTest, CallingZeroCopyUpdateAfterOfferServiceProp MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // When the initial value is set via an Update call - const auto update_result = unit.my_dummy_field_.Update(initial_value); + const auto update_result = unit.my_dummy_field_.Update(kDummyInitialValue); // which does not return an error EXPECT_TRUE(update_result.has_value()); @@ -630,7 +577,9 @@ TEST(SkeletonFieldZeroCopyUpdateTest, CallingZeroCopyUpdateAfterOfferServiceProp EXPECT_EQ(update_result_2.error(), ComErrc::kBindingFailure); } -TEST(SkeletonFieldInitialValueFixture, LatestFieldValueWillBeSetOnPrepareOffer) +using SkeletonFieldInitialValueFixture = SkeletonFieldTestFixture; + +TEST_F(SkeletonFieldInitialValueFixture, LatestFieldValueWillBeSetOnPrepareOffer) { RecordProperty("Verifies", "SCR-22129134"); RecordProperty( @@ -640,32 +589,19 @@ TEST(SkeletonFieldInitialValueFixture, LatestFieldValueWillBeSetOnPrepareOffer) RecordProperty("Priority", "1"); RecordProperty("DerivationTechnique", "Analysis of requirements"); - const TestSampleType initial_value{42}; - const TestSampleType latest_value{43}; - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - - // Expecting that a SkeletonField binding is created - auto skeleton_field_binding_mock_ptr = std::make_unique>(); - auto& skeleton_field_binding_mock = *skeleton_field_binding_mock_ptr; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); + const TestSampleType latest_value{kDummyInitialValue + 1U}; // and that PrepareOffer() will be called on the event binding - EXPECT_CALL(skeleton_field_binding_mock, PrepareOffer()).WillOnce(Return(score::Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(score::Result{})); // and Send will be called only once on the event binding with the latest value - EXPECT_CALL(skeleton_field_binding_mock, Send(latest_value, _)); + EXPECT_CALL(skeleton_field_binding_mock_, Send(latest_value, _)); // Given a skeleton created based on a Lola binding MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // When the initial value is set via an Update call - const auto update_result = unit.my_dummy_field_.Update(initial_value); + const auto update_result = unit.my_dummy_field_.Update(kDummyInitialValue); // which does not return an error EXPECT_TRUE(update_result.has_value()); @@ -683,7 +619,7 @@ TEST(SkeletonFieldInitialValueFixture, LatestFieldValueWillBeSetOnPrepareOffer) EXPECT_TRUE(prepare_offer_result.has_value()); } -TEST(SkeletonFieldInitialValueFixture, OfferingFieldBeforeUpdatingValueReturnsError) +TEST_F(SkeletonFieldInitialValueFixture, OfferingFieldBeforeUpdatingValueReturnsError) { RecordProperty("Verifies", "SCR-17563743"); RecordProperty("Description", "Calling OfferService before setting the field value returns kFieldValueIsNotValid."); @@ -691,20 +627,8 @@ TEST(SkeletonFieldInitialValueFixture, OfferingFieldBeforeUpdatingValueReturnsEr RecordProperty("Priority", "1"); RecordProperty("DerivationTechnique", "Analysis of requirements"); - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - - // Expecting that a SkeletonField binding is created - auto skeleton_field_binding_mock_ptr = std::make_unique>(); - auto& skeleton_field_binding_mock = *skeleton_field_binding_mock_ptr; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); - // and that PrepareOffer() will not be called on the event binding - EXPECT_CALL(skeleton_field_binding_mock, PrepareOffer()).Times(0); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).Times(0); // Given a skeleton created based on a Lola binding MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; @@ -719,33 +643,19 @@ TEST(SkeletonFieldInitialValueFixture, OfferingFieldBeforeUpdatingValueReturnsEr EXPECT_EQ(result.error(), ComErrc::kFieldValueIsNotValid); } -TEST(SkeletonFieldInitialValueFixture, MoveConstructingFieldBeforePrepareOfferWillKeepInitialValue) +TEST_F(SkeletonFieldInitialValueFixture, MoveConstructingFieldBeforePrepareOfferWillKeepInitialValue) { - const TestSampleType initial_value{42}; - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - - // Expecting that a SkeletonField binding is created - auto skeleton_field_binding_mock_ptr = std::make_unique>(); - auto& skeleton_field_binding_mock = *skeleton_field_binding_mock_ptr; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); - // and that PrepareOffer() will be called on the event binding - EXPECT_CALL(skeleton_field_binding_mock, PrepareOffer()).WillOnce(Return(score::Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(score::Result{})); // and Send will be called on the event binding with the initial value - EXPECT_CALL(skeleton_field_binding_mock, Send(initial_value, _)); + EXPECT_CALL(skeleton_field_binding_mock_, Send(kDummyInitialValue, _)); // Given a skeleton created based on a Lola binding MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // When the initial value is set via an Update call - const auto update_result = unit.my_dummy_field_.Update(initial_value); + const auto update_result = unit.my_dummy_field_.Update(kDummyInitialValue); // which does not return an error EXPECT_TRUE(update_result.has_value()); @@ -760,10 +670,9 @@ TEST(SkeletonFieldInitialValueFixture, MoveConstructingFieldBeforePrepareOfferWi EXPECT_TRUE(prepare_offer_result.has_value()); } -TEST(SkeletonFieldInitialValueFixture, MoveAssigningFieldBeforePrepareOfferWillKeepInitialValue) +TEST(SkeletonFieldInitialValueTest, MoveAssigningFieldBeforePrepareOfferWillKeepInitialValue) { - const TestSampleType initial_value{42}; - const TestSampleType initial_value_2{43}; + const TestSampleType kDummyInitialValue_2{kDummyInitialValue + 1U}; RuntimeMockGuard runtime_mock_guard{}; ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); @@ -783,13 +692,13 @@ TEST(SkeletonFieldInitialValueFixture, MoveAssigningFieldBeforePrepareOfferWillK EXPECT_CALL(skeleton_field_binding_mock, PrepareOffer()).WillOnce(Return(score::Result{})); // and Send will be called on the event binding with the initial value from the moved-from field - EXPECT_CALL(skeleton_field_binding_mock, Send(initial_value, _)); + EXPECT_CALL(skeleton_field_binding_mock, Send(kDummyInitialValue, _)); // Given a skeleton created based on a Lola binding MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // When the initial value is set via an Update call - const auto update_result = unit.my_dummy_field_.Update(initial_value); + const auto update_result = unit.my_dummy_field_.Update(kDummyInitialValue); // which does not return an error EXPECT_TRUE(update_result.has_value()); @@ -813,7 +722,7 @@ TEST(SkeletonFieldInitialValueFixture, MoveAssigningFieldBeforePrepareOfferWillK MyDummySkeleton unit_2{std::make_unique(), identifier2}; // When the initial value is set via an Update call - const auto update_result_2 = unit_2.my_dummy_field_.Update(initial_value_2); + const auto update_result_2 = unit_2.my_dummy_field_.Update(kDummyInitialValue_2); // which does not return an error EXPECT_TRUE(update_result_2.has_value()); @@ -827,17 +736,8 @@ TEST(SkeletonFieldInitialValueFixture, MoveAssigningFieldBeforePrepareOfferWillK EXPECT_TRUE(prepare_offer_result.has_value()); } -TEST(SkeletonFieldTest, SkeletonFieldsRegisterThemselvesWithSkeleton) +TEST_F(SkeletonFieldTestFixture, SkeletonFieldsRegisterThemselvesWithSkeleton) { - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - // Expecting that the SkeletonFieldBindingFactory returns a valid binding - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::make_unique>()))); - // Given a skeleton created based on a Lola binding MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; @@ -857,17 +757,8 @@ TEST(SkeletonFieldTest, SkeletonFieldsRegisterThemselvesWithSkeleton) EXPECT_EQ(&field, &unit.my_dummy_field_); } -TEST(SkeletonFieldTest, MovingConstructingSkeletonUpdatesFieldMapReference) +TEST_F(SkeletonFieldTestFixture, MovingConstructingSkeletonUpdatesFieldMapReference) { - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - // Expecting that the SkeletonFieldBindingFactory returns a valid binding - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::make_unique>()))); - // Given a skeleton created based on a Lola binding MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; @@ -889,11 +780,8 @@ TEST(SkeletonFieldTest, MovingConstructingSkeletonUpdatesFieldMapReference) EXPECT_EQ(&field, &unit2.my_dummy_field_); } -TEST(SkeletonFieldTest, MovingAssigningSkeletonUpdatesFieldMapReference) +TEST_F(SkeletonFieldTestFixture, MovingAssigningSkeletonUpdatesFieldMapReference) { - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - ServiceIdentifierType service{make_ServiceIdentifierType("foo2", 1U, 0U)}; const ServiceInstanceDeployment instance_deployment{ service, @@ -903,12 +791,6 @@ TEST(SkeletonFieldTest, MovingAssigningSkeletonUpdatesFieldMapReference) InstanceIdentifier identifier2{make_InstanceIdentifier(instance_deployment, kTypeDeployment)}; // Expecting that the SkeletonFieldBindingFactory returns a valid binding for both Skeletons - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::make_unique>()))); - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, CreateEventBinding(identifier2, _, kFieldName)) - .WillOnce(Return(ByMove(std::make_unique>()))); // Given a skeleton created based on a Lola binding MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; @@ -933,17 +815,9 @@ TEST(SkeletonFieldTest, MovingAssigningSkeletonUpdatesFieldMapReference) EXPECT_EQ(&field, &unit2.my_dummy_field_); } -TEST(SkeletonFieldDeathTest, UpdateWithInvalidFieldNameTriggersTermination) +using SkeletonFieldDeathTest = SkeletonFieldTestFixture; +TEST_F(SkeletonFieldDeathTest, UpdateWithInvalidFieldNameTriggersTermination) { - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - // Expecting that the SkeletonFieldBindingFactory returns a valid binding - SkeletonFieldBindingFactoryMockGuard skeleton_field_binding_factory_mock_guard{}; - EXPECT_CALL(skeleton_field_binding_factory_mock_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::make_unique>()))); - // Given a skeleton created based on a Lola binding MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; @@ -960,7 +834,6 @@ TEST(SkeletonFieldDeathTest, UpdateWithInvalidFieldNameTriggersTermination) } // Helper skeleton that holds an EnableSet=true field (setter-capable field) - class MySetterSkeleton : public SkeletonBase { public: @@ -969,9 +842,8 @@ class MySetterSkeleton : public SkeletonBase SkeletonField my_setter_field_{*this, kFieldName}; }; -// Static type-trait tests for RegisterSetHandler availability - -TEST(SkeletonFieldSetHandlerTest, RegisterSetHandlerOnlyExistsWhenEnableSetIsTrue) +/// gtodo: What is this test testing?? +TEST(SkeletonFieldSetHandlerTypeTraitsTest, RegisterSetHandlerOnlyExistsWhenEnableSetIsTrue) { RecordProperty("Description", "RegisterSetHandler() shall only exist on SkeletonField. " @@ -990,38 +862,14 @@ TEST(SkeletonFieldSetHandlerTest, RegisterSetHandlerOnlyExistsWhenEnableSetIsTru "EnableSet=false and EnableSet=true fields must be different types"); } -// RegisterSetHandler – happy-path: handler forwarded to method binding +using SkeletonFieldSetHandlerTest = SkeletonFieldTestFixture; -TEST(SkeletonFieldSetHandlerTest, RegisterSetHandlerForwardsToMethodBinding) +TEST_F(SkeletonFieldSetHandlerTest, RegisterSetHandlerForwardsToMethodBinding) { - RecordProperty("Description", - "Calling RegisterSetHandler() on an EnableSet=true SkeletonField shall forward " - "the handler registration to the underlying SkeletonMethod binding and return " - "success."); - RecordProperty("TestType", "Requirements-based test"); - RecordProperty("Priority", "1"); - RecordProperty("DerivationTechnique", "Analysis of requirements"); - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard field_binding_factory_guard{}; - EXPECT_CALL(field_binding_factory_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::make_unique>()))); - - // Inject a mock SkeletonMethodBinding so that RegisterHandler is interceptable. - mock_binding::SkeletonMethod method_binding_mock{}; - SkeletonMethodBindingFactoryMockGuard method_binding_factory_guard{}; - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kSet)) - .WillOnce(Return(ByMove(std::make_unique(method_binding_mock)))); - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kGet)) - .WillOnce(Return(ByMove(nullptr))); - - // The method binding's RegisterHandler must be called exactly once and returns success. - EXPECT_CALL(method_binding_mock, RegisterHandler(_)).WillOnce(Return(Result{})); + // Expecting that RegisterHandler is called on the field set method binding which returns success + EXPECT_CALL(skeleton_field_set_binding_mock_, RegisterHandler(_)).WillOnce(Return(Result{})); - // Given a setter-capable skeleton + // Given a skeleton containing a field with a setter enabled MySetterSkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // When RegisterSetHandler is called with a valid (no-op) handler @@ -1031,36 +879,13 @@ TEST(SkeletonFieldSetHandlerTest, RegisterSetHandlerForwardsToMethodBinding) EXPECT_TRUE(result.has_value()); } -// RegisterSetHandler – failure propagation from the method binding - -TEST(SkeletonFieldSetHandlerTest, RegisterSetHandlerPropagatesBindingError) +TEST_F(SkeletonFieldSetHandlerTest, RegisterSetHandlerPropagatesBindingError) { - RecordProperty("Description", - "When the underlying SkeletonMethod binding returns an error from RegisterHandler, " - "RegisterSetHandler() shall propagate that error unchanged."); - RecordProperty("TestType", "Requirements-based test"); - RecordProperty("Priority", "1"); - RecordProperty("DerivationTechnique", "Analysis of requirements"); - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard field_binding_factory_guard{}; - EXPECT_CALL(field_binding_factory_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::make_unique>()))); - - mock_binding::SkeletonMethod method_binding_mock{}; - SkeletonMethodBindingFactoryMockGuard method_binding_factory_guard{}; - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kSet)) - .WillOnce(Return(ByMove(std::make_unique(method_binding_mock)))); - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kGet)) - .WillOnce(Return(ByMove(nullptr))); - - // The method binding returns an error - EXPECT_CALL(method_binding_mock, RegisterHandler(_)) + // Expecting that RegisterHandler is called on the field set method binding which returns an error + EXPECT_CALL(skeleton_field_set_binding_mock_, RegisterHandler(_)) .WillOnce(Return(MakeUnexpected(ComErrc::kCommunicationLinkError))); + // Given a skeleton containing a field with a setter enabled MySetterSkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // When RegisterSetHandler is called @@ -1071,34 +896,12 @@ TEST(SkeletonFieldSetHandlerTest, RegisterSetHandlerPropagatesBindingError) EXPECT_EQ(result.error(), ComErrc::kCommunicationLinkError); } -// PrepareOffer fails when EnableSet=true but no handler has been registered - -TEST(SkeletonFieldSetHandlerTest, PrepareOfferFailsWhenSetHandlerNotRegistered) +TEST_F(SkeletonFieldSetHandlerTest, PrepareOfferFailsWhenSetHandlerNotRegistered) { - RecordProperty("Verifies", "SCR-17563743"); - RecordProperty("Description", - "When a SkeletonField is defined with EnableSet=true and no set handler has been " - "registered, PrepareOffer() shall return kSetHandlerNotSet."); - RecordProperty("TestType", "Requirements-based test"); - RecordProperty("Priority", "1"); - RecordProperty("DerivationTechnique", "Analysis of requirements"); - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard field_binding_factory_guard{}; - EXPECT_CALL(field_binding_factory_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::make_unique>()))); - - SkeletonMethodBindingFactoryMockGuard method_binding_factory_guard{}; - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, _)) - .WillOnce(Return(ByMove(nullptr))) - .WillOnce(Return(ByMove(nullptr))); - + // Given a skeleton containing a field with a setter enabled MySetterSkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; - // Set an initial value so that the initial-value check does not fire first + // and given an initial value was set so that the initial-value check does not fail EXPECT_TRUE(unit.my_setter_field_.Update(TestSampleType{42}).has_value()); // When PrepareOffer is called without having called RegisterSetHandler @@ -1109,50 +912,18 @@ TEST(SkeletonFieldSetHandlerTest, PrepareOfferFailsWhenSetHandlerNotRegistered) EXPECT_EQ(result.error(), ComErrc::kSetHandlerNotSet); } -// PrepareOffer succeeds when EnableSet=true and handler IS registered - -TEST(SkeletonFieldSetHandlerTest, PrepareOfferSucceedsAfterRegisterSetHandler) +TEST_F(SkeletonFieldSetHandlerTest, PrepareOfferSucceedsAfterRegisterSetHandler) { - RecordProperty("Description", - "When an EnableSet=true SkeletonField has a set handler registered and an initial " - "value set, PrepareOffer() shall succeed."); - RecordProperty("TestType", "Requirements-based test"); - RecordProperty("Priority", "1"); - RecordProperty("DerivationTechnique", "Analysis of requirements"); - - const TestSampleType initial_value{7U}; - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard field_binding_factory_guard{}; - auto event_binding_ptr = std::make_unique>(); - auto& event_binding = *event_binding_ptr; - EXPECT_CALL(field_binding_factory_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(event_binding_ptr)))); - - mock_binding::SkeletonMethod method_binding_mock{}; - SkeletonMethodBindingFactoryMockGuard method_binding_factory_guard{}; - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kSet)) - .WillOnce(Return(ByMove(std::make_unique(method_binding_mock)))); - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kGet)) - .WillOnce(Return(ByMove(nullptr))); - - // The binding's RegisterHandler returns success - EXPECT_CALL(method_binding_mock, RegisterHandler(_)).WillOnce(Return(Result{})); - - // PrepareOffer on the event binding and the initial-value Send must succeed - EXPECT_CALL(event_binding, PrepareOffer()).WillOnce(Return(Result{})); - EXPECT_CALL(event_binding, Send(initial_value, _)).WillOnce(Return(Result{})); + const TestSampleType kDummyInitialValue{7U}; + // Given a skeleton containing a field with a setter enabled MySetterSkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // Register a valid (no-op) set handler ASSERT_TRUE(unit.my_setter_field_.RegisterSetHandler([](TestSampleType& /*value*/) noexcept {}).has_value()); // Set the initial field value - ASSERT_TRUE(unit.my_setter_field_.Update(initial_value).has_value()); + ASSERT_TRUE(unit.my_setter_field_.Update(kDummyInitialValue).has_value()); // When PrepareOffer is called const auto result = unit.my_setter_field_.PrepareOffer(); @@ -1161,45 +932,22 @@ TEST(SkeletonFieldSetHandlerTest, PrepareOfferSucceedsAfterRegisterSetHandler) EXPECT_TRUE(result.has_value()); } -// EnableSet=false: PrepareOffer does NOT require a registered set handler - -TEST(SkeletonFieldSetHandlerTest, PrepareOfferSucceedsWithoutHandlerWhenEnableSetIsFalse) +TEST_F(SkeletonFieldSetHandlerTest, PrepareOfferSucceedsWithoutHandlerWhenEnableSetIsFalse) { - RecordProperty("Description", - "When a SkeletonField has EnableSet=false (no setter), PrepareOffer() shall " - "succeed without registering a set handler."); - RecordProperty("TestType", "Requirements-based test"); - RecordProperty("Priority", "1"); - RecordProperty("DerivationTechnique", "Analysis of requirements"); - - const TestSampleType initial_value{5U}; - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard field_binding_factory_guard{}; - auto event_binding_ptr = std::make_unique>(); - auto& event_binding = *event_binding_ptr; - EXPECT_CALL(field_binding_factory_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(event_binding_ptr)))); - - EXPECT_CALL(event_binding, PrepareOffer()).WillOnce(Return(Result{})); - EXPECT_CALL(event_binding, Send(initial_value, _)).WillOnce(Return(Result{})); - - // A non-setter skeleton (EnableSet=false) + // Given a skeleton containing a field without a setter enabled MyDummySkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; - ASSERT_TRUE(unit.my_dummy_field_.Update(initial_value).has_value()); + ASSERT_TRUE(unit.my_dummy_field_.Update(kDummyInitialValue).has_value()); - // PrepareOffer must succeed even without a RegisterSetHandler call + // When PrepareOffer is called without registering a set handler const auto result = unit.my_dummy_field_.PrepareOffer(); + + // Then it succeeds EXPECT_TRUE(result.has_value()); } -// RegisterSetHandler accepts any callable with the expected signature - -TEST(SkeletonFieldSetHandlerTest, RegisterSetHandlerAcceptsAnyCallable) +// gtodo: What is this testing??? +TEST(SkeletonFieldSetHandlerTypeTraitsTest, RegisterSetHandlerAcceptsAnyCallable) { RecordProperty("Description", "RegisterSetHandler() shall accept any callable (lambda, std::function, " @@ -1236,7 +984,7 @@ class CapturingSkeletonMethodBinding : public SkeletonMethodBinding TypeErasedHandler captured_handler_{}; }; -TEST(SkeletonFieldSetHandlerTest, UserCallbackIsInvokedByWrappedHandler) +TEST_F(SkeletonFieldSetHandlerTest, UserCallbackIsInvokedByWrappedHandler) { RecordProperty("Description", "The callback registered with RegisterSetHandler() is invoked by the wrapped " @@ -1248,31 +996,17 @@ TEST(SkeletonFieldSetHandlerTest, UserCallbackIsInvokedByWrappedHandler) const TestSampleType incoming_value{99U}; bool user_callback_called{false}; - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard field_binding_factory_guard{}; - auto event_binding_ptr = std::make_unique>(); - auto& event_binding = *event_binding_ptr; - EXPECT_CALL(field_binding_factory_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(event_binding_ptr)))); - - // PrepareOffer and the deferred Send for the initial value - EXPECT_CALL(event_binding, PrepareOffer()).WillOnce(Return(Result{})); - EXPECT_CALL(event_binding, Send(TestSampleType{1U}, _)).WillOnce(Return(Result{})); - // The wrapped handler also calls Update(incoming_value) → Send on the event binding - EXPECT_CALL(event_binding, Send(incoming_value, _)).WillOnce(Return(Result{})); - // Use a capturing binding so that we can invoke the type-erased handler later auto capturing_binding = std::make_unique(); auto& capturing_binding_ref = *capturing_binding; - - SkeletonMethodBindingFactoryMockGuard method_binding_factory_guard{}; - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kSet)) + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(kInstanceIdWithLolaBinding, _, _, MethodType::kSet)) .WillOnce(Return(ByMove(std::move(capturing_binding)))); - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kGet)) - .WillOnce(Return(ByMove(nullptr))); + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(kInstanceIdWithLolaBinding, _, _, MethodType::kGet)) + .WillOnce(InvokeWithoutArgs([]() { + return std::unique_ptr{}; + })); MySetterSkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; @@ -1290,13 +1024,7 @@ TEST(SkeletonFieldSetHandlerTest, UserCallbackIsInvokedByWrappedHandler) // Simulate the proxy invoking the setter by calling the captured type-erased handler. // The SkeletonMethod serializes the incoming value into a byte span before dispatch. // We replicate that serialization here for the single TestSampleType argument. - using InArgStorage = TestSampleType; - InArgStorage in_arg{incoming_value}; - TestSampleType return_storage{}; - std::optional> in_span{ - score::cpp::span{reinterpret_cast(&in_arg), sizeof(InArgStorage)}}; - std::optional> out_span{ - score::cpp::span{reinterpret_cast(&return_storage), sizeof(TestSampleType)}}; + auto [in_span, out_span] = CreateFieldSetterInArgAndReturnSpans(incoming_value, TestSampleType{}); capturing_binding_ref.captured_handler_(in_span, out_span); @@ -1304,8 +1032,7 @@ TEST(SkeletonFieldSetHandlerTest, UserCallbackIsInvokedByWrappedHandler) EXPECT_TRUE(user_callback_called); } -// Handler wrapping: user callback may modify the value in-place -TEST(SkeletonFieldSetHandlerTest, UserCallbackCanModifyValueInPlace) +TEST_F(SkeletonFieldSetHandlerTest, UserCallbackCanModifyValueInPlace) { RecordProperty("Description", "The set handler callback receives the value by reference. Modifications made " @@ -1318,29 +1045,21 @@ TEST(SkeletonFieldSetHandlerTest, UserCallbackCanModifyValueInPlace) const TestSampleType incoming_value{10U}; const TestSampleType modified_value{20U}; // callback doubles the value - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard field_binding_factory_guard{}; - auto event_binding_ptr = std::make_unique>(); - auto& event_binding = *event_binding_ptr; - EXPECT_CALL(field_binding_factory_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(event_binding_ptr)))); - - EXPECT_CALL(event_binding, PrepareOffer()).WillOnce(Return(Result{})); - EXPECT_CALL(event_binding, Send(TestSampleType{1U}, _)).WillOnce(Return(Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, Send(TestSampleType{1U}, _)).WillOnce(Return(Result{})); // The modified value (20) must be the one forwarded to the event binding - EXPECT_CALL(event_binding, Send(modified_value, _)).WillOnce(Return(Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, Send(modified_value, _)).WillOnce(Return(Result{})); auto capturing_binding = std::make_unique(); auto& capturing_binding_ref = *capturing_binding; - - SkeletonMethodBindingFactoryMockGuard method_binding_factory_guard{}; - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kSet)) + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(kInstanceIdWithLolaBinding, _, _, MethodType::kSet)) .WillOnce(Return(ByMove(std::move(capturing_binding)))); - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kGet)) - .WillOnce(Return(ByMove(nullptr))); + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(kInstanceIdWithLolaBinding, _, _, MethodType::kGet)) + .WillOnce(InvokeWithoutArgs([]() { + return std::unique_ptr{}; + })); MySetterSkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; @@ -1355,19 +1074,13 @@ TEST(SkeletonFieldSetHandlerTest, UserCallbackCanModifyValueInPlace) ASSERT_TRUE(unit.my_setter_field_.PrepareOffer().has_value()); // Invoke the wrapped handler with incoming_value (10) - TestSampleType in_arg{incoming_value}; - TestSampleType return_storage{}; - std::optional> in_span{ - score::cpp::span{reinterpret_cast(&in_arg), sizeof(in_arg)}}; - std::optional> out_span{ - score::cpp::span{reinterpret_cast(&return_storage), sizeof(TestSampleType)}}; + auto [in_span, out_span] = CreateFieldSetterInArgAndReturnSpans(incoming_value, TestSampleType{}); // The handler shall call Send with 20, not 10 capturing_binding_ref.captured_handler_(in_span, out_span); } -// Handler wrapping: Update() failure inside the wrapped handler is logged, not propagated -TEST(SkeletonFieldSetHandlerTest, WrappedHandlerLogsWhenUpdateFails) +TEST_F(SkeletonFieldSetHandlerTest, WrappedHandlerLogsWhenUpdateFails) { RecordProperty("Description", "When the event binding's Send() fails inside the wrapped set handler, the " @@ -1381,30 +1094,22 @@ TEST(SkeletonFieldSetHandlerTest, WrappedHandlerLogsWhenUpdateFails) const TestSampleType incoming_value{55U}; bool user_callback_called{false}; - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard field_binding_factory_guard{}; - auto event_binding_ptr = std::make_unique>(); - auto& event_binding = *event_binding_ptr; - EXPECT_CALL(field_binding_factory_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(event_binding_ptr)))); - - EXPECT_CALL(event_binding, PrepareOffer()).WillOnce(Return(Result{})); - EXPECT_CALL(event_binding, Send(TestSampleType{1U}, _)).WillOnce(Return(Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, Send(TestSampleType{1U}, _)).WillOnce(Return(Result{})); // Simulate Update() failure when the wrapped handler is invoked by the proxy - EXPECT_CALL(event_binding, Send(incoming_value, _)) + EXPECT_CALL(skeleton_field_binding_mock_, Send(incoming_value, _)) .WillOnce(Return(MakeUnexpected(ComErrc::kCommunicationLinkError))); auto capturing_binding = std::make_unique(); auto& capturing_binding_ref = *capturing_binding; - - SkeletonMethodBindingFactoryMockGuard method_binding_factory_guard{}; - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kSet)) + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(kInstanceIdWithLolaBinding, _, _, MethodType::kSet)) .WillOnce(Return(ByMove(std::move(capturing_binding)))); - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kGet)) - .WillOnce(Return(ByMove(nullptr))); + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(kInstanceIdWithLolaBinding, _, _, MethodType::kGet)) + .WillOnce(InvokeWithoutArgs([]() { + return std::unique_ptr{}; + })); MySetterSkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; @@ -1417,12 +1122,7 @@ TEST(SkeletonFieldSetHandlerTest, WrappedHandlerLogsWhenUpdateFails) ASSERT_TRUE(unit.my_setter_field_.Update(TestSampleType{1U}).has_value()); ASSERT_TRUE(unit.my_setter_field_.PrepareOffer().has_value()); - TestSampleType in_arg{incoming_value}; - TestSampleType return_storage{}; - std::optional> in_span{ - score::cpp::span{reinterpret_cast(&in_arg), sizeof(in_arg)}}; - std::optional> out_span{ - score::cpp::span{reinterpret_cast(&return_storage), sizeof(TestSampleType)}}; + auto [in_span, out_span] = CreateFieldSetterInArgAndReturnSpans(incoming_value, TestSampleType{}); // Handler must complete normally even when Update() returns an error capturing_binding_ref.captured_handler_(in_span, out_span); @@ -1431,8 +1131,7 @@ TEST(SkeletonFieldSetHandlerTest, WrappedHandlerLogsWhenUpdateFails) EXPECT_TRUE(user_callback_called); } -// RegisterSetHandler sets is_set_handler_registered_ flag -TEST(SkeletonFieldSetHandlerTest, IsSetHandlerRegisteredFlagIsSetAfterRegistration) +TEST_F(SkeletonFieldSetHandlerTest, IsSetHandlerRegisteredFlagIsSetAfterRegistration) { RecordProperty("Description", "After a successful RegisterSetHandler() call the internal flag " @@ -1441,33 +1140,17 @@ TEST(SkeletonFieldSetHandlerTest, IsSetHandlerRegisteredFlagIsSetAfterRegistrati RecordProperty("Priority", "1"); RecordProperty("DerivationTechnique", "Analysis of requirements"); - const TestSampleType initial_value{3U}; - - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard field_binding_factory_guard{}; - auto event_binding_ptr = std::make_unique>(); - auto& event_binding = *event_binding_ptr; - EXPECT_CALL(field_binding_factory_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(event_binding_ptr)))); + const TestSampleType kDummyInitialValue{3U}; - EXPECT_CALL(event_binding, PrepareOffer()).WillOnce(Return(Result{})); - EXPECT_CALL(event_binding, Send(initial_value, _)).WillOnce(Return(Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, Send(kDummyInitialValue, _)).WillOnce(Return(Result{})); - mock_binding::SkeletonMethod method_binding_mock{}; - SkeletonMethodBindingFactoryMockGuard method_binding_factory_guard{}; - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kSet)) - .WillOnce(Return(ByMove(std::make_unique(method_binding_mock)))); - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kGet)) - .WillOnce(Return(ByMove(nullptr))); - EXPECT_CALL(method_binding_mock, RegisterHandler(_)).WillOnce(Return(Result{})); + EXPECT_CALL(skeleton_field_set_binding_mock_, RegisterHandler(_)).WillOnce(Return(Result{})); MySetterSkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; // Before registration PrepareOffer should fail with kSetHandlerNotSet - ASSERT_TRUE(unit.my_setter_field_.Update(initial_value).has_value()); + ASSERT_TRUE(unit.my_setter_field_.Update(kDummyInitialValue).has_value()); { // Separate scope: verify failure without handler // (We cannot call PrepareOffer twice without a stop-offer in between, so we @@ -1482,8 +1165,7 @@ TEST(SkeletonFieldSetHandlerTest, IsSetHandlerRegisteredFlagIsSetAfterRegistrati EXPECT_TRUE(result.has_value()); } -// RegisterSetHandler called twice: second call replaces the handler -TEST(SkeletonFieldSetHandlerTest, SecondRegisterSetHandlerReplacesHandler) +TEST_F(SkeletonFieldSetHandlerTest, SecondRegisterSetHandlerReplacesHandler) { RecordProperty("Description", "Calling RegisterSetHandler() a second time shall replace the previously stored " @@ -1497,28 +1179,18 @@ TEST(SkeletonFieldSetHandlerTest, SecondRegisterSetHandlerReplacesHandler) bool first_callback_called{false}; bool second_callback_called{false}; - RuntimeMockGuard runtime_mock_guard{}; - ON_CALL(runtime_mock_guard.runtime_mock_, GetTracingFilterConfig()).WillByDefault(Return(nullptr)); - - SkeletonFieldBindingFactoryMockGuard field_binding_factory_guard{}; - auto event_binding_ptr = std::make_unique>(); - auto& event_binding = *event_binding_ptr; - EXPECT_CALL(field_binding_factory_guard.factory_mock_, - CreateEventBinding(kInstanceIdWithLolaBinding, _, kFieldName)) - .WillOnce(Return(ByMove(std::move(event_binding_ptr)))); - - EXPECT_CALL(event_binding, PrepareOffer()).WillOnce(Return(Result{})); - EXPECT_CALL(event_binding, Send(TestSampleType{1U}, _)).WillOnce(Return(Result{})); - EXPECT_CALL(event_binding, Send(incoming_value, _)).WillOnce(Return(Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, PrepareOffer()).WillOnce(Return(Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, Send(TestSampleType{1U}, _)).WillOnce(Return(Result{})); + EXPECT_CALL(skeleton_field_binding_mock_, Send(incoming_value, _)).WillOnce(Return(Result{})); // The method binding is called twice (once per RegisterSetHandler) auto capturing_binding = std::make_unique(); auto& capturing_binding_ref = *capturing_binding; - - SkeletonMethodBindingFactoryMockGuard method_binding_factory_guard{}; - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kSet)) + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(kInstanceIdWithLolaBinding, _, _, MethodType::kSet)) .WillOnce(Return(ByMove(std::move(capturing_binding)))); - EXPECT_CALL(method_binding_factory_guard.factory_mock_, Create(kInstanceIdWithLolaBinding, _, _, MethodType::kGet)) + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(kInstanceIdWithLolaBinding, _, _, MethodType::kGet)) .WillOnce(Return(ByMove(nullptr))); MySetterSkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; @@ -1541,12 +1213,7 @@ TEST(SkeletonFieldSetHandlerTest, SecondRegisterSetHandlerReplacesHandler) ASSERT_TRUE(unit.my_setter_field_.PrepareOffer().has_value()); // Invoke the most-recently captured handler (from the second registration) - TestSampleType in_arg{incoming_value}; - TestSampleType return_storage{}; - std::optional> in_span{ - score::cpp::span{reinterpret_cast(&in_arg), sizeof(in_arg)}}; - std::optional> out_span{ - score::cpp::span{reinterpret_cast(&return_storage), sizeof(TestSampleType)}}; + auto [in_span, out_span] = CreateFieldSetterInArgAndReturnSpans(incoming_value, TestSampleType{}); capturing_binding_ref.captured_handler_(in_span, out_span); @@ -1555,5 +1222,26 @@ TEST(SkeletonFieldSetHandlerTest, SecondRegisterSetHandlerReplacesHandler) EXPECT_TRUE(second_callback_called); } +using SkeletonFieldMoveConstructionFixture = SkeletonFieldTestFixture; +TEST_F(SkeletonFieldMoveConstructionFixture, SecondRegisterSetHandlerReplacesHandler) +{ + // Note. This test verifies that moving a skeleton does not break the getter / setter methods stored within a field. + // When moving, UpdateSkeletonReference must update the references to SkeletonBase in the field instance as well as + // the stored methods. However, the SkeletonBase reference in the methods are only used when moving the method (to + // update the reference to the method in SkeletonBase). Since the methods are stored in the field as unique_ptrs, + // they will never actually be moved. Therefore, with the current implementation, the SkeletonBase reference in the + // getter and setter are never used and so we have no way of ensuring that they are updated correctly. We can only + // verify that the method is still valid after move construction. + + // Given a skeleton containing a field with a setter enabled + MySetterSkeleton unit{std::make_unique(), kInstanceIdWithLolaBinding}; + + // When move constructing the skeleton + MySetterSkeleton unit2{std::move(unit)}; + + // Then the method should still be usable (validated by calling RegisterSetHandler which dispatches to the method) + unit2.my_setter_field_.RegisterSetHandler([](TestSampleType& /*value*/) noexcept {}); +} + } // namespace } // namespace score::mw::com::impl diff --git a/score/mw/com/impl/tracing/skeleton_tracing_test.cpp b/score/mw/com/impl/tracing/skeleton_tracing_test.cpp index f2d395cdb..e987fc35f 100644 --- a/score/mw/com/impl/tracing/skeleton_tracing_test.cpp +++ b/score/mw/com/impl/tracing/skeleton_tracing_test.cpp @@ -67,6 +67,8 @@ class MyDummyField : public SkeletonFieldBase { } + void UpdateSkeletonReference(SkeletonBase& skeleton_base) noexcept override {} + bool IsInitialValueSaved() const noexcept override { return true; @@ -77,9 +79,9 @@ class MyDummyField : public SkeletonFieldBase return {}; } - bool IsSetHandlerRegistered() const noexcept override + bool IsSetHandlerMissing() const noexcept override { - return true; + return false; } }; diff --git a/score/mw/com/impl/traits_test.cpp b/score/mw/com/impl/traits_test.cpp index 7074a6829..f99961ee5 100644 --- a/score/mw/com/impl/traits_test.cpp +++ b/score/mw/com/impl/traits_test.cpp @@ -12,6 +12,7 @@ ********************************************************************************/ #include "score/mw/com/impl/traits.h" +#include "method_type.h" #include "score/mw/com/impl/bindings/mock_binding/proxy_method.h" #include "score/mw/com/impl/bindings/mock_binding/skeleton.h" #include "score/mw/com/impl/bindings/mock_binding/skeleton_method.h" @@ -67,7 +68,7 @@ class MyInterface : public InterfaceTrait::Base using InterfaceTrait::Base::Base; typename InterfaceTrait::template Event some_event{*this, kEventName}; - typename InterfaceTrait::template Field some_field{*this, kFieldName}; + typename InterfaceTrait::template Field some_field{*this, kFieldName}; typename InterfaceTrait::template Method some_method{*this, kMethodName}; }; using MyProxy = AsProxy; @@ -96,7 +97,6 @@ class ProxyCreationFixture : public ::testing::Test public: void SetUp() override { - auto proxy_binding_mock_ptr = std::make_unique(proxy_binding_mock_); auto proxy_event_binding_mock_ptr = std::make_unique>(proxy_event_binding_mock_); @@ -104,6 +104,10 @@ class ProxyCreationFixture : public ::testing::Test std::make_unique>(proxy_field_binding_mock_); auto proxy_method_binding_mock_ptr = std::make_unique(proxy_method_binding_mock_); + auto proxy_field_get_binding_mock_ptr = + std::make_unique(proxy_field_get_binding_mock_); + auto proxy_field_set_binding_mock_ptr = + std::make_unique(proxy_field_set_binding_mock_); auto& runtime_mock = runtime_mock_guard_.runtime_mock_; // By default the runtime configuration has no GetTracingFilterConfig @@ -122,8 +126,12 @@ class ProxyCreationFixture : public ::testing::Test .WillByDefault(Return(ByMove(std::move(proxy_field_binding_mock_ptr)))); // By default the Create call on the ProxyMethodBindingFactory returns valid bindings. - ON_CALL(proxy_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, kMethodName, _)) + ON_CALL(proxy_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, kMethodName, MethodType::kMethod)) .WillByDefault(Return(ByMove(std::move(proxy_method_binding_mock_ptr)))); + ON_CALL(proxy_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, kFieldName, MethodType::kSet)) + .WillByDefault(Return(ByMove(std::move(proxy_field_set_binding_mock_ptr)))); + ON_CALL(proxy_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, kFieldName, MethodType::kGet)) + .WillByDefault(Return(ByMove(std::move(proxy_field_get_binding_mock_ptr)))); // By default that the proxy_binding can successfully call SetupMethods ON_CALL(proxy_binding_mock_, SetupMethods()).WillByDefault(Return(score::Result{})); @@ -146,6 +154,8 @@ class ProxyCreationFixture : public ::testing::Test mock_binding::ProxyEvent proxy_event_binding_mock_{}; mock_binding::ProxyEvent proxy_field_binding_mock_{}; mock_binding::ProxyMethod proxy_method_binding_mock_{}; + mock_binding::ProxyMethod proxy_field_set_binding_mock_{}; + mock_binding::ProxyMethod proxy_field_get_binding_mock_{}; }; TEST(GeneratedProxyTest, NotCopyable) @@ -461,6 +471,10 @@ class SkeletonCreationFixture : public ::testing::Test std::make_unique>(skeleton_field_binding_mock_); auto skeleton_method_binding_mock_ptr = std::make_unique(skeleton_method_binding_mock_); + auto skeleton_field_get_binding_mock_ptr = + std::make_unique(skeleton_field_get_binding_mock_); + auto skeleton_field_set_binding_mock_ptr = + std::make_unique(skeleton_field_set_binding_mock_); auto& runtime_mock = runtime_mock_guard_.runtime_mock_; // By default the runtime configuration has no GetTracingFilterConfig @@ -481,18 +495,15 @@ class SkeletonCreationFixture : public ::testing::Test .WillByDefault(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); // By default the Create call on the SkeletonMethodBindingFactory returns valid bindings. - // Broad catch-all for field get/set method bindings (defined before the specific kMethodName matcher - // so that the more specific ON_CALL takes precedence for kMethodName calls). - ON_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, _, _)) - .WillByDefault(Invoke([this](const InstanceIdentifier&, - SkeletonBinding*, - const std::string_view, - MethodType) -> std::unique_ptr { - return std::make_unique(skeleton_field_method_binding_mock_); - })); ON_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, - Create(identifier_with_valid_binding_, _, kMethodName, _)) + Create(identifier_with_valid_binding_, _, kMethodName, MethodType::kMethod)) .WillByDefault(Return(ByMove(std::move(skeleton_method_binding_mock_ptr)))); + ON_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(identifier_with_valid_binding_, _, kFieldName, MethodType::kSet)) + .WillByDefault(Return(ByMove(std::move(skeleton_field_set_binding_mock_ptr)))); + ON_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(identifier_with_valid_binding_, _, kFieldName, MethodType::kGet)) + .WillByDefault(Return(ByMove(std::move(skeleton_field_get_binding_mock_ptr)))); // By default the runtime configuration resolves instance identifiers resolved_instance_identifiers_.push_back(identifier_with_valid_binding_); @@ -519,7 +530,8 @@ class SkeletonCreationFixture : public ::testing::Test mock_binding::SkeletonEvent skeleton_event_binding_mock_{}; mock_binding::SkeletonEvent skeleton_field_binding_mock_{}; mock_binding::SkeletonMethod skeleton_method_binding_mock_{}; - mock_binding::SkeletonMethod skeleton_field_method_binding_mock_{}; + mock_binding::SkeletonMethod skeleton_field_set_binding_mock_{}; + mock_binding::SkeletonMethod skeleton_field_get_binding_mock_{}; }; using GeneratedSkeletonCreationInstanceSpecifierTestFixture = SkeletonCreationFixture; @@ -539,6 +551,10 @@ TEST_F(GeneratedSkeletonCreationInstanceSpecifierTestFixture, std::make_unique>(skeleton_field_binding_mock_); auto skeleton_method_binding_mock_ptr = std::make_unique(skeleton_method_binding_mock_); + auto skeleton_field_set_binding_mock_ptr = + std::make_unique(skeleton_field_set_binding_mock_); + auto skeleton_field_get_binding_mock_ptr = + std::make_unique(skeleton_field_get_binding_mock_); // Expecting that valid bindings are created for the Skeleton, SkeletonEvent and SkeletonField EXPECT_CALL(skeleton_binding_factory_mock_guard_.factory_mock_, Create(identifier_with_valid_binding_)) @@ -549,15 +565,14 @@ TEST_F(GeneratedSkeletonCreationInstanceSpecifierTestFixture, EXPECT_CALL(skeleton_field_binding_factory_mock_guard_.factory_mock_, CreateEventBinding(identifier_with_valid_binding_, _, kFieldName)) .WillOnce(Return(ByMove(std::move(skeleton_field_binding_mock_ptr)))); - // Field get method binding (not yet fully implemented; set method only exists when EnableSet=true) - EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, _, _)) - .Times(1) - .WillOnce(Invoke([this](const InstanceIdentifier&, SkeletonBinding*, const std::string_view, MethodType) - -> std::unique_ptr { - return std::make_unique(skeleton_field_method_binding_mock_); - })); EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, - Create(identifier_with_valid_binding_, _, kMethodName, _)) + Create(identifier_with_valid_binding_, _, kFieldName, MethodType::kSet)) + .WillOnce(Return(ByMove(std::move(skeleton_field_set_binding_mock_ptr)))); + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(identifier_with_valid_binding_, _, kFieldName, MethodType::kGet)) + .WillOnce(Return(ByMove(std::move(skeleton_field_get_binding_mock_ptr)))); + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(identifier_with_valid_binding_, _, kMethodName, MethodType::kMethod)) .WillOnce(Return(ByMove(std::move(skeleton_method_binding_mock_ptr)))); // When constructing a skeleton with an InstanceSpecifier @@ -644,11 +659,13 @@ TEST_F(GeneratedSkeletonCreationInstanceSpecifierTestFixture, RecordProperty("DerivationTechnique", "Analysis of requirements"); // Expecting that the Create call on the SkeletonMethodBindingFactory returns an invalid binding for the method. - // Field get method binding (not yet fully implemented; set method only exists when EnableSet=true) - EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, _, _)).Times(1); EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, - Create(identifier_with_valid_binding_, _, kMethodName, _)) + Create(_, _, kMethodName, MethodType::kMethod)) .WillOnce(Return(ByMove(nullptr))); + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(identifier_with_valid_binding_, _, kFieldName, MethodType::kSet)); + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(identifier_with_valid_binding_, _, kFieldName, MethodType::kGet)); // When constructing a skeleton with an InstanceSpecifier const auto unit = MySkeleton::Create(kInstanceSpecifier); @@ -777,13 +794,13 @@ TEST_F(GeneratedSkeletonCreationInstanceIdentifierTestFixture, ConstructingFromI TEST_F(GeneratedSkeletonCreationInstanceIdentifierTestFixture, ConstructingFromInvalidSkeletonMethodReturnsError) { - // Expecting that the Create call on the SkeletonMethodBindingFactory returns an invalid binding for the method. - // Field get method binding (not yet fully implemented; set method only exists when EnableSet=true) - EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, _, _)).Times(1); - EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, - Create(identifier_with_valid_binding_, _, kMethodName, _)) + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, _, MethodType::kMethod)) .WillOnce(Return(ByMove(nullptr))); + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(identifier_with_valid_binding_, _, kFieldName, MethodType::kSet)); + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, + Create(identifier_with_valid_binding_, _, kFieldName, MethodType::kGet)); // When constructing a skeleton with an InstanceIdentifier const auto unit = MySkeleton::Create(identifier_with_valid_binding_); @@ -843,6 +860,9 @@ TEST_F(GeneratedSkeletonCreationInstanceIdentifierTestFixture, CanInterpretAsSke // and updating the field value std::ignore = unit.some_field.Update(field_value); + // and registering a field set handler + unit.some_field.RegisterSetHandler([](TestSampleType&) {}); + // and offering the service const auto result = unit.OfferService(); EXPECT_TRUE(result.has_value()); @@ -907,6 +927,9 @@ class GeneratedSkeletonStopOfferServiceRaiiFixture : public SkeletonCreationFixt const auto update_result = skeleton.some_field.Update(field_value); ASSERT_TRUE(update_result.has_value()); + const auto register_result = skeleton.some_field.RegisterSetHandler([](TestSampleType&) {}); + ASSERT_TRUE(register_result.has_value()); + const auto offer_result = skeleton.OfferService(); ASSERT_TRUE(offer_result.has_value()); } @@ -932,15 +955,15 @@ class GeneratedSkeletonStopOfferServiceRaiiFixture : public SkeletonCreationFixt EXPECT_CALL(skeleton_field_binding_factory_mock_guard_.factory_mock_, CreateEventBinding(_, _, _)) .WillOnce(Return(ByMove( std::make_unique>(skeleton_field_binding_mock_)))); - EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, _, _)) + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, _, MethodType::kSet)) .WillOnce( - Return(ByMove(std::make_unique(skeleton_method_binding_mock_)))) - .WillRepeatedly(Invoke([this](const InstanceIdentifier&, - SkeletonBinding*, - const std::string_view, - MethodType) -> std::unique_ptr { - return std::make_unique(skeleton_field_method_binding_mock_); - })); + Return(ByMove(std::make_unique(skeleton_field_set_binding_mock_)))); + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, _, MethodType::kGet)) + .WillOnce( + Return(ByMove(std::make_unique(skeleton_field_get_binding_mock_)))); + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, _, MethodType::kMethod)) + .WillOnce( + Return(ByMove(std::make_unique(skeleton_method_binding_mock_)))); EXPECT_CALL(skeleton_binding_factory_mock_guard_.factory_mock_, Create(_)) .WillOnce(Return(ByMove(std::make_unique(skeleton_binding_mock_2_)))); @@ -950,15 +973,15 @@ class GeneratedSkeletonStopOfferServiceRaiiFixture : public SkeletonCreationFixt EXPECT_CALL(skeleton_field_binding_factory_mock_guard_.factory_mock_, CreateEventBinding(_, _, _)) .WillOnce(Return(ByMove( std::make_unique>(skeleton_field_binding_mock_2_)))); - EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, _, _)) + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, _, MethodType::kSet)) + .WillOnce(Return( + ByMove(std::make_unique(skeleton_field_set_binding_mock_2_)))); + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, _, MethodType::kGet)) + .WillOnce(Return( + ByMove(std::make_unique(skeleton_field_get_binding_mock_2_)))); + EXPECT_CALL(skeleton_method_binding_factory_mock_guard_.factory_mock_, Create(_, _, _, MethodType::kMethod)) .WillOnce( - Return(ByMove(std::make_unique(skeleton_method_binding_mock_2_)))) - .WillRepeatedly(Invoke([this](const InstanceIdentifier&, - SkeletonBinding*, - const std::string_view, - MethodType) -> std::unique_ptr { - return std::make_unique(skeleton_field_method_binding_mock_); - })); + Return(ByMove(std::make_unique(skeleton_method_binding_mock_2_)))); score::cpp::ignore = skeleton_.emplace(CreateService()); score::cpp::ignore = skeleton_2_.emplace(CreateService()); @@ -997,6 +1020,8 @@ class GeneratedSkeletonStopOfferServiceRaiiFixture : public SkeletonCreationFixt mock_binding::SkeletonEvent skeleton_event_binding_mock_2_{}; mock_binding::SkeletonEvent skeleton_field_binding_mock_2_{}; mock_binding::SkeletonMethod skeleton_method_binding_mock_2_{}; + mock_binding::SkeletonMethod skeleton_field_set_binding_mock_2_{}; + mock_binding::SkeletonMethod skeleton_field_get_binding_mock_2_{}; std::optional skeleton_{}; std::optional skeleton_2_{};