use core::num::NonZeroU64;
use super::Span;
fn any_dot() -> NonZeroU64 {
let raw: u64 = kani::any();
kani::assume(raw != 0);
NonZeroU64::new(raw).unwrap()
}
fn any_span(station: u32) -> Span {
let start = any_dot();
let end = any_dot();
kani::assume(start <= end);
Span {
station,
start,
end,
}
}
#[kani::proof]
fn contains_agrees_with_range() {
let span = any_span(0);
let dot = any_dot();
let by_arith = span.start <= dot && dot <= span.end;
assert_eq!(span.contains(0, dot), by_arith);
assert!(!span.contains(1, dot));
}
#[kani::proof]
fn len_never_overflows() {
let span = any_span(0);
let diff = span.end.get() - span.start.get();
let len = diff.checked_add(1).expect("run cardinality fits u64");
assert_eq!(span.len(), len);
assert!(span.len() >= 1);
}
#[kani::proof]
fn coalesce_is_commutative() {
let a = any_span(0);
let b = any_span(0);
match (a.coalesce(b), b.coalesce(a)) {
(Ok(ab), Ok(ba)) => assert_eq!(ab, ba),
(Err((a1, b1)), Err((b2, a2))) => {
assert_eq!(a1, a2);
assert_eq!(b1, b2);
}
_ => kani::assert(
false,
"coalesce disagrees on mergeability across the argument order",
),
}
}
#[kani::proof]
fn coalesce_is_associative_where_defined() {
let a = any_span(0);
let b = any_span(0);
let c = any_span(0);
if let (Ok(ab), Ok(bc)) = (a.coalesce(b), b.coalesce(c))
&& let (Ok(left), Ok(right)) = (ab.coalesce(c), a.coalesce(bc))
{
assert_eq!(left, right);
}
}
#[kani::proof]
fn split_then_coalesce_is_identity() {
let span = any_span(0);
let seq = any_dot();
let (head, tail) = span.split_at(seq);
match tail {
Some(tail) => {
assert!(head.abuts(&tail));
assert_eq!(head.coalesce(tail), Ok(span));
}
None => assert_eq!(head, span),
}
}