Skip to content

Commit

Permalink
Merge pull request #462 from xieyuschen/iox2-213-posix-tests-uniid-an…
Browse files Browse the repository at this point in the history
…d-waiter

[#213] improves test cases for unique_id and adaptive_waiter
  • Loading branch information
elBoberido authored Oct 14, 2024
2 parents a48cd97 + 32dd773 commit 8a61101
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 10 deletions.
53 changes: 50 additions & 3 deletions iceoryx2-bb/posix/src/unique_system_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,20 +98,24 @@ impl From<u128> for UniqueSystemId {
impl UniqueSystemId {
/// Creates a new system wide unique id
pub fn new() -> Result<Self, UniqueSystemIdCreationError> {
static COUNTER: IoxAtomicU32 = IoxAtomicU32::new(0);
let msg = "Failed to create UniqueSystemId";
let pid = Process::from_self().id().value() as _;
let now = fail!(from "UniqueSystemId::new()",
when Time::now_with_clock(ClockType::default()),
with UniqueSystemIdCreationError::FailedToAcquireTime,
"{} since the current time could not be acquired.", msg);

Ok(UniqueSystemId {
Ok(Self::create(pid, now))
}

fn create(pid: u32, now: Time) -> UniqueSystemId {
static COUNTER: IoxAtomicU32 = IoxAtomicU32::new(0);
UniqueSystemId {
pid,
seconds: now.seconds() as u32,
nanoseconds: now.nanoseconds(),
counter: COUNTER.fetch_add(1, Ordering::Relaxed),
})
}
}

/// Returns the underlying value of the new system wide unique id
Expand All @@ -133,3 +137,46 @@ impl UniqueSystemId {
}
}
}

#[cfg(test)]
use iceoryx2_bb_testing::assert_that;

#[test]
// ensures the unique_system_id is unique when a process creates the id simultaneously.
fn test_unique_system_id_when_creating_simultaneously() {
let pid = Process::from_self().id().value() as _;
let now = Time::now_with_clock(ClockType::default()).unwrap();

let handle1 =
std::thread::spawn(move || -> UniqueSystemId { UniqueSystemId::create(pid, now) });
let handle2 =
std::thread::spawn(move || -> UniqueSystemId { UniqueSystemId::create(pid, now) });

let id1 = handle1.join().unwrap();
let id2 = handle2.join().unwrap();
assert_that!(id1.pid(), eq id2.pid());
assert_that!(id1.creation_time(), eq id2.creation_time());
assert_that!(id1.value(), ne id2.value());
}

#[test]
// ensures the unique_system_id is unique when 2 processes create their id simultaneously.
fn test_unique_system_id_across_processes() {
let pid = Process::from_self().id().value() as _;
let now = Time::now_with_clock(ClockType::default()).unwrap();

let id1 = UniqueSystemId::create(pid, now);
// ideally, fork and exec the current process to reset the static counter inside UniqueSystemId::create
// is better, but to ease the test now, we can duplicate the logic inside the lambda instead.
static COUNTER: IoxAtomicU32 = IoxAtomicU32::new(0);
let id2 = UniqueSystemId {
pid: pid + 1,
seconds: now.seconds() as u32,
nanoseconds: now.nanoseconds(),
counter: COUNTER.fetch_add(1, Ordering::Relaxed),
};

assert_that!(id1.pid(), ne id2.pid());
assert_that!(id1.creation_time(), eq id2.creation_time());
assert_that!(id1.value(), ne id2.value());
}
44 changes: 37 additions & 7 deletions iceoryx2-bb/posix/tests/adaptive_wait_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,50 @@ use std::time::Instant;
const TIMEOUT: Duration = Duration::from_millis(50);

#[test]
fn adaptive_wait_wait_loop_initial_repetitions_plus_one_is_at_least_final_waiting_time() {
let start = Instant::now();
fn adaptive_wait_wait_at_different_time_depends_on_repetition_times() {
let mut counter: u64 = 0;

AdaptiveWaitBuilder::new()
.create()
.unwrap()
let mut waiter = AdaptiveWaitBuilder::new().create().unwrap();

waiter
.wait_while(move || -> bool {
counter += 1;
counter <= ADAPTIVE_WAIT_YIELD_REPETITIONS
})
.expect("failed to test wait_loop");
// the waiter starts to sleep ADAPTIVE_WAIT_INITIAL_WAITING_TIME instead of yield later.
assert_that!(waiter.yield_count(), eq ADAPTIVE_WAIT_YIELD_REPETITIONS);

// test sleep time ADAPTIVE_WAIT_INITIAL_WAITING_TIME
let start = Instant::now();
waiter
.wait_while(move || -> bool {
counter += 1;
counter < ADAPTIVE_WAIT_INITIAL_REPETITIONS
counter <= 1 // stop at the second turn
})
.expect("failed to test wait_loop");
assert_that!(start.elapsed(), time_at_least ADAPTIVE_WAIT_INITIAL_WAITING_TIME);

assert_that!(start.elapsed(), ge ADAPTIVE_WAIT_FINAL_WAITING_TIME);
waiter
.wait_while(move || -> bool {
counter += 1;
// continue to reach the edge of sleeping time.
counter < ADAPTIVE_WAIT_INITIAL_REPETITIONS - ADAPTIVE_WAIT_YIELD_REPETITIONS
})
.expect("failed to test wait_loop");

// verify the waiter will enter the next stage at the next repetition.
// the waiter starts to sleep longer as ADAPTIVE_WAIT_FINAL_WAITING_TIME
// instead of ADAPTIVE_WAIT_INITIAL_WAITING_TIME later.
assert_that!(waiter.yield_count(), eq ADAPTIVE_WAIT_INITIAL_REPETITIONS);
let start = Instant::now();
waiter
.wait_while(move || -> bool {
counter += 1;
counter <= 1 // stop at the second turn
})
.expect("failed to test wait_loop");
assert_that!(start.elapsed(), time_at_least ADAPTIVE_WAIT_FINAL_WAITING_TIME);
}

#[test]
Expand Down

0 comments on commit 8a61101

Please sign in to comment.