#![forbid(unsafe_code)]
use ridl_rt::contract::{InterfaceNo, Ordinal};
use ridl_rt::sample::{Continuity, EventSeqTracker, TrackerFull};
const IFACE: InterfaceNo = InterfaceNo(1);
const OTHER_IFACE: InterfaceNo = InterfaceNo(2);
const SHIFT_DONE: Ordinal = Ordinal(2);
const DOOR_OPENED: Ordinal = Ordinal(3);
#[test]
fn the_first_occurrence_of_a_channel_reports_no_loss() {
let mut tracker = EventSeqTracker::<2>::new();
assert_eq!(
tracker.observe(IFACE, SHIFT_DONE, 41),
Ok(Continuity::First)
);
}
#[test]
fn consecutive_seqs_report_no_loss() {
let mut tracker = EventSeqTracker::<2>::new();
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 1), Ok(Continuity::First));
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 2), Ok(Continuity::Next));
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 3), Ok(Continuity::Next));
}
#[test]
fn a_gap_is_reported_as_a_loss_of_its_width() {
let mut tracker = EventSeqTracker::<2>::new();
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 1), Ok(Continuity::First));
assert_eq!(
tracker.observe(IFACE, SHIFT_DONE, 3),
Ok(Continuity::Lost { count: 1 })
);
assert_eq!(
tracker.observe(IFACE, SHIFT_DONE, 10),
Ok(Continuity::Lost { count: 6 })
);
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 11), Ok(Continuity::Next));
}
#[test]
fn interleaved_channels_of_one_interface_report_no_loss() {
let mut tracker = EventSeqTracker::<2>::new();
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 1), Ok(Continuity::First));
assert_eq!(
tracker.observe(IFACE, DOOR_OPENED, 1),
Ok(Continuity::First)
);
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 2), Ok(Continuity::Next));
assert_eq!(tracker.observe(IFACE, DOOR_OPENED, 2), Ok(Continuity::Next));
assert_eq!(
tracker.observe(IFACE, DOOR_OPENED, 4),
Ok(Continuity::Lost { count: 1 })
);
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 3), Ok(Continuity::Next));
}
#[test]
fn one_ordinal_in_two_interfaces_is_two_channels() {
let mut tracker = EventSeqTracker::<2>::new();
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 5), Ok(Continuity::First));
assert_eq!(
tracker.observe(OTHER_IFACE, SHIFT_DONE, 9),
Ok(Continuity::First)
);
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 6), Ok(Continuity::Next));
assert_eq!(
tracker.observe(OTHER_IFACE, SHIFT_DONE, 10),
Ok(Continuity::Next)
);
}
#[test]
fn a_seq_not_newer_than_the_last_is_reported_and_leaves_the_last_unchanged() {
let mut tracker = EventSeqTracker::<2>::new();
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 5), Ok(Continuity::First));
assert_eq!(
tracker.observe(IFACE, SHIFT_DONE, 5),
Ok(Continuity::NotNewer { last: 5 })
);
assert_eq!(
tracker.observe(IFACE, SHIFT_DONE, 3),
Ok(Continuity::NotNewer { last: 5 })
);
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 6), Ok(Continuity::Next));
}
#[test]
fn a_channel_beyond_the_capacity_is_refused() {
let mut tracker = EventSeqTracker::<1>::new();
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 1), Ok(Continuity::First));
assert_eq!(tracker.observe(IFACE, DOOR_OPENED, 1), Err(TrackerFull));
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 2), Ok(Continuity::Next));
}
#[test]
fn a_forgotten_channel_starts_again_and_frees_its_slot() {
let mut tracker = EventSeqTracker::<1>::new();
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 1), Ok(Continuity::First));
tracker.forget(IFACE, SHIFT_DONE);
assert_eq!(
tracker.observe(IFACE, DOOR_OPENED, 7),
Ok(Continuity::First)
);
tracker.forget(IFACE, DOOR_OPENED);
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 9), Ok(Continuity::First));
}
#[test]
fn a_default_tracker_holds_no_channel() {
let mut tracker: EventSeqTracker<1> = Default::default();
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 3), Ok(Continuity::First));
}
#[test]
fn the_largest_seq_follows_its_predecessor() {
let mut tracker = EventSeqTracker::<1>::new();
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 0), Ok(Continuity::First));
assert_eq!(
tracker.observe(IFACE, SHIFT_DONE, u64::MAX),
Ok(Continuity::Lost {
count: u64::MAX - 1
})
);
assert_eq!(
tracker.observe(IFACE, SHIFT_DONE, u64::MAX),
Ok(Continuity::NotNewer { last: u64::MAX })
);
}
#[test]
fn a_tracker_can_be_built_in_a_const_context() {
const TRACKER: EventSeqTracker<4> = EventSeqTracker::new();
let mut tracker = TRACKER;
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 1), Ok(Continuity::First));
}
#[test]
fn forgetting_one_channel_leaves_the_others_counting() {
let mut tracker = EventSeqTracker::<2>::new();
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 1), Ok(Continuity::First));
assert_eq!(
tracker.observe(IFACE, DOOR_OPENED, 4),
Ok(Continuity::First)
);
tracker.forget(IFACE, SHIFT_DONE);
assert_eq!(tracker.observe(IFACE, DOOR_OPENED, 5), Ok(Continuity::Next));
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 8), Ok(Continuity::First));
}
#[test]
fn forgetting_a_channel_leaves_the_same_ordinal_in_another_interface() {
let mut tracker = EventSeqTracker::<2>::new();
assert_eq!(
tracker.observe(OTHER_IFACE, SHIFT_DONE, 1),
Ok(Continuity::First)
);
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 1), Ok(Continuity::First));
tracker.forget(IFACE, SHIFT_DONE);
assert_eq!(
tracker.observe(OTHER_IFACE, SHIFT_DONE, 2),
Ok(Continuity::Next)
);
assert_eq!(tracker.observe(IFACE, SHIFT_DONE, 9), Ok(Continuity::First));
}