From c8f46cde249a687f7e178c06979535426f153be9 Mon Sep 17 00:00:00 2001 From: Christian Eltzschig Date: Wed, 6 Mar 2024 23:44:13 +0100 Subject: [PATCH 1/8] [#129] Store SharedMemoryManagent in separate pointer instead of acquiring it from the base address --- Cargo.toml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 28c3330fa..2689858be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,7 +76,8 @@ windows-sys = { version = "0.48.0", features = ["Win32_Security", "Win32_Securit "Win32_System_SystemServices"] } [profile.release] -strip = true -lto = true -# opt-level = "z" -panic = "abort" +debug = true +# strip = true +# lto = true +# # opt-level = "z" +# panic = "abort" From 5cf8a1944cd33a49e1ad0697dba895b179c803cc Mon Sep 17 00:00:00 2001 From: Christian Eltzschig Date: Wed, 28 Feb 2024 01:52:47 +0100 Subject: [PATCH 2/8] [#133] Introduce id() for all communication entities; write drop tests; fix bug in sample releasing to wrong publisher --- iceoryx2/src/port/listener.rs | 7 + iceoryx2/src/port/notifier.rs | 7 + iceoryx2/src/port/publisher.rs | 5 + iceoryx2/src/port/subscriber.rs | 11 +- iceoryx2/src/sample.rs | 21 +- iceoryx2/src/service/builder/event.rs | 4 +- iceoryx2/src/service/builder/mod.rs | 2 +- .../src/service/builder/publish_subscribe.rs | 24 ++- .../tests/service_publish_subscribe_tests.rs | 179 ++++++++++++++++++ 9 files changed, 242 insertions(+), 18 deletions(-) diff --git a/iceoryx2/src/port/listener.rs b/iceoryx2/src/port/listener.rs index c3bba269d..c5d68f6b5 100644 --- a/iceoryx2/src/port/listener.rs +++ b/iceoryx2/src/port/listener.rs @@ -69,6 +69,7 @@ pub struct Listener { listener: >::Listener, cache: Vec, dynamic_storage: Rc, + port_id: UniqueListenerId, } impl Drop for Listener { @@ -101,6 +102,7 @@ impl Listener { dynamic_listener_handle: None, listener, cache: vec![], + port_id, }; std::sync::atomic::compiler_fence(Ordering::SeqCst); @@ -194,4 +196,9 @@ impl Listener { Ok(self.cache()) } + + /// Returns the [`UniqueListenerId`] of the [`Listener`] + pub fn id(&self) -> UniqueListenerId { + self.port_id + } } diff --git a/iceoryx2/src/port/notifier.rs b/iceoryx2/src/port/notifier.rs index 2f44684e9..695da7ff8 100644 --- a/iceoryx2/src/port/notifier.rs +++ b/iceoryx2/src/port/notifier.rs @@ -142,6 +142,7 @@ pub struct Notifier { default_event_id: EventId, dynamic_storage: Rc, dynamic_notifier_handle: Option, + port_id: UniqueNotifierId, } impl Drop for Notifier { @@ -173,6 +174,7 @@ impl Notifier { listener_list_state: unsafe { UnsafeCell::new(listener_list.get_state()) }, dynamic_storage, dynamic_notifier_handle: None, + port_id, }; if let Err(e) = new_self.populate_listener_channels() { @@ -243,6 +245,11 @@ impl Notifier { Ok(()) } + /// Returns the [`UniqueNotifierId`] of the [`Notifier`] + pub fn id(&self) -> UniqueNotifierId { + self.port_id + } + /// Notifies all [`crate::port::listener::Listener`] connected to the service with the default /// event id provided on creation. /// On success the number of diff --git a/iceoryx2/src/port/publisher.rs b/iceoryx2/src/port/publisher.rs index 9280755b5..d5e2f84b5 100644 --- a/iceoryx2/src/port/publisher.rs +++ b/iceoryx2/src/port/publisher.rs @@ -569,6 +569,11 @@ impl Publisher UniquePublisherId { + self.data_segment.port_id + } + /// Copies the input `value` into a [`crate::sample_mut::SampleMut`] and delivers it. /// On success it returns the number of [`crate::port::subscriber::Subscriber`]s that received /// the data, otherwise a [`PublisherSendError`] describing the failure. diff --git a/iceoryx2/src/port/subscriber.rs b/iceoryx2/src/port/subscriber.rs index af9b886b7..02832098a 100644 --- a/iceoryx2/src/port/subscriber.rs +++ b/iceoryx2/src/port/subscriber.rs @@ -248,9 +248,9 @@ impl Subscriber match data { None => Ok(None), - Some(relative_addr) => { + Some(offset) => { let absolute_address = - relative_addr.value() + connection.data_segment.payload_start_address(); + offset.value() + connection.data_segment.payload_start_address(); Ok(Some(Sample { publisher_connections: Rc::clone(&self.publisher_connections), channel_id, @@ -259,6 +259,8 @@ impl Subscriber, ) }, + offset, + origin: connection.publisher_id, })) } }, @@ -270,6 +272,11 @@ impl Subscriber UniqueSubscriberId { + self.publisher_connections.subscriber_id() + } + /// Receives a [`crate::sample::Sample`] from [`crate::port::publisher::Publisher`]. If no sample could be /// received [`None`] is returned. If a failure occurs [`SubscriberReceiveError`] is returned. pub fn receive(&self) -> Result>, SubscriberReceiveError> { diff --git a/iceoryx2/src/sample.rs b/iceoryx2/src/sample.rs index c1c284859..ba70f259c 100644 --- a/iceoryx2/src/sample.rs +++ b/iceoryx2/src/sample.rs @@ -36,10 +36,10 @@ use std::rc::Rc; use std::{fmt::Debug, ops::Deref}; use iceoryx2_bb_log::{fatal_panic, warn}; -use iceoryx2_cal::shared_memory::SharedMemory; use iceoryx2_cal::zero_copy_connection::{PointerOffset, ZeroCopyReceiver, ZeroCopyReleaseError}; use crate::port::details::publisher_connections::PublisherConnections; +use crate::port::port_identifiers::UniquePublisherId; use crate::raw_sample::RawSample; use crate::service::header::publish_subscribe::Header; @@ -51,6 +51,8 @@ pub struct Sample { pub(crate) publisher_connections: Rc>, pub(crate) ptr: RawSample, pub(crate) channel_id: usize, + pub(crate) offset: PointerOffset, + pub(crate) origin: UniquePublisherId, } impl Deref for Sample { @@ -64,12 +66,12 @@ impl Drop for Sample { - let distance = self.ptr.as_ptr() as usize - c.data_segment.payload_start_address(); - match c.receiver.release(PointerOffset::new(distance)) { - Ok(()) => (), - Err(ZeroCopyReleaseError::RetrieveBufferFull) => { - fatal_panic!(from self, when c.receiver.release(PointerOffset::new(distance)), - "This should never happen! The publishers retrieve channel is full and the sample cannot be returned."); + if c.publisher_id == self.origin { + match c.receiver.release(self.offset) { + Ok(()) => (), + Err(ZeroCopyReleaseError::RetrieveBufferFull) => { + fatal_panic!(from self, "This should never happen! The publishers retrieve channel is full and the sample cannot be returned."); + } } } } @@ -90,4 +92,9 @@ impl Sample &Header { self.ptr.as_header_ref() } + + /// Returns the [`UniquePublisherId`] of the sender + pub fn origin(&self) -> UniquePublisherId { + self.origin + } } diff --git a/iceoryx2/src/service/builder/event.rs b/iceoryx2/src/service/builder/event.rs index 16eaa04ea..e849d8531 100644 --- a/iceoryx2/src/service/builder/event.rs +++ b/iceoryx2/src/service/builder/event.rs @@ -274,10 +274,12 @@ impl Builder { "{} since the configuration could not be serialized.", msg); // only unlock the static details when the service is successfully created - let unlocked_static_details = fail!(from self, when static_config.unlock(service_config.as_slice()), + let mut unlocked_static_details = fail!(from self, when static_config.unlock(service_config.as_slice()), with EventCreateError::Corrupted, "{} since the configuration could not be written to the static storage.", msg); + unlocked_static_details.release_ownership(); + Ok(event::PortFactory::new(ServiceType::from_state( service::ServiceState::new( self.base.service_config.clone(), diff --git a/iceoryx2/src/service/builder/mod.rs b/iceoryx2/src/service/builder/mod.rs index 147778c92..5f34f8cbe 100644 --- a/iceoryx2/src/service/builder/mod.rs +++ b/iceoryx2/src/service/builder/mod.rs @@ -296,7 +296,7 @@ impl BuilderWithServiceType { .config(&static_config_storage_config::( self.global_config.as_ref(), )) - .has_ownership(false) + .has_ownership(true) .create_locked(), "Failed to create static service information since the underlying static storage could not be created."), ) diff --git a/iceoryx2/src/service/builder/publish_subscribe.rs b/iceoryx2/src/service/builder/publish_subscribe.rs index d50c26bc1..ad7a97193 100644 --- a/iceoryx2/src/service/builder/publish_subscribe.rs +++ b/iceoryx2/src/service/builder/publish_subscribe.rs @@ -24,6 +24,7 @@ use crate::service::*; use iceoryx2_bb_elementary::enum_gen; use iceoryx2_bb_log::{fail, fatal_panic, warn}; use iceoryx2_bb_posix::adaptive_wait::AdaptiveWaitBuilder; +use iceoryx2_cal::dynamic_storage::DynamicStorageCreateError; use iceoryx2_cal::serialize::Serialize; use iceoryx2_cal::static_storage::StaticStorageLocked; @@ -67,6 +68,7 @@ pub enum PublishSubscribeCreateError { InternalFailure, IsBeingCreatedByAnotherInstance, UnableToCreateStaticServiceInformation, + OldConnectionsStillActive, } impl std::fmt::Display for PublishSubscribeCreateError { @@ -397,7 +399,7 @@ impl Builder { number_of_subscribers: pubsub_config.max_subscribers, }; - let dynamic_config = self.base.create_dynamic_config_storage( + let dynamic_config = match self.base.create_dynamic_config_storage( dynamic_config::MessagingPattern::PublishSubscribe( dynamic_config::publish_subscribe::DynamicConfig::new( &dynamic_config_setting, @@ -406,20 +408,28 @@ impl Builder { dynamic_config::publish_subscribe::DynamicConfig::memory_size( &dynamic_config_setting, ), - ); - let dynamic_config = Rc::new(fail!(from self, when dynamic_config, - with PublishSubscribeCreateError::InternalFailure, - "{} since the dynamic service segment could not be created.", msg)); - + ) { + Ok(c) => Rc::new(c), + Err(DynamicStorageCreateError::AlreadyExists) => { + fail!(from self, with PublishSubscribeCreateError::OldConnectionsStillActive, + "{} since there are still Publishers, Subscribers or active Samples.", msg); + } + Err(e) => { + fail!(from self, with PublishSubscribeCreateError::InternalFailure, + "{} since the dynamic service segment could not be created ({:?}).", msg, e); + } + }; let service_config = fail!(from self, when ServiceType::ConfigSerializer::serialize(&self.base.service_config), with PublishSubscribeCreateError::Corrupted, "{} since the configuration could not be serialized.", msg); // only unlock the static details when the service is successfully created - let unlocked_static_details = fail!(from self, when static_config.unlock(service_config.as_slice()), + let mut unlocked_static_details = fail!(from self, when static_config.unlock(service_config.as_slice()), with PublishSubscribeCreateError::Corrupted, "{} since the configuration could not be written to the static storage.", msg); + unlocked_static_details.release_ownership(); + Ok(publish_subscribe::PortFactory::new( ServiceType::from_state(service::ServiceState::new( self.base.service_config.clone(), diff --git a/iceoryx2/tests/service_publish_subscribe_tests.rs b/iceoryx2/tests/service_publish_subscribe_tests.rs index 3d2ac7c7a..68d548709 100644 --- a/iceoryx2/tests/service_publish_subscribe_tests.rs +++ b/iceoryx2/tests/service_publish_subscribe_tests.rs @@ -1533,6 +1533,185 @@ mod service_publish_subscribe { } } + #[test] + fn sample_origin_is_tracked_correctly() { + let service_name = generate_name(); + let sut = Sut::new(&service_name) + .publish_subscribe() + .create::() + .unwrap(); + + let publisher_1 = sut.publisher().create().unwrap(); + let publisher_2 = sut.publisher().create().unwrap(); + let subscriber = sut.subscriber().create().unwrap(); + + assert_that!(publisher_1.send_copy(123), eq Ok(1)); + let sample = subscriber.receive().unwrap().unwrap(); + assert_that!(sample.origin(), eq publisher_1.id()); + + assert_that!(publisher_2.send_copy(123), eq Ok(1)); + let sample = subscriber.receive().unwrap().unwrap(); + assert_that!(sample.origin(), eq publisher_2.id()); + } + + #[test] + fn dropping_service_keeps_established_communication() { + let service_name = generate_name(); + let sut = Sut::new(&service_name) + .publish_subscribe() + .create::() + .unwrap(); + + let publisher = sut.publisher().create().unwrap(); + let subscriber = sut.subscriber().create().unwrap(); + + drop(sut); + assert_that!(Sut::does_exist(&service_name).unwrap(), eq false); + + const PAYLOAD: u64 = 98129312938; + + assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); + assert_that!(*subscriber.receive().unwrap().unwrap(), eq PAYLOAD); + } + + #[test] + fn ports_of_dropped_service_block_new_service_creation() { + let service_name = generate_name(); + let sut = Sut::new(&service_name) + .publish_subscribe() + .create::() + .unwrap(); + + let subscriber = sut.subscriber().create().unwrap(); + let publisher = sut.publisher().create().unwrap(); + + drop(sut); + + assert_that!(Sut::new(&service_name) + .publish_subscribe() + .create::().err().unwrap(), + eq PublishSubscribeCreateError::OldConnectionsStillActive); + + drop(subscriber); + + assert_that!(Sut::new(&service_name) + .publish_subscribe() + .create::().err().unwrap(), + eq PublishSubscribeCreateError::OldConnectionsStillActive); + + drop(publisher); + + assert_that!( + Sut::new(&service_name).publish_subscribe().create::(), + is_ok + ); + } + + #[test] + fn sample_of_dropped_service_does_not_block_new_service_creation() { + let service_name = generate_name(); + let sut = Sut::new(&service_name) + .publish_subscribe() + .create::() + .unwrap(); + + let subscriber = sut.subscriber().create().unwrap(); + let publisher = sut.publisher().create().unwrap(); + + assert_that!(publisher.send_copy(5), eq Ok(1)); + let sample = subscriber.receive().unwrap(); + assert_that!(sample, is_some); + + drop(sut); + drop(subscriber); + drop(publisher); + + assert_that!( + Sut::new(&service_name).publish_subscribe().create::(), + is_ok + ); + } + + #[test] + fn when_everything_is_dropped_the_sample_can_still_be_consumed() { + let service_name = generate_name(); + let sut = Sut::new(&service_name) + .publish_subscribe() + .create::() + .unwrap(); + + let subscriber = sut.subscriber().create().unwrap(); + let publisher = sut.publisher().create().unwrap(); + + drop(sut); + + const PAYLOAD: u64 = 8761238679123; + + assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); + let sample = subscriber.receive().unwrap().unwrap(); + + drop(subscriber); + drop(publisher); + + assert_that!(*sample, eq PAYLOAD); + } + + #[test] + fn sample_from_dropped_publisher_does_not_block_new_publishers() { + let service_name = generate_name(); + let sut = Sut::new(&service_name) + .publish_subscribe() + .max_publishers(1) + .create::() + .unwrap(); + + let subscriber = sut.subscriber().create().unwrap(); + let publisher = sut.publisher().create().unwrap(); + + assert_that!(publisher.send_copy(123554), eq Ok(1)); + let sample = subscriber.receive().unwrap().unwrap(); + + drop(publisher); + + const PAYLOAD: u64 = 123981235645; + + let publisher = sut.publisher().create().unwrap(); + assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); + //TODO: why does it deadlock here? + //TODO: sample_mut_from_dropped_publisher + //TODO: drop tests for events + //assert_that!(*sample, eq 123554); + let sample_2 = subscriber.receive().unwrap().unwrap(); + assert_that!(*sample_2, eq PAYLOAD); + } + + #[test] + fn sample_from_dropped_subscriber_does_not_block_new_subscribers() { + let service_name = generate_name(); + let sut = Sut::new(&service_name) + .publish_subscribe() + .max_subscribers(1) + .history_size(0) + .create::() + .unwrap(); + + let subscriber = sut.subscriber().create().unwrap(); + let publisher = sut.publisher().create().unwrap(); + + assert_that!(publisher.send_copy(1234), eq Ok(1)); + let sample = subscriber.receive().unwrap().unwrap(); + + drop(subscriber); + + const PAYLOAD: u64 = 123666645; + + let subscriber = sut.subscriber().create().unwrap(); + assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); + let sample_2 = subscriber.receive().unwrap().unwrap(); + assert_that!(*sample, eq 1234); + assert_that!(*sample_2, eq PAYLOAD); + } + #[instantiate_tests()] mod zero_copy {} From 96028a3e3e35ab92c33f62139edf4fb992b27e89 Mon Sep 17 00:00:00 2001 From: Christian Eltzschig Date: Fri, 1 Mar 2024 11:12:52 +0100 Subject: [PATCH 3/8] [#133] Move Sample, SampleMut tests in its own test files; add SampleMut tests --- iceoryx2/tests/sample_mut_tests.rs | 161 ++++++++++++++++++ iceoryx2/tests/sample_tests.rs | 156 +++++++++++++++++ .../tests/service_publish_subscribe_tests.rs | 126 -------------- 3 files changed, 317 insertions(+), 126 deletions(-) create mode 100644 iceoryx2/tests/sample_mut_tests.rs create mode 100644 iceoryx2/tests/sample_tests.rs diff --git a/iceoryx2/tests/sample_mut_tests.rs b/iceoryx2/tests/sample_mut_tests.rs new file mode 100644 index 000000000..021cfbed4 --- /dev/null +++ b/iceoryx2/tests/sample_mut_tests.rs @@ -0,0 +1,161 @@ +// Copyright (c) 2024 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache Software License 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license +// which is available at https://opensource.org/licenses/MIT. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + +#[generic_tests::define] +mod sample_mut { + use iceoryx2::port::publisher::Publisher; + use iceoryx2::port::subscriber::Subscriber; + use iceoryx2::prelude::*; + use iceoryx2::service::port_factory::publish_subscribe::PortFactory; + use iceoryx2::service::Service; + use iceoryx2_bb_posix::unique_system_id::UniqueSystemId; + use iceoryx2_bb_testing::assert_that; + + const MAX_LOANED_SAMPLES: usize = 5; + + fn generate_name() -> ServiceName { + ServiceName::new(&format!( + "service_tests_{}", + UniqueSystemId::new().unwrap().value() + )) + .unwrap() + } + + struct TestFixture { + service_name: ServiceName, + service: PortFactory, + publisher: Publisher, + subscriber: Subscriber, + } + + impl TestFixture { + fn new() -> Self { + let service_name = generate_name(); + let service = Sut::new(&service_name) + .publish_subscribe() + .create::() + .unwrap(); + + let publisher = service + .publisher() + .max_loaned_samples(MAX_LOANED_SAMPLES) + .create() + .unwrap(); + + let subscriber = service.subscriber().create().unwrap(); + + Self { + service_name, + service, + publisher, + subscriber, + } + } + + fn publisher(&self) -> &Publisher { + &self.publisher + } + + fn subscriber(&self) -> &Subscriber { + &self.subscriber + } + } + + #[test] + fn when_going_out_of_scope_it_is_released() { + let test = TestFixture::::new(); + + let mut sample_vec = vec![]; + + for _ in 0..4 { + while let Ok(sample) = test.publisher().loan() { + sample_vec.push(sample); + } + + assert_that!(sample_vec, len MAX_LOANED_SAMPLES); + sample_vec.clear(); + } + } + + #[test] + fn header_tracks_correct_origin() { + let test = TestFixture::::new(); + let sample = test.publisher().loan().unwrap(); + assert_that!(sample.header().publisher_id(), eq test.publisher().id()); + } + + #[test] + fn write_payload_works() { + const PAYLOAD_1: u64 = 891283689123555; + const PAYLOAD_2: u64 = 71820; + let test = TestFixture::::new(); + let sample = test.publisher().loan_uninit().unwrap(); + let mut sample = sample.write_payload(PAYLOAD_1); + + assert_that!(*sample.payload(), eq PAYLOAD_1); + assert_that!(*sample.payload_mut(), eq PAYLOAD_1); + + *sample.payload_mut() = PAYLOAD_2; + + assert_that!(*sample.payload(), eq PAYLOAD_2); + assert_that!(*sample.payload_mut(), eq PAYLOAD_2); + } + + #[test] + fn assume_init_works() { + const PAYLOAD: u64 = 7182055123; + let test = TestFixture::::new(); + let mut sample = test.publisher().loan_uninit().unwrap(); + let _ = *sample.payload_mut().write(PAYLOAD); + let mut sample = unsafe { sample.assume_init() }; + + assert_that!(*sample.payload(), eq PAYLOAD); + assert_that!(*sample.payload_mut(), eq PAYLOAD); + } + + #[test] + fn send_works() { + const PAYLOAD: u64 = 3215357; + let test = TestFixture::::new(); + let sample = test.publisher().loan_uninit().unwrap(); + let sample = sample.write_payload(PAYLOAD); + + assert_that!(sample.send(), eq Ok(1)); + + let received_sample = test.subscriber().receive().unwrap().unwrap(); + assert_that!(*received_sample, eq PAYLOAD); + } + + #[test] + fn sample_of_dropped_service_does_not_block_new_service_creation() { + //TODO: sample_mut_from_dropped_publisher + //TODO: drop tests for events + //TODO: refactor sample tests with TestFixture like SampleMut tests + + let test = TestFixture::::new(); + let service_name = test.service_name.clone(); + let _sample = test.publisher().loan_uninit().unwrap(); + + drop(test); + + assert_that!( + Sut::new(&service_name).publish_subscribe().create::(), + is_ok + ); + } + + #[instantiate_tests()] + mod zero_copy {} + + #[instantiate_tests()] + mod process_local {} +} diff --git a/iceoryx2/tests/sample_tests.rs b/iceoryx2/tests/sample_tests.rs new file mode 100644 index 000000000..96f4916f0 --- /dev/null +++ b/iceoryx2/tests/sample_tests.rs @@ -0,0 +1,156 @@ +// Copyright (c) 2024 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache Software License 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license +// which is available at https://opensource.org/licenses/MIT. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + +#[generic_tests::define] +mod sample { + use iceoryx2::prelude::*; + use iceoryx2::service::Service; + use iceoryx2_bb_posix::unique_system_id::UniqueSystemId; + use iceoryx2_bb_testing::assert_that; + + fn generate_name() -> ServiceName { + ServiceName::new(&format!( + "service_tests_{}", + UniqueSystemId::new().unwrap().value() + )) + .unwrap() + } + + #[test] + fn origin_is_tracked_correctly() { + let service_name = generate_name(); + let sut = Sut::new(&service_name) + .publish_subscribe() + .create::() + .unwrap(); + + let publisher_1 = sut.publisher().create().unwrap(); + let publisher_2 = sut.publisher().create().unwrap(); + let subscriber = sut.subscriber().create().unwrap(); + + assert_that!(publisher_1.send_copy(123), eq Ok(1)); + let sample = subscriber.receive().unwrap().unwrap(); + assert_that!(sample.origin(), eq publisher_1.id()); + + assert_that!(publisher_2.send_copy(123), eq Ok(1)); + let sample = subscriber.receive().unwrap().unwrap(); + assert_that!(sample.origin(), eq publisher_2.id()); + } + + #[test] + fn sample_of_dropped_service_does_not_block_new_service_creation() { + let service_name = generate_name(); + let sut = Sut::new(&service_name) + .publish_subscribe() + .create::() + .unwrap(); + + let subscriber = sut.subscriber().create().unwrap(); + let publisher = sut.publisher().create().unwrap(); + + assert_that!(publisher.send_copy(5), eq Ok(1)); + let sample = subscriber.receive().unwrap(); + assert_that!(sample, is_some); + + drop(sut); + drop(subscriber); + drop(publisher); + + assert_that!( + Sut::new(&service_name).publish_subscribe().create::(), + is_ok + ); + } + + #[test] + fn when_everything_is_dropped_the_sample_can_still_be_consumed() { + let service_name = generate_name(); + let sut = Sut::new(&service_name) + .publish_subscribe() + .create::() + .unwrap(); + + let subscriber = sut.subscriber().create().unwrap(); + let publisher = sut.publisher().create().unwrap(); + + drop(sut); + + const PAYLOAD: u64 = 8761238679123; + + assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); + let sample = subscriber.receive().unwrap().unwrap(); + + drop(subscriber); + drop(publisher); + + assert_that!(*sample, eq PAYLOAD); + } + + #[test] + fn sample_received_from_dropped_publisher_does_not_block_new_publishers() { + let service_name = generate_name(); + let sut = Sut::new(&service_name) + .publish_subscribe() + .max_publishers(1) + .create::() + .unwrap(); + + let subscriber = sut.subscriber().create().unwrap(); + let publisher = sut.publisher().create().unwrap(); + + assert_that!(publisher.send_copy(123554), eq Ok(1)); + let sample = subscriber.receive().unwrap().unwrap(); + + drop(publisher); + + const PAYLOAD: u64 = 123981235645; + + let publisher = sut.publisher().create().unwrap(); + assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); + assert_that!(*sample, eq 123554); + let sample_2 = subscriber.receive().unwrap().unwrap(); + assert_that!(*sample_2, eq PAYLOAD); + } + + #[test] + fn sample_from_dropped_subscriber_does_not_block_new_subscribers() { + let service_name = generate_name(); + let sut = Sut::new(&service_name) + .publish_subscribe() + .max_subscribers(1) + .history_size(0) + .create::() + .unwrap(); + + let subscriber = sut.subscriber().create().unwrap(); + let publisher = sut.publisher().create().unwrap(); + + assert_that!(publisher.send_copy(1234), eq Ok(1)); + let sample = subscriber.receive().unwrap().unwrap(); + + drop(subscriber); + + const PAYLOAD: u64 = 123666645; + + let subscriber = sut.subscriber().create().unwrap(); + assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); + let sample_2 = subscriber.receive().unwrap().unwrap(); + assert_that!(*sample, eq 1234); + assert_that!(*sample_2, eq PAYLOAD); + } + + #[instantiate_tests()] + mod zero_copy {} + + #[instantiate_tests()] + mod process_local {} +} diff --git a/iceoryx2/tests/service_publish_subscribe_tests.rs b/iceoryx2/tests/service_publish_subscribe_tests.rs index 68d548709..b42466d26 100644 --- a/iceoryx2/tests/service_publish_subscribe_tests.rs +++ b/iceoryx2/tests/service_publish_subscribe_tests.rs @@ -1533,27 +1533,6 @@ mod service_publish_subscribe { } } - #[test] - fn sample_origin_is_tracked_correctly() { - let service_name = generate_name(); - let sut = Sut::new(&service_name) - .publish_subscribe() - .create::() - .unwrap(); - - let publisher_1 = sut.publisher().create().unwrap(); - let publisher_2 = sut.publisher().create().unwrap(); - let subscriber = sut.subscriber().create().unwrap(); - - assert_that!(publisher_1.send_copy(123), eq Ok(1)); - let sample = subscriber.receive().unwrap().unwrap(); - assert_that!(sample.origin(), eq publisher_1.id()); - - assert_that!(publisher_2.send_copy(123), eq Ok(1)); - let sample = subscriber.receive().unwrap().unwrap(); - assert_that!(sample.origin(), eq publisher_2.id()); - } - #[test] fn dropping_service_keeps_established_communication() { let service_name = generate_name(); @@ -1607,111 +1586,6 @@ mod service_publish_subscribe { ); } - #[test] - fn sample_of_dropped_service_does_not_block_new_service_creation() { - let service_name = generate_name(); - let sut = Sut::new(&service_name) - .publish_subscribe() - .create::() - .unwrap(); - - let subscriber = sut.subscriber().create().unwrap(); - let publisher = sut.publisher().create().unwrap(); - - assert_that!(publisher.send_copy(5), eq Ok(1)); - let sample = subscriber.receive().unwrap(); - assert_that!(sample, is_some); - - drop(sut); - drop(subscriber); - drop(publisher); - - assert_that!( - Sut::new(&service_name).publish_subscribe().create::(), - is_ok - ); - } - - #[test] - fn when_everything_is_dropped_the_sample_can_still_be_consumed() { - let service_name = generate_name(); - let sut = Sut::new(&service_name) - .publish_subscribe() - .create::() - .unwrap(); - - let subscriber = sut.subscriber().create().unwrap(); - let publisher = sut.publisher().create().unwrap(); - - drop(sut); - - const PAYLOAD: u64 = 8761238679123; - - assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); - let sample = subscriber.receive().unwrap().unwrap(); - - drop(subscriber); - drop(publisher); - - assert_that!(*sample, eq PAYLOAD); - } - - #[test] - fn sample_from_dropped_publisher_does_not_block_new_publishers() { - let service_name = generate_name(); - let sut = Sut::new(&service_name) - .publish_subscribe() - .max_publishers(1) - .create::() - .unwrap(); - - let subscriber = sut.subscriber().create().unwrap(); - let publisher = sut.publisher().create().unwrap(); - - assert_that!(publisher.send_copy(123554), eq Ok(1)); - let sample = subscriber.receive().unwrap().unwrap(); - - drop(publisher); - - const PAYLOAD: u64 = 123981235645; - - let publisher = sut.publisher().create().unwrap(); - assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); - //TODO: why does it deadlock here? - //TODO: sample_mut_from_dropped_publisher - //TODO: drop tests for events - //assert_that!(*sample, eq 123554); - let sample_2 = subscriber.receive().unwrap().unwrap(); - assert_that!(*sample_2, eq PAYLOAD); - } - - #[test] - fn sample_from_dropped_subscriber_does_not_block_new_subscribers() { - let service_name = generate_name(); - let sut = Sut::new(&service_name) - .publish_subscribe() - .max_subscribers(1) - .history_size(0) - .create::() - .unwrap(); - - let subscriber = sut.subscriber().create().unwrap(); - let publisher = sut.publisher().create().unwrap(); - - assert_that!(publisher.send_copy(1234), eq Ok(1)); - let sample = subscriber.receive().unwrap().unwrap(); - - drop(subscriber); - - const PAYLOAD: u64 = 123666645; - - let subscriber = sut.subscriber().create().unwrap(); - assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); - let sample_2 = subscriber.receive().unwrap().unwrap(); - assert_that!(*sample, eq 1234); - assert_that!(*sample_2, eq PAYLOAD); - } - #[instantiate_tests()] mod zero_copy {} From c6adb0733a78945810d021fa5a9f18850d6f3927 Mon Sep 17 00:00:00 2001 From: Christian Eltzschig Date: Mon, 4 Mar 2024 00:23:02 +0100 Subject: [PATCH 4/8] [#133] Add and refactor Sample(Mut) tests --- iceoryx2/tests/sample_mut_tests.rs | 51 +++++------ iceoryx2/tests/sample_tests.rs | 135 +++++++++++++++-------------- 2 files changed, 98 insertions(+), 88 deletions(-) diff --git a/iceoryx2/tests/sample_mut_tests.rs b/iceoryx2/tests/sample_mut_tests.rs index 021cfbed4..25dc383f5 100644 --- a/iceoryx2/tests/sample_mut_tests.rs +++ b/iceoryx2/tests/sample_mut_tests.rs @@ -15,6 +15,7 @@ mod sample_mut { use iceoryx2::port::publisher::Publisher; use iceoryx2::port::subscriber::Subscriber; use iceoryx2::prelude::*; + use iceoryx2::service::builder::publish_subscribe::PublishSubscribeCreateError; use iceoryx2::service::port_factory::publish_subscribe::PortFactory; use iceoryx2::service::Service; use iceoryx2_bb_posix::unique_system_id::UniqueSystemId; @@ -42,6 +43,7 @@ mod sample_mut { let service_name = generate_name(); let service = Sut::new(&service_name) .publish_subscribe() + .max_publishers(1) .create::() .unwrap(); @@ -60,14 +62,6 @@ mod sample_mut { subscriber, } } - - fn publisher(&self) -> &Publisher { - &self.publisher - } - - fn subscriber(&self) -> &Subscriber { - &self.subscriber - } } #[test] @@ -77,7 +71,7 @@ mod sample_mut { let mut sample_vec = vec![]; for _ in 0..4 { - while let Ok(sample) = test.publisher().loan() { + while let Ok(sample) = test.publisher.loan() { sample_vec.push(sample); } @@ -89,8 +83,8 @@ mod sample_mut { #[test] fn header_tracks_correct_origin() { let test = TestFixture::::new(); - let sample = test.publisher().loan().unwrap(); - assert_that!(sample.header().publisher_id(), eq test.publisher().id()); + let sample = test.publisher.loan().unwrap(); + assert_that!(sample.header().publisher_id(), eq test.publisher.id()); } #[test] @@ -98,7 +92,7 @@ mod sample_mut { const PAYLOAD_1: u64 = 891283689123555; const PAYLOAD_2: u64 = 71820; let test = TestFixture::::new(); - let sample = test.publisher().loan_uninit().unwrap(); + let sample = test.publisher.loan_uninit().unwrap(); let mut sample = sample.write_payload(PAYLOAD_1); assert_that!(*sample.payload(), eq PAYLOAD_1); @@ -114,7 +108,7 @@ mod sample_mut { fn assume_init_works() { const PAYLOAD: u64 = 7182055123; let test = TestFixture::::new(); - let mut sample = test.publisher().loan_uninit().unwrap(); + let mut sample = test.publisher.loan_uninit().unwrap(); let _ = *sample.payload_mut().write(PAYLOAD); let mut sample = unsafe { sample.assume_init() }; @@ -126,31 +120,38 @@ mod sample_mut { fn send_works() { const PAYLOAD: u64 = 3215357; let test = TestFixture::::new(); - let sample = test.publisher().loan_uninit().unwrap(); + let sample = test.publisher.loan_uninit().unwrap(); let sample = sample.write_payload(PAYLOAD); assert_that!(sample.send(), eq Ok(1)); - let received_sample = test.subscriber().receive().unwrap().unwrap(); + let received_sample = test.subscriber.receive().unwrap().unwrap(); assert_that!(*received_sample, eq PAYLOAD); } #[test] - fn sample_of_dropped_service_does_not_block_new_service_creation() { - //TODO: sample_mut_from_dropped_publisher - //TODO: drop tests for events - //TODO: refactor sample tests with TestFixture like SampleMut tests - + fn sample_of_dropped_service_does_block_new_service_creation() { let test = TestFixture::::new(); let service_name = test.service_name.clone(); - let _sample = test.publisher().loan_uninit().unwrap(); + let _sample = test.publisher.loan_uninit().unwrap(); drop(test); - assert_that!( - Sut::new(&service_name).publish_subscribe().create::(), - is_ok - ); + let result = Sut::new(&service_name).publish_subscribe().create::(); + assert_that!(result, is_err); + assert_that!(result.err().unwrap(), eq PublishSubscribeCreateError::OldConnectionsStillActive); + } + + #[test] + fn sample_of_dropped_publisher_does_not_block_new_publishers() { + let test = TestFixture::::new(); + let service = test.service; + let publisher = test.publisher; + let _sample = publisher.loan_uninit().unwrap(); + + drop(publisher); + + assert_that!(service.publisher().create(), is_ok); } #[instantiate_tests()] diff --git a/iceoryx2/tests/sample_tests.rs b/iceoryx2/tests/sample_tests.rs index 96f4916f0..f363bd09c 100644 --- a/iceoryx2/tests/sample_tests.rs +++ b/iceoryx2/tests/sample_tests.rs @@ -12,7 +12,10 @@ #[generic_tests::define] mod sample { + use iceoryx2::port::publisher::Publisher; + use iceoryx2::port::subscriber::Subscriber; use iceoryx2::prelude::*; + use iceoryx2::service::port_factory::publish_subscribe::PortFactory; use iceoryx2::service::Service; use iceoryx2_bb_posix::unique_system_id::UniqueSystemId; use iceoryx2_bb_testing::assert_that; @@ -25,45 +28,64 @@ mod sample { .unwrap() } + struct TestFixture { + service_name: ServiceName, + service: PortFactory, + publisher_1: Publisher, + publisher_2: Publisher, + subscriber: Subscriber, + } + + impl TestFixture { + fn new() -> Self { + let service_name = generate_name(); + let service = Sut::new(&service_name) + .publish_subscribe() + .max_publishers(2) + .max_subscribers(1) + .create::() + .unwrap(); + + let publisher_1 = service.publisher().create().unwrap(); + + let publisher_2 = service.publisher().create().unwrap(); + + let subscriber = service.subscriber().create().unwrap(); + + Self { + service_name, + service, + publisher_1, + publisher_2, + subscriber, + } + } + } + #[test] fn origin_is_tracked_correctly() { - let service_name = generate_name(); - let sut = Sut::new(&service_name) - .publish_subscribe() - .create::() - .unwrap(); + let test = TestFixture::::new(); - let publisher_1 = sut.publisher().create().unwrap(); - let publisher_2 = sut.publisher().create().unwrap(); - let subscriber = sut.subscriber().create().unwrap(); + assert_that!(test.publisher_1.send_copy(123), eq Ok(1)); + let sample = test.subscriber.receive().unwrap().unwrap(); + assert_that!(sample.origin(), eq test.publisher_1.id()); - assert_that!(publisher_1.send_copy(123), eq Ok(1)); - let sample = subscriber.receive().unwrap().unwrap(); - assert_that!(sample.origin(), eq publisher_1.id()); - - assert_that!(publisher_2.send_copy(123), eq Ok(1)); - let sample = subscriber.receive().unwrap().unwrap(); - assert_that!(sample.origin(), eq publisher_2.id()); + assert_that!(test.publisher_2.send_copy(123), eq Ok(1)); + let sample = test.subscriber.receive().unwrap().unwrap(); + assert_that!(sample.origin(), eq test.publisher_2.id()); } #[test] fn sample_of_dropped_service_does_not_block_new_service_creation() { - let service_name = generate_name(); - let sut = Sut::new(&service_name) - .publish_subscribe() - .create::() - .unwrap(); + let test = TestFixture::::new(); - let subscriber = sut.subscriber().create().unwrap(); - let publisher = sut.publisher().create().unwrap(); + let service_name = test.service_name; - assert_that!(publisher.send_copy(5), eq Ok(1)); - let sample = subscriber.receive().unwrap(); + assert_that!(test.publisher_1.send_copy(5), eq Ok(1)); + let sample = test.subscriber.receive().unwrap(); assert_that!(sample, is_some); - drop(sut); - drop(subscriber); - drop(publisher); + drop(test); assert_that!( Sut::new(&service_name).publish_subscribe().create::(), @@ -73,78 +95,65 @@ mod sample { #[test] fn when_everything_is_dropped_the_sample_can_still_be_consumed() { - let service_name = generate_name(); - let sut = Sut::new(&service_name) - .publish_subscribe() - .create::() - .unwrap(); + let test = TestFixture::::new(); - let subscriber = sut.subscriber().create().unwrap(); - let publisher = sut.publisher().create().unwrap(); + let sut = test.service; + let publisher_1 = test.publisher_1; + let publisher_2 = test.publisher_2; + let subscriber = test.subscriber; drop(sut); const PAYLOAD: u64 = 8761238679123; - assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); + assert_that!(publisher_1.send_copy(PAYLOAD), eq Ok(1)); let sample = subscriber.receive().unwrap().unwrap(); drop(subscriber); - drop(publisher); + drop(publisher_1); + drop(publisher_2); assert_that!(*sample, eq PAYLOAD); } #[test] fn sample_received_from_dropped_publisher_does_not_block_new_publishers() { - let service_name = generate_name(); - let sut = Sut::new(&service_name) - .publish_subscribe() - .max_publishers(1) - .create::() - .unwrap(); + let test = TestFixture::::new(); - let subscriber = sut.subscriber().create().unwrap(); - let publisher = sut.publisher().create().unwrap(); + let publisher = test.publisher_1; assert_that!(publisher.send_copy(123554), eq Ok(1)); - let sample = subscriber.receive().unwrap().unwrap(); + let sample = test.subscriber.receive().unwrap().unwrap(); drop(publisher); const PAYLOAD: u64 = 123981235645; - let publisher = sut.publisher().create().unwrap(); + let publisher = test.service.publisher().create().unwrap(); assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); assert_that!(*sample, eq 123554); - let sample_2 = subscriber.receive().unwrap().unwrap(); + let sample_2 = test.subscriber.receive().unwrap().unwrap(); assert_that!(*sample_2, eq PAYLOAD); } #[test] fn sample_from_dropped_subscriber_does_not_block_new_subscribers() { - let service_name = generate_name(); - let sut = Sut::new(&service_name) - .publish_subscribe() - .max_subscribers(1) - .history_size(0) - .create::() - .unwrap(); - - let subscriber = sut.subscriber().create().unwrap(); - let publisher = sut.publisher().create().unwrap(); - - assert_that!(publisher.send_copy(1234), eq Ok(1)); - let sample = subscriber.receive().unwrap().unwrap(); + let test = TestFixture::::new(); + + let subscriber = test.subscriber; + + assert_that!(test.publisher_1.send_copy(1234), eq Ok(1)); + let _sample = subscriber.receive().unwrap().unwrap(); drop(subscriber); const PAYLOAD: u64 = 123666645; - let subscriber = sut.subscriber().create().unwrap(); - assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); + let subscriber = test.service.subscriber().create().unwrap(); + assert_that!(test.publisher_1.send_copy(PAYLOAD), eq Ok(1)); + let sample_1 = subscriber.receive().unwrap().unwrap(); let sample_2 = subscriber.receive().unwrap().unwrap(); - assert_that!(*sample, eq 1234); + assert_that!(*sample_1, eq 1234); assert_that!(*sample_2, eq PAYLOAD); } From fc014f57824691b3f342b67372b80e61017b73f7 Mon Sep 17 00:00:00 2001 From: Christian Eltzschig Date: Mon, 4 Mar 2024 12:52:48 +0100 Subject: [PATCH 5/8] [#133] Write additional tests for events --- iceoryx2/src/service/builder/event.rs | 19 ++- iceoryx2/tests/service_event_tests.rs | 181 ++++++++++++++++++++++++++ 2 files changed, 195 insertions(+), 5 deletions(-) diff --git a/iceoryx2/src/service/builder/event.rs b/iceoryx2/src/service/builder/event.rs index e849d8531..1dc491e2e 100644 --- a/iceoryx2/src/service/builder/event.rs +++ b/iceoryx2/src/service/builder/event.rs @@ -21,6 +21,7 @@ use crate::service::{self, dynamic_config::event::DynamicConfigSettings}; use iceoryx2_bb_elementary::enum_gen; use iceoryx2_bb_log::{fail, fatal_panic}; use iceoryx2_bb_posix::adaptive_wait::AdaptiveWaitBuilder; +use iceoryx2_cal::dynamic_storage::DynamicStorageCreateError; use super::ServiceState; @@ -55,6 +56,7 @@ pub enum EventCreateError { AlreadyExists, PermissionDenied, UnableToCreateStaticServiceInformation, + OldConnectionsStillActive, } impl std::fmt::Display for EventCreateError { @@ -259,15 +261,22 @@ impl Builder { number_of_notifiers: event_config.max_notifiers, }; - let dynamic_config = self.base.create_dynamic_config_storage( + let dynamic_config = match self.base.create_dynamic_config_storage( dynamic_config::MessagingPattern::Event( dynamic_config::event::DynamicConfig::new(&dynamic_config_setting), ), dynamic_config::event::DynamicConfig::memory_size(&dynamic_config_setting), - ); - let dynamic_config = Rc::new(fail!(from self, when dynamic_config, - with EventCreateError::InternalFailure, - "{} since the dynamic service segment could not be created.", msg)); + ) { + Ok(c) => Rc::new(c), + Err(DynamicStorageCreateError::AlreadyExists) => { + fail!(from self, with EventCreateError::OldConnectionsStillActive, + "{} since there are still active Listeners or Notifiers.", msg); + } + Err(e) => { + fail!(from self, with EventCreateError::InternalFailure, + "{} since the dynamic service segment could not be created ({:?}).", msg, e); + } + }; let service_config = fail!(from self, when ServiceType::ConfigSerializer::serialize(&self.base.service_config), with EventCreateError::Corrupted, diff --git a/iceoryx2/tests/service_event_tests.rs b/iceoryx2/tests/service_event_tests.rs index a35e1b8d8..d20ceb5e5 100644 --- a/iceoryx2/tests/service_event_tests.rs +++ b/iceoryx2/tests/service_event_tests.rs @@ -12,11 +12,16 @@ #[generic_tests::define] mod service_event { + use std::sync::atomic::{AtomicBool, Ordering}; + use std::sync::Barrier; + use std::time::Duration; + use iceoryx2::config::Config; use iceoryx2::prelude::*; use iceoryx2::service::builder::event::{EventCreateError, EventOpenError}; use iceoryx2_bb_posix::unique_system_id::UniqueSystemId; use iceoryx2_bb_testing::assert_that; + use iceoryx2_bb_testing::watchdog::Watchdog; fn generate_name() -> ServiceName { ServiceName::new(&format!( @@ -365,6 +370,182 @@ mod service_event { } } + #[test] + // TODO iox2-139 + #[ignore] + fn concurrent_reconnecting_notifier_can_trigger_waiting_listener() { + let _watch_dog = Watchdog::new(Duration::from_secs(10)); + + const NUMBER_OF_LISTENER_THREADS: usize = 2; + const NUMBER_OF_NOTIFIER_THREADS: usize = 2; + const NUMBER_OF_ITERATIONS: usize = 50; + const EVENT_ID: EventId = EventId::new(558); + + let keep_running = AtomicBool::new(true); + let service_name = generate_name(); + let barrier = Barrier::new(NUMBER_OF_LISTENER_THREADS + NUMBER_OF_NOTIFIER_THREADS); + + let sut = Sut::new(&service_name) + .event() + .max_listeners(NUMBER_OF_LISTENER_THREADS) + .max_notifiers(NUMBER_OF_NOTIFIER_THREADS) + .create() + .unwrap(); + + std::thread::scope(|s| { + let mut listener_threads = vec![]; + for _ in 0..NUMBER_OF_LISTENER_THREADS { + listener_threads.push(s.spawn(|| { + let mut listener = sut.listener().create().unwrap(); + barrier.wait(); + + let mut counter = 0; + while counter < NUMBER_OF_ITERATIONS { + let event_ids = listener.blocking_wait().unwrap(); + if !event_ids.is_empty() { + counter += 1; + for id in event_ids { + assert_that!(*id, eq EVENT_ID); + } + } + } + })); + } + + for _ in 0..NUMBER_OF_NOTIFIER_THREADS { + s.spawn(|| { + barrier.wait(); + + while keep_running.load(Ordering::Relaxed) { + let notifier = sut.notifier().create().unwrap(); + assert_that!(notifier.notify_with_custom_event_id(EVENT_ID), is_ok); + } + }); + } + + for thread in listener_threads { + thread.join().unwrap(); + } + + keep_running.store(false, Ordering::Relaxed); + }); + } + + #[test] + // TODO iox2-139 + #[ignore] + fn concurrent_reconnecting_listener_can_wait_for_triggering_notifiers() { + let _watch_dog = Watchdog::new(Duration::from_secs(1)); + + const NUMBER_OF_LISTENER_THREADS: usize = 2; + const NUMBER_OF_NOTIFIER_THREADS: usize = 2; + const NUMBER_OF_ITERATIONS: usize = 50; + const EVENT_ID: EventId = EventId::new(558); + + let keep_running = AtomicBool::new(true); + let service_name = generate_name(); + let barrier = Barrier::new(NUMBER_OF_LISTENER_THREADS + NUMBER_OF_NOTIFIER_THREADS); + + let sut = Sut::new(&service_name) + .event() + .max_listeners(NUMBER_OF_LISTENER_THREADS * 2) + .max_notifiers(NUMBER_OF_NOTIFIER_THREADS) + .create() + .unwrap(); + + std::thread::scope(|s| { + let mut listener_threads = vec![]; + for _ in 0..NUMBER_OF_LISTENER_THREADS { + listener_threads.push(s.spawn(|| { + barrier.wait(); + + let mut counter = 0; + let mut listener = sut.listener().create().unwrap(); + while counter < NUMBER_OF_ITERATIONS { + let event_ids = listener.blocking_wait().unwrap(); + if !event_ids.is_empty() { + counter += 1; + for id in event_ids { + assert_that!(*id, eq EVENT_ID); + } + listener = sut.listener().create().unwrap(); + } + } + })); + } + + for _ in 0..NUMBER_OF_NOTIFIER_THREADS { + s.spawn(|| { + let notifier = sut.notifier().create().unwrap(); + barrier.wait(); + + while keep_running.load(Ordering::Relaxed) { + assert_that!(notifier.notify_with_custom_event_id(EVENT_ID), is_ok); + } + }); + } + + for thread in listener_threads { + thread.join().unwrap(); + } + + keep_running.store(false, Ordering::Relaxed); + }); + } + + #[test] + fn communication_persists_when_service_is_dropped() { + let service_name = generate_name(); + let event_id = EventId::new(43212); + + let sut = Sut::new(&service_name).event().create().unwrap(); + + let notifier = sut.notifier().default_event_id(event_id).create().unwrap(); + let mut listener = sut.listener().create().unwrap(); + + assert_that!(Sut::does_exist(&service_name), eq Ok(true)); + drop(sut); + assert_that!(Sut::does_exist(&service_name), eq Ok(false)); + + assert_that!(notifier.notify(), eq Ok(1)); + + let mut received_events = 0; + for event in listener.try_wait().unwrap().iter() { + assert_that!(*event, eq event_id); + received_events += 1; + } + assert_that!(received_events, eq 1); + } + + #[test] + fn persisting_connection_does_prevent_service_recreation() { + let service_name = generate_name(); + let event_id = EventId::new(43212); + + let sut = Sut::new(&service_name).event().create().unwrap(); + + let notifier = sut.notifier().default_event_id(event_id).create().unwrap(); + let listener = sut.listener().create().unwrap(); + + assert_that!(Sut::does_exist(&service_name), eq Ok(true)); + drop(sut); + assert_that!(Sut::does_exist(&service_name), eq Ok(false)); + + let sut = Sut::new(&service_name).event().create(); + assert_that!(sut, is_err); + assert_that!(sut.err().unwrap(), eq EventCreateError::OldConnectionsStillActive); + + drop(listener); + + let sut = Sut::new(&service_name).event().create(); + assert_that!(sut, is_err); + assert_that!(sut.err().unwrap(), eq EventCreateError::OldConnectionsStillActive); + + drop(notifier); + + assert_that!(Sut::new(&service_name).event().create(), is_ok); + } + #[instantiate_tests()] mod zero_copy {} From 9b0c561fa980765bbea70399e08ec2db301d0440 Mon Sep 17 00:00:00 2001 From: Christian Eltzschig Date: Thu, 7 Mar 2024 01:07:58 +0100 Subject: [PATCH 6/8] [#133] Write shm pool allocator tests --- Cargo.toml | 9 +- iceoryx2-cal/src/shm_allocator/mod.rs | 2 + .../shm_allocator_pool_allocator_tests.rs | 102 ++++++++++++++++++ 3 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 iceoryx2-cal/tests/shm_allocator_pool_allocator_tests.rs diff --git a/Cargo.toml b/Cargo.toml index 2689858be..28c3330fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,8 +76,7 @@ windows-sys = { version = "0.48.0", features = ["Win32_Security", "Win32_Securit "Win32_System_SystemServices"] } [profile.release] -debug = true -# strip = true -# lto = true -# # opt-level = "z" -# panic = "abort" +strip = true +lto = true +# opt-level = "z" +panic = "abort" diff --git a/iceoryx2-cal/src/shm_allocator/mod.rs b/iceoryx2-cal/src/shm_allocator/mod.rs index fd48daae9..cbdba7dd6 100644 --- a/iceoryx2-cal/src/shm_allocator/mod.rs +++ b/iceoryx2-cal/src/shm_allocator/mod.rs @@ -52,6 +52,8 @@ pub enum ShmAllocatorInitError { pub trait ShmAllocator: Send + Sync + 'static { type Configuration: ShmAllocatorConfig; + /// Returns the required memory size of the additional dynamic part of the allocator that is + /// allocated in [`ShmAllocator::init()`]. fn management_size(memory_size: usize, config: &Self::Configuration) -> usize; /// Creates a new uninitialized shared memory allocator. diff --git a/iceoryx2-cal/tests/shm_allocator_pool_allocator_tests.rs b/iceoryx2-cal/tests/shm_allocator_pool_allocator_tests.rs new file mode 100644 index 000000000..5c3e453c8 --- /dev/null +++ b/iceoryx2-cal/tests/shm_allocator_pool_allocator_tests.rs @@ -0,0 +1,102 @@ +// Copyright (c) 2024 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache Software License 2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license +// which is available at https://opensource.org/licenses/MIT. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + +mod shm_allocator_pool_allocator { + use std::{alloc::Layout, collections::HashSet, ptr::NonNull}; + + use iceoryx2_bb_elementary::allocator::AllocationError; + use iceoryx2_bb_memory::bump_allocator::BumpAllocator; + use iceoryx2_bb_testing::assert_that; + use iceoryx2_cal::{ + shm_allocator::{pool_allocator::*, ShmAllocationError, ShmAllocator}, + zero_copy_connection::PointerOffset, + }; + + const MAX_SUPPORTED_ALIGNMENT: usize = 32; + const BUCKET_CONFIG: Layout = unsafe { Layout::from_size_align_unchecked(32, 4) }; + const MEM_SIZE: usize = 8192; + const PAYLOAD_SIZE: usize = 1024; + + struct TestFixture { + _payload_memory: Box<[u8; MEM_SIZE]>, + _base_address: NonNull<[u8]>, + sut: Box, + } + + impl TestFixture { + fn new(bucket_layout: Layout) -> Self { + let mut payload_memory = Box::new([0u8; MEM_SIZE]); + let base_address = + unsafe { NonNull::<[u8]>::new_unchecked(&mut payload_memory[0..PAYLOAD_SIZE]) }; + let allocator = BumpAllocator::new( + unsafe { NonNull::new_unchecked(payload_memory[PAYLOAD_SIZE..].as_mut_ptr()) }, + MEM_SIZE, + ); + let config = &Config { bucket_layout }; + let sut = Box::new(unsafe { + PoolAllocator::new_uninit(MAX_SUPPORTED_ALIGNMENT, base_address, config) + }); + + unsafe { sut.init(&allocator).unwrap() }; + + Self { + _payload_memory: payload_memory, + _base_address: base_address, + sut, + } + } + } + + #[test] + fn is_setup_correctly() { + let test = TestFixture::new(Layout::from_size_align(2, 1).unwrap()); + + assert_that!(test.sut.number_of_buckets() as usize, eq PAYLOAD_SIZE / 2); + assert_that!(test.sut.relative_start_address() as usize, eq 0); + + let test = TestFixture::new(BUCKET_CONFIG); + + assert_that!(test.sut.bucket_size(), eq BUCKET_CONFIG.size()); + assert_that!(test.sut.max_alignment(), eq BUCKET_CONFIG.align()); + } + + #[test] + fn allocate_and_release_all_buckets_works() { + const REPETITIONS: usize = 10; + let test = TestFixture::new(BUCKET_CONFIG); + + for _ in 0..REPETITIONS { + let mut mem_set = HashSet::new(); + for _ in 0..test.sut.number_of_buckets() { + let memory = unsafe { test.sut.allocate(BUCKET_CONFIG).unwrap() }; + // the returned offset must be a multiple of the bucket size + assert_that!((memory.value() - test.sut.relative_start_address()) % BUCKET_CONFIG.size(), eq 0); + assert_that!(mem_set.insert(memory.value()), eq true); + } + + assert_that!(unsafe { test.sut.allocate(BUCKET_CONFIG) }, eq Err(ShmAllocationError::AllocationError(AllocationError::OutOfMemory))); + + for memory in mem_set { + unsafe { + test.sut + .deallocate(PointerOffset::new(memory), BUCKET_CONFIG) + } + } + } + } + + #[test] + fn allocate_with_unsupported_alignment_fails() { + let test = TestFixture::new(Layout::from_size_align(BUCKET_CONFIG.size(), 1).unwrap()); + assert_that!(unsafe { test.sut.allocate(BUCKET_CONFIG) }, eq Err(ShmAllocationError::ExceedsMaxSupportedAlignment)); + } +} From a25c5cd8567b4bd49188998512d000a62c1437b4 Mon Sep 17 00:00:00 2001 From: Christian Eltzschig Date: Thu, 7 Mar 2024 01:18:19 +0100 Subject: [PATCH 7/8] [#133] Add release notes --- doc/release-notes/iceoryx2-unreleased.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/release-notes/iceoryx2-unreleased.md b/doc/release-notes/iceoryx2-unreleased.md index 551fcef62..8e8e8ec86 100644 --- a/doc/release-notes/iceoryx2-unreleased.md +++ b/doc/release-notes/iceoryx2-unreleased.md @@ -14,6 +14,9 @@ * Introduce semantic string `iceoryx2-bb-system-types::base64url` * Introduce `iceoryx2-cal::hash::HashValue` that contains the result of a hash * Port `UsedChunkList` from iceoryx1 [#129](https://github.com/eclipse-iceoryx/iceoryx2/issues/129) + * From [#133](https://github.com/eclipse-iceoryx/iceoryx2/issues/133) + * Add `Notifier|Listener|Publisher|Subscriber::id()` method to acquire unique port id + * Add `Sample::origin()` to determine the `UniquePublisherId` of the sender * Performance improvements, especially for AMD CPUs [#136](https://github.com/eclipse-iceoryx/iceoryx2/issues/136) ### Bugfixes @@ -33,6 +36,7 @@ * Fix broken `Publisher|Subscriber::populate_{subscriber|publisher}_channels()` [#129](https://github.com/eclipse-iceoryx/iceoryx2/issues/129) * Fix failing reacquire of delivered samples in the zero copy receive channel [#130](https://github.com/eclipse-iceoryx/iceoryx2/issues/130) * Fix receiving of invalid samples when subscriber is connected [#131](https://github.com/eclipse-iceoryx/iceoryx2/issues/131) + * Fix problem where sample is released to the wrong publisher [#133](https://github.com/eclipse-iceoryx/iceoryx2/issues/133) * Fixes for FreeBSD 14.0 [#140](https://github.com/eclipse-iceoryx/iceoryx2/issues/140) * Fix segfault in `iceoryx2-pal-posix;:shm_list()` caused by `sysctl` * Adjust test to handle unordered event notifications From 13ea2efdb59deac32c9cac472a7abc32831fa44b Mon Sep 17 00:00:00 2001 From: Christian Eltzschig Date: Mon, 11 Mar 2024 09:58:06 +0100 Subject: [PATCH 8/8] [#133] Add one more random pool allocator test; make tests more explicit; add explanation to todos --- .../shm_allocator_pool_allocator_tests.rs | 38 ++++++++++ iceoryx2/tests/sample_mut_tests.rs | 51 +++++++------ iceoryx2/tests/sample_tests.rs | 76 ++++++++++--------- iceoryx2/tests/service_event_tests.rs | 4 +- 4 files changed, 108 insertions(+), 61 deletions(-) diff --git a/iceoryx2-cal/tests/shm_allocator_pool_allocator_tests.rs b/iceoryx2-cal/tests/shm_allocator_pool_allocator_tests.rs index 5c3e453c8..5c48bf99b 100644 --- a/iceoryx2-cal/tests/shm_allocator_pool_allocator_tests.rs +++ b/iceoryx2-cal/tests/shm_allocator_pool_allocator_tests.rs @@ -94,6 +94,44 @@ mod shm_allocator_pool_allocator { } } + #[test] + fn allocate_twice_release_once_until_memory_is_exhausted_works() { + const REPETITIONS: usize = 10; + let test = TestFixture::new(BUCKET_CONFIG); + + for _ in 0..REPETITIONS { + let mut mem_set = HashSet::new(); + for _ in 0..(test.sut.number_of_buckets() - 1) { + let memory_1 = unsafe { test.sut.allocate(BUCKET_CONFIG).unwrap() }; + // the returned offset must be a multiple of the bucket size + assert_that!((memory_1.value() - test.sut.relative_start_address()) % BUCKET_CONFIG.size(), eq 0); + + let memory_2 = unsafe { test.sut.allocate(BUCKET_CONFIG).unwrap() }; + // the returned offset must be a multiple of the bucket size + assert_that!((memory_2.value() - test.sut.relative_start_address()) % BUCKET_CONFIG.size(), eq 0); + assert_that!(mem_set.insert(memory_2.value()), eq true); + + unsafe { + test.sut.deallocate(memory_1, BUCKET_CONFIG); + } + } + + let memory = unsafe { test.sut.allocate(BUCKET_CONFIG).unwrap() }; + // the returned offset must be a multiple of the bucket size + assert_that!((memory.value() - test.sut.relative_start_address()) % BUCKET_CONFIG.size(), eq 0); + assert_that!(mem_set.insert(memory.value()), eq true); + + assert_that!(unsafe { test.sut.allocate(BUCKET_CONFIG) }, eq Err(ShmAllocationError::AllocationError(AllocationError::OutOfMemory))); + + for memory in mem_set { + unsafe { + test.sut + .deallocate(PointerOffset::new(memory), BUCKET_CONFIG) + } + } + } + } + #[test] fn allocate_with_unsupported_alignment_fails() { let test = TestFixture::new(Layout::from_size_align(BUCKET_CONFIG.size(), 1).unwrap()); diff --git a/iceoryx2/tests/sample_mut_tests.rs b/iceoryx2/tests/sample_mut_tests.rs index 25dc383f5..aea0b2c61 100644 --- a/iceoryx2/tests/sample_mut_tests.rs +++ b/iceoryx2/tests/sample_mut_tests.rs @@ -12,7 +12,7 @@ #[generic_tests::define] mod sample_mut { - use iceoryx2::port::publisher::Publisher; + use iceoryx2::port::publisher::{Publisher, PublisherLoanError}; use iceoryx2::port::subscriber::Subscriber; use iceoryx2::prelude::*; use iceoryx2::service::builder::publish_subscribe::PublishSubscribeCreateError; @@ -31,14 +31,14 @@ mod sample_mut { .unwrap() } - struct TestFixture { + struct TestContext { service_name: ServiceName, service: PortFactory, publisher: Publisher, subscriber: Subscriber, } - impl TestFixture { + impl TestContext { fn new() -> Self { let service_name = generate_name(); let service = Sut::new(&service_name) @@ -66,33 +66,40 @@ mod sample_mut { #[test] fn when_going_out_of_scope_it_is_released() { - let test = TestFixture::::new(); + let test_context = TestContext::::new(); let mut sample_vec = vec![]; for _ in 0..4 { - while let Ok(sample) = test.publisher.loan() { + while let Ok(sample) = test_context.publisher.loan() { sample_vec.push(sample); } assert_that!(sample_vec, len MAX_LOANED_SAMPLES); + + let loan_result = test_context.publisher.loan(); + assert_that!(loan_result, is_err); + assert_that!(loan_result.err().unwrap(), eq PublisherLoanError::ExceedsMaxLoanedChunks); + sample_vec.clear(); + + assert_that!(test_context.publisher.loan(), is_ok); } } #[test] fn header_tracks_correct_origin() { - let test = TestFixture::::new(); - let sample = test.publisher.loan().unwrap(); - assert_that!(sample.header().publisher_id(), eq test.publisher.id()); + let test_context = TestContext::::new(); + let sample = test_context.publisher.loan().unwrap(); + assert_that!(sample.header().publisher_id(), eq test_context.publisher.id()); } #[test] fn write_payload_works() { const PAYLOAD_1: u64 = 891283689123555; const PAYLOAD_2: u64 = 71820; - let test = TestFixture::::new(); - let sample = test.publisher.loan_uninit().unwrap(); + let test_context = TestContext::::new(); + let sample = test_context.publisher.loan_uninit().unwrap(); let mut sample = sample.write_payload(PAYLOAD_1); assert_that!(*sample.payload(), eq PAYLOAD_1); @@ -107,8 +114,8 @@ mod sample_mut { #[test] fn assume_init_works() { const PAYLOAD: u64 = 7182055123; - let test = TestFixture::::new(); - let mut sample = test.publisher.loan_uninit().unwrap(); + let test_context = TestContext::::new(); + let mut sample = test_context.publisher.loan_uninit().unwrap(); let _ = *sample.payload_mut().write(PAYLOAD); let mut sample = unsafe { sample.assume_init() }; @@ -119,23 +126,23 @@ mod sample_mut { #[test] fn send_works() { const PAYLOAD: u64 = 3215357; - let test = TestFixture::::new(); - let sample = test.publisher.loan_uninit().unwrap(); + let test_context = TestContext::::new(); + let sample = test_context.publisher.loan_uninit().unwrap(); let sample = sample.write_payload(PAYLOAD); assert_that!(sample.send(), eq Ok(1)); - let received_sample = test.subscriber.receive().unwrap().unwrap(); + let received_sample = test_context.subscriber.receive().unwrap().unwrap(); assert_that!(*received_sample, eq PAYLOAD); } #[test] fn sample_of_dropped_service_does_block_new_service_creation() { - let test = TestFixture::::new(); - let service_name = test.service_name.clone(); - let _sample = test.publisher.loan_uninit().unwrap(); + let test_context = TestContext::::new(); + let service_name = test_context.service_name.clone(); + let _sample = test_context.publisher.loan_uninit().unwrap(); - drop(test); + drop(test_context); let result = Sut::new(&service_name).publish_subscribe().create::(); assert_that!(result, is_err); @@ -144,9 +151,9 @@ mod sample_mut { #[test] fn sample_of_dropped_publisher_does_not_block_new_publishers() { - let test = TestFixture::::new(); - let service = test.service; - let publisher = test.publisher; + let test_context = TestContext::::new(); + let service = test_context.service; + let publisher = test_context.publisher; let _sample = publisher.loan_uninit().unwrap(); drop(publisher); diff --git a/iceoryx2/tests/sample_tests.rs b/iceoryx2/tests/sample_tests.rs index f363bd09c..24e114772 100644 --- a/iceoryx2/tests/sample_tests.rs +++ b/iceoryx2/tests/sample_tests.rs @@ -28,7 +28,7 @@ mod sample { .unwrap() } - struct TestFixture { + struct TestContext { service_name: ServiceName, service: PortFactory, publisher_1: Publisher, @@ -36,7 +36,7 @@ mod sample { subscriber: Subscriber, } - impl TestFixture { + impl TestContext { fn new() -> Self { let service_name = generate_name(); let service = Sut::new(&service_name) @@ -64,28 +64,28 @@ mod sample { #[test] fn origin_is_tracked_correctly() { - let test = TestFixture::::new(); + let test_context = TestContext::::new(); - assert_that!(test.publisher_1.send_copy(123), eq Ok(1)); - let sample = test.subscriber.receive().unwrap().unwrap(); - assert_that!(sample.origin(), eq test.publisher_1.id()); + assert_that!(test_context.publisher_1.send_copy(123), eq Ok(1)); + let sample = test_context.subscriber.receive().unwrap().unwrap(); + assert_that!(sample.origin(), eq test_context.publisher_1.id()); - assert_that!(test.publisher_2.send_copy(123), eq Ok(1)); - let sample = test.subscriber.receive().unwrap().unwrap(); - assert_that!(sample.origin(), eq test.publisher_2.id()); + assert_that!(test_context.publisher_2.send_copy(123), eq Ok(1)); + let sample = test_context.subscriber.receive().unwrap().unwrap(); + assert_that!(sample.origin(), eq test_context.publisher_2.id()); } #[test] fn sample_of_dropped_service_does_not_block_new_service_creation() { - let test = TestFixture::::new(); + let test_context = TestContext::::new(); - let service_name = test.service_name; + let service_name = test_context.service_name; - assert_that!(test.publisher_1.send_copy(5), eq Ok(1)); - let sample = test.subscriber.receive().unwrap(); + assert_that!(test_context.publisher_1.send_copy(5), eq Ok(1)); + let sample = test_context.subscriber.receive().unwrap(); assert_that!(sample, is_some); - drop(test); + drop(test_context); assert_that!( Sut::new(&service_name).publish_subscribe().create::(), @@ -95,12 +95,12 @@ mod sample { #[test] fn when_everything_is_dropped_the_sample_can_still_be_consumed() { - let test = TestFixture::::new(); + let test_context = TestContext::::new(); - let sut = test.service; - let publisher_1 = test.publisher_1; - let publisher_2 = test.publisher_2; - let subscriber = test.subscriber; + let sut = test_context.service; + let publisher_1 = test_context.publisher_1; + let publisher_2 = test_context.publisher_2; + let subscriber = test_context.subscriber; drop(sut); @@ -118,43 +118,45 @@ mod sample { #[test] fn sample_received_from_dropped_publisher_does_not_block_new_publishers() { - let test = TestFixture::::new(); + let test_context = TestContext::::new(); + const PAYLOAD_1: u64 = 123554; - let publisher = test.publisher_1; + let publisher = test_context.publisher_1; - assert_that!(publisher.send_copy(123554), eq Ok(1)); - let sample = test.subscriber.receive().unwrap().unwrap(); + assert_that!(publisher.send_copy(PAYLOAD_1), eq Ok(1)); + let sample = test_context.subscriber.receive().unwrap().unwrap(); drop(publisher); - const PAYLOAD: u64 = 123981235645; + const PAYLOAD_2: u64 = 123981235645; - let publisher = test.service.publisher().create().unwrap(); - assert_that!(publisher.send_copy(PAYLOAD), eq Ok(1)); - assert_that!(*sample, eq 123554); - let sample_2 = test.subscriber.receive().unwrap().unwrap(); - assert_that!(*sample_2, eq PAYLOAD); + let publisher = test_context.service.publisher().create().unwrap(); + assert_that!(publisher.send_copy(PAYLOAD_2), eq Ok(1)); + assert_that!(*sample, eq PAYLOAD_1); + let sample_2 = test_context.subscriber.receive().unwrap().unwrap(); + assert_that!(*sample_2, eq PAYLOAD_2); } #[test] fn sample_from_dropped_subscriber_does_not_block_new_subscribers() { - let test = TestFixture::::new(); + let test_context = TestContext::::new(); + const PAYLOAD_1: u64 = 7781123554; - let subscriber = test.subscriber; + let subscriber = test_context.subscriber; - assert_that!(test.publisher_1.send_copy(1234), eq Ok(1)); + assert_that!(test_context.publisher_1.send_copy(PAYLOAD_1), eq Ok(1)); let _sample = subscriber.receive().unwrap().unwrap(); drop(subscriber); - const PAYLOAD: u64 = 123666645; + const PAYLOAD_2: u64 = 123666645; - let subscriber = test.service.subscriber().create().unwrap(); - assert_that!(test.publisher_1.send_copy(PAYLOAD), eq Ok(1)); + let subscriber = test_context.service.subscriber().create().unwrap(); + assert_that!(test_context.publisher_1.send_copy(PAYLOAD_2), eq Ok(1)); let sample_1 = subscriber.receive().unwrap().unwrap(); let sample_2 = subscriber.receive().unwrap().unwrap(); - assert_that!(*sample_1, eq 1234); - assert_that!(*sample_2, eq PAYLOAD); + assert_that!(*sample_1, eq PAYLOAD_1); + assert_that!(*sample_2, eq PAYLOAD_2); } #[instantiate_tests()] diff --git a/iceoryx2/tests/service_event_tests.rs b/iceoryx2/tests/service_event_tests.rs index d20ceb5e5..dfd443e6e 100644 --- a/iceoryx2/tests/service_event_tests.rs +++ b/iceoryx2/tests/service_event_tests.rs @@ -371,7 +371,7 @@ mod service_event { } #[test] - // TODO iox2-139 + // TODO iox2-139, enable when bitset is integrated into events #[ignore] fn concurrent_reconnecting_notifier_can_trigger_waiting_listener() { let _watch_dog = Watchdog::new(Duration::from_secs(10)); @@ -432,7 +432,7 @@ mod service_event { } #[test] - // TODO iox2-139 + // TODO iox2-139, enable when bitset is integrated into events #[ignore] fn concurrent_reconnecting_listener_can_wait_for_triggering_notifiers() { let _watch_dog = Watchdog::new(Duration::from_secs(1));