diff --git a/score/mw/com/impl/bindings/lola/skeleton_event_test.cpp b/score/mw/com/impl/bindings/lola/skeleton_event_test.cpp index a5ba305a5..821a746b0 100644 --- a/score/mw/com/impl/bindings/lola/skeleton_event_test.cpp +++ b/score/mw/com/impl/bindings/lola/skeleton_event_test.cpp @@ -445,5 +445,56 @@ TEST_F(SkeletonEventTimestampFixture, SendUpdatesTimestampInControlData) << "The second timestamp should be exactly one greater than the first."; } +TEST_F(SkeletonEventTimestampFixture, PrepareOfferInitializesCurrentTimestampFromReopenedControlData) +{ + RecordProperty("Description", + "Checks that a SkeletonEvent which reopens existing shared memory continues the timestamp sequence " + "from the latest timestamp already present in the event control data."); + RecordProperty("TestType", "Unit Test"); + + constexpr bool enforce_max_samples{true}; + constexpr SlotIndexType existing_slot_index{0U}; + constexpr EventSlotStatus::EventTimeStamp existing_latest_timestamp{42U}; + + auto existing_service_data_control_qm = + CreateServiceDataControlWithEvent(fake_element_fq_id_, QualityType::kASIL_QM); + auto existing_service_data_control_asil_b = + CreateServiceDataControlWithEvent(fake_element_fq_id_, QualityType::kASIL_B); + auto existing_service_data_storage = CreateServiceDataStorageWithEvent(fake_element_fq_id_); + + auto& existing_event_control_qm = + GetEventControlFromServiceDataControl(fake_element_fq_id_, *existing_service_data_control_qm); + auto& existing_event_control_asil_b = + GetEventControlFromServiceDataControl(fake_element_fq_id_, *existing_service_data_control_asil_b); + ProviderEventDataControlLocalView<> existing_provider_control_qm{existing_event_control_qm.data_control}; + ProviderEventDataControlLocalView<> existing_provider_control_asil_b{existing_event_control_asil_b.data_control}; + existing_provider_control_qm.EventReady(existing_slot_index, existing_latest_timestamp); + existing_provider_control_asil_b.EventReady(existing_slot_index, existing_latest_timestamp); + + ExpectControlSegmentOpened(*existing_service_data_control_qm, existing_service_data_control_asil_b.get()); + ExpectDataSegmentOpened(existing_service_data_storage); + WithAlreadyConnectedProxy(); + + InitialiseSkeletonEvent(fake_element_fq_id_, fake_event_name_, max_samples_, max_subscribers_, enforce_max_samples); + + std::ignore = skeleton_event_->PrepareOffer(); + + auto allocated_slot_result = skeleton_event_->Allocate(); + ASSERT_TRUE(allocated_slot_result.has_value()); + auto allocated_slot = std::move(allocated_slot_result).value(); + + const impl::SampleAllocateePtrView allocated_slot_view{allocated_slot}; + const auto* const lola_allocated_slot = + allocated_slot_view.template As>(); + ASSERT_NE(lola_allocated_slot, nullptr); + const auto allocated_slot_index = lola_allocated_slot->GetReferencedSlot(); + + const auto send_result = skeleton_event_->Send(std::move(allocated_slot), std::nullopt); + ASSERT_TRUE(send_result.has_value()); + + const EventSlotStatus final_slot_status{existing_provider_control_qm[allocated_slot_index]}; + EXPECT_EQ(final_slot_status.GetTimeStamp(), existing_latest_timestamp + 1U); +} + } // namespace } // namespace score::mw::com::impl::lola diff --git a/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.cpp b/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.cpp index a0c1adf0b..60a17e7f3 100644 --- a/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.cpp +++ b/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.cpp @@ -313,6 +313,32 @@ void SkeletonMockedMemoryFixture::ExpectServiceUsageMarkerFileCreatedOrOpenedAnd EXPECT_CALL(*unistd_mock_, unlink(StrEq(test::kServiceInstanceUsageFilePath))).Times(0); } +void SkeletonMockedMemoryFixture::ExpectControlSegmentOpened(ServiceDataControl& service_data_control_qm, + ServiceDataControl* const service_data_control_asil_b) + noexcept +{ + ON_CALL(*control_qm_shared_memory_resource_mock_, getUsableBaseAddress()) + .WillByDefault(Return(static_cast(&service_data_control_qm))); + ON_CALL(shared_memory_factory_mock_, Open(test::kControlChannelPathQm, true, _)) + .WillByDefault(Return(control_qm_shared_memory_resource_mock_)); + + if (service_data_control_asil_b != nullptr) + { + ON_CALL(*control_asil_b_shared_memory_resource_mock_, getUsableBaseAddress()) + .WillByDefault(Return(static_cast(service_data_control_asil_b))); + ON_CALL(shared_memory_factory_mock_, Open(test::kControlChannelPathAsilB, true, _)) + .WillByDefault(Return(control_asil_b_shared_memory_resource_mock_)); + } +} + +void SkeletonMockedMemoryFixture::ExpectDataSegmentOpened(ServiceDataStorage& service_data_storage) noexcept +{ + ON_CALL(*data_shared_memory_resource_mock_, getUsableBaseAddress()) + .WillByDefault(Return(static_cast(&service_data_storage))); + ON_CALL(shared_memory_factory_mock_, Open(test::kDataChannelPath, true, _)) + .WillByDefault(Return(data_shared_memory_resource_mock_)); +} + std::unique_ptr SkeletonMockedMemoryFixture::CreateServiceDataControlWithEvent( ElementFqId element_fq_id, QualityType quality_type) noexcept diff --git a/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.h b/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.h index 64252e9f3..1a1822a8e 100644 --- a/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.h +++ b/score/mw/com/impl/bindings/lola/test/skeleton_test_resources.h @@ -436,6 +436,11 @@ class SkeletonMockedMemoryFixture : public ::testing::Test void ExpectServiceUsageMarkerFileCreatedOrOpenedAndClosed() noexcept; + void ExpectControlSegmentOpened(ServiceDataControl& service_data_control_qm, + ServiceDataControl* service_data_control_asil_b = nullptr) noexcept; + + void ExpectDataSegmentOpened(ServiceDataStorage& service_data_storage) noexcept; + std::unique_ptr CreateServiceDataControlWithEvent(ElementFqId element_fq_id, QualityType quality_type) noexcept; static EventControl& GetEventControlFromServiceDataControl(ElementFqId element_fq_id,