Skip to content

Commit

Permalink
[eclipse-iceoryx#195] Add tests for publisher sliced API
Browse files Browse the repository at this point in the history
  • Loading branch information
elfenpiff committed Apr 24, 2024
1 parent 86d279c commit 44c5837
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 9 deletions.
31 changes: 25 additions & 6 deletions iceoryx2/src/port/publisher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ use crate::service::dynamic_config::publish_subscribe::{PublisherDetails, Subscr
use crate::service::header::publish_subscribe::Header;
use crate::service::naming_scheme::data_segment_name;
use crate::service::port_factory::publisher::{LocalPublisherConfig, UnableToDeliverStrategy};
use crate::service::static_config::publish_subscribe;
use crate::service::static_config::publish_subscribe::{self, TypeDetails};
use crate::{config, sample_mut::SampleMut};
use iceoryx2_bb_container::queue::Queue;
use iceoryx2_bb_elementary::allocator::AllocationError;
Expand Down Expand Up @@ -111,6 +111,7 @@ impl std::error::Error for PublisherCreateError {}
pub enum PublisherLoanError {
OutOfMemory,
ExceedsMaxLoanedChunks,
ExceedsMaxLoanSize,
InternalFailure,
}

Expand Down Expand Up @@ -674,12 +675,10 @@ impl<Service: service::Service, MessageType: Debug + Sized> Publisher<Service, M
&self,
) -> Result<SampleMut<MaybeUninit<MessageType>, Service>, PublisherLoanError> {
let chunk = self.allocate(RawSampleMut::<Header, MessageType>::layout())?;

let (header_ptr, message_ptr) =
RawSampleMut::<Header, MessageType>::header_message_ptr(chunk.data_ptr);

unsafe { header_ptr.write(Header::new(self.data_segment.port_id)) };
unsafe { message_ptr.write(MaybeUninit::uninit()) };

let sample = unsafe { RawSampleMut::new_unchecked(header_ptr, message_ptr) };
Ok(SampleMut::<MaybeUninit<MessageType>, Service>::new(
Expand Down Expand Up @@ -737,7 +736,8 @@ impl<Service: service::Service, MessageType: Default + Debug> Publisher<Service,
&self,
number_of_elements: usize,
) -> Result<SampleMut<[MessageType], Service>, PublisherLoanError> {
todo!()
let sample = self.loan_slice_uninit(number_of_elements)?;
Ok(sample.write_from_fn(|_| MessageType::default()))
}
}

Expand All @@ -746,6 +746,27 @@ impl<Service: service::Service, MessageType: Debug> Publisher<Service, [MessageT
&self,
number_of_elements: usize,
) -> Result<SampleMut<[MaybeUninit<MessageType>], Service>, PublisherLoanError> {
let max_elements = if let TypeDetails::Sliced { sliced: d } = self
.data_segment
.static_config
.publish_subscribe()
.type_details()
{
d.max_elements
} else {
debug_assert!(
false,
"This should never happen! The Publisher Type is not a slice."
);
0
};

if max_elements < number_of_elements {
fail!(from self, with PublisherLoanError::ExceedsMaxLoanSize,
"Unable to loan slice with {} elements since it would exceed the max supported number of elements of {}.",
number_of_elements, max_elements);
}

let layout = RawSampleMut::<Header, [MessageType]>::layout_slice(number_of_elements);
let chunk = self.allocate(layout)?;

Expand All @@ -756,8 +777,6 @@ impl<Service: service::Service, MessageType: Debug> Publisher<Service, [MessageT
);

unsafe { header_ptr.write(Header::new(self.data_segment.port_id)) };
//unsafe { (*message_ptr) };

let sample = unsafe { RawSampleMut::new_unchecked(header_ptr, message_ptr) };

Ok(SampleMut::<[MaybeUninit<MessageType>], Service>::new(
Expand Down
21 changes: 21 additions & 0 deletions iceoryx2/src/sample_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,27 @@ impl<MessageType: Debug, Service: crate::service::Service>
}
}

impl<MessageType: Debug, Service: crate::service::Service>
SampleMut<[MaybeUninit<MessageType>], Service>
{
pub unsafe fn assume_init(self) -> SampleMut<[MessageType], Service> {
// the transmute is not nice but safe since MaybeUninit is #[repr(transparent)] to the inner type
std::mem::transmute(self)
}

pub fn write_from_fn<F: FnMut(usize) -> MessageType>(
mut self,
mut initializer: F,
) -> SampleMut<[MessageType], Service> {
for (i, element) in self.payload_mut().iter_mut().enumerate() {
element.write(initializer(i));
}

// SAFETY: this is safe since the payload was initialized on the line above
unsafe { self.assume_init() }
}
}

impl<
M: Debug + ?Sized, // `M` is either a `MessageType` or a `MaybeUninit<MessageType>`
Service: crate::service::Service,
Expand Down
2 changes: 1 addition & 1 deletion iceoryx2/src/service/builder/publish_subscribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ impl<ServiceType: service::Service> Builder<ServiceType> {
}

/// Returns the [`SlicedBuilder`] to create a slice typed [`Service`].
pub fn slice<MessageType: Debug>(mut self) -> SlicedBuilder<MessageType, ServiceType> {
pub fn sliced<MessageType: Debug>(mut self) -> SlicedBuilder<MessageType, ServiceType> {
self.config_details_mut().type_details = TypeDetails::from_slice::<MessageType, Header>(1);

SlicedBuilder {
Expand Down
91 changes: 91 additions & 0 deletions iceoryx2/tests/publisher_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@ mod publisher {
))?)
}

const COMPLEX_TYPE_DEFAULT_VALUE: u64 = 872379237;

#[derive(Debug)]
#[repr(C)]
struct ComplexType {
data: u64,
}

impl Default for ComplexType {
fn default() -> Self {
ComplexType {
data: COMPLEX_TYPE_DEFAULT_VALUE,
}
}
}

#[test]
fn publisher_loan_and_send_sample_works<Sut: Service>() -> TestResult<()> {
let service_name = generate_name()?;
Expand All @@ -50,6 +66,81 @@ mod publisher {
Ok(())
}

#[test]
fn publisher_loan_initializes_sample_with_default<Sut: Service>() -> TestResult<()> {
let service_name = generate_name()?;
let service = Sut::new(&service_name)
.publish_subscribe()
.typed::<ComplexType>()
.create()?;

let publisher = service.publisher().create()?;
let sut = publisher.loan()?;

assert_that!(sut.payload().data, eq COMPLEX_TYPE_DEFAULT_VALUE);

Ok(())
}

#[test]
fn publisher_loan_slice_initializes_sample_with_default<Sut: Service>() -> TestResult<()> {
const NUMBER_OF_ELEMENTS: usize = 120;
let service_name = generate_name()?;
let service = Sut::new(&service_name)
.publish_subscribe()
.sliced::<ComplexType>()
.max_elements(NUMBER_OF_ELEMENTS)
.create()?;

let publisher = service.publisher().create()?;
let sut = publisher.loan_slice(NUMBER_OF_ELEMENTS)?;

for i in 0..NUMBER_OF_ELEMENTS {
assert_that!(sut.payload()[i].data, eq COMPLEX_TYPE_DEFAULT_VALUE);
}

Ok(())
}

#[test]
fn publisher_loan_slice_up_to_max_elements_works<Sut: Service>() -> TestResult<()> {
const NUMBER_OF_ELEMENTS: usize = 125;
let service_name = generate_name()?;
let service = Sut::new(&service_name)
.publish_subscribe()
.sliced::<ComplexType>()
.max_elements(NUMBER_OF_ELEMENTS)
.create()?;

let publisher = service.publisher().create()?;

for i in 0..NUMBER_OF_ELEMENTS {
let sut = publisher.loan_slice(i)?;
assert_that!(sut.payload().len(), eq i);
}

Ok(())
}

#[test]
fn publisher_loan_slice_more_than_max_elements_fails<Sut: Service>() -> TestResult<()> {
const NUMBER_OF_ELEMENTS: usize = 125;
let service_name = generate_name()?;
let service = Sut::new(&service_name)
.publish_subscribe()
.sliced::<ComplexType>()
.max_elements(NUMBER_OF_ELEMENTS)
.create()?;

let publisher = service.publisher().create()?;

let sut = publisher.loan_slice(NUMBER_OF_ELEMENTS + 1);
assert_that!(sut, is_err);
assert_that!(sut.err().unwrap(), eq PublisherLoanError::ExceedsMaxLoanSize);

Ok(())
}

#[test]
fn publisher_loan_unit_and_send_sample_works<Sut: Service>() -> TestResult<()> {
let service_name = generate_name()?;
Expand Down
4 changes: 2 additions & 2 deletions iceoryx2/tests/service_publish_subscribe_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1794,15 +1794,15 @@ mod service_publish_subscribe {
let service_name = generate_name();
let sut = Sut::new(&service_name)
.publish_subscribe()
.slice::<u64>()
.sliced::<u64>()
.max_elements(12)
.create()
.unwrap();

let publisher = sut.publisher().create().unwrap();
let subscriber = sut.subscriber().create().unwrap();

let sample = publisher.loan_slice_uninit(11).unwrap();
let sample = publisher.loan_slice(11).unwrap();
}

#[instantiate_tests(<iceoryx2::service::zero_copy::Service>)]
Expand Down

0 comments on commit 44c5837

Please sign in to comment.