extern crate alloc;
use alloc::vec::Vec;
use crate::metis::{
Anchor, Cut, DotSet, Dotted, Metatheses, RefoundMap, RefoundMapDecodeBudget,
RefoundMapDecodeError, Rhapsody,
};
use super::{Seq, clock, d, delete, fixture_map, insert};
#[test]
fn test_refound_map_to_bytes_layout() {
let map = fixture_map();
let frame = map.to_bytes();
assert_eq!(
frame,
[
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ]
);
assert_eq!(RefoundMap::from_bytes(&frame), Ok(map));
}
#[test]
fn test_refound_map_empty_frame() {
let refounded = Rhapsody::new()
.refound(&Metatheses::new())
.expect("the empty stratum folds");
let (_, map) = refounded.into_parts();
let frame = map.to_bytes();
assert_eq!(
frame,
[0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
);
assert_eq!(RefoundMap::from_bytes(&frame), Ok(map));
}
#[test]
fn test_refound_map_swept_station_row() {
let mut replica: Seq = Dotted::new();
let one = clock(1);
let three = clock(3);
let a = insert(&mut replica, &one, 1, Anchor::Origin);
let b = insert(&mut replica, &three, 3, Anchor::After(a.into()));
delete(&mut replica, b);
let refounded = replica
.store()
.refound(&Metatheses::new())
.expect("a sealed stratum folds");
let (_, map) = refounded.into_parts();
assert_eq!(map.translate(d(3, 1)), None, "the swept dot has no image");
let frame = map.to_bytes();
let decoded = RefoundMap::from_bytes(&frame).expect("a swept-station frame decodes");
assert_eq!(decoded, map);
assert_eq!(decoded.to_bytes(), frame);
assert_eq!(decoded.translate(d(3, 1)), None);
assert_eq!(
decoded.translate(d(3, 2)),
Some(d(3, 1)),
"the affine window opens just above the swept station's ceiling"
);
}
#[test]
fn test_refound_map_entry_order_is_semantic() {
let map = fixture_map();
let frame = map.to_bytes();
let mut permuted = frame.clone();
let head: [u8; 8] = frame[29..37].try_into().unwrap();
let tail: [u8; 8] = frame[37..45].try_into().unwrap();
permuted[29..37].copy_from_slice(&tail);
permuted[37..45].copy_from_slice(&head);
let decoded = RefoundMap::from_bytes(&permuted).expect("the permuted frame is canonical too");
assert_ne!(decoded, map, "the permutation is the map's content");
assert_eq!(map.translate(d(1, 1)), Some(d(1, 1)));
assert_eq!(
decoded.translate(d(1, 1)),
Some(d(1, 2)),
"old 1 now lands second"
);
assert_eq!(
decoded.translate(d(1, 3)),
Some(d(1, 1)),
"old 3 now lands first"
);
assert_eq!(decoded.to_bytes(), permuted);
}
#[test]
fn test_refound_map_cut_bound_map_round_trips() {
let mut replica: Seq = Dotted::new();
let one = clock(1);
let a = insert(&mut replica, &one, 1, Anchor::Origin);
let _b = insert(&mut replica, &one, 1, Anchor::After(a.into()));
let refounded = replica
.store()
.refound(&Metatheses::new())
.expect("a sealed stratum folds");
let (_, mut map) = refounded.into_parts();
let mut have = DotSet::new();
for dot in 1..=4 {
assert!(have.insert(d(1, dot)));
}
map.bind_cut(&Cut::floor_of(&have));
assert_eq!(
map.translate(d(1, 3)),
None,
"below the cut, unwitnessed: no image"
);
assert_eq!(
map.translate(d(1, 5)),
Some(d(1, 3)),
"above the cut: affine"
);
let frame = map.to_bytes();
let decoded = RefoundMap::from_bytes(&frame).expect("a cut-bound frame decodes");
assert_eq!(decoded, map);
assert_eq!(decoded.to_bytes(), frame);
assert_eq!(decoded.translate(d(1, 3)), None);
assert_eq!(decoded.translate(d(1, 5)), Some(d(1, 3)));
}
#[test]
fn test_refound_map_unknown_version_refused() {
let mut frame = fixture_map().to_bytes();
frame[0] = 0x02;
assert_eq!(
RefoundMap::from_bytes(&frame),
Err(RefoundMapDecodeError::UnknownVersion(0x02))
);
assert_eq!(
RefoundMap::from_bytes(&[]),
Err(RefoundMapDecodeError::UnexpectedLength {
expected: 9,
found: 0,
})
);
}
#[test]
fn test_refound_map_truncation_refused() {
let frame = fixture_map().to_bytes();
let cut = &frame[..frame.len() - 4];
assert!(matches!(
RefoundMap::from_bytes(cut),
Err(RefoundMapDecodeError::UnexpectedLength { .. })
));
let mut hostile = Vec::from(&[0x01u8][..]);
hostile.extend_from_slice(&u64::MAX.to_be_bytes());
assert!(matches!(
RefoundMap::from_bytes(&hostile),
Err(RefoundMapDecodeError::UnexpectedLength { .. })
));
}
#[test]
fn test_refound_map_impossible_count_refuses_before_rows() {
let mut frame = fixture_map().to_bytes();
frame[1..9].copy_from_slice(&4u64.to_be_bytes());
for byte in &mut frame[13..21] {
*byte = 0;
}
assert!(matches!(
RefoundMap::from_bytes(&frame),
Err(RefoundMapDecodeError::UnexpectedLength { .. })
));
}
#[test]
fn test_refound_map_trailing_bytes_refused() {
let mut frame = fixture_map().to_bytes();
let exact = frame.len();
frame.push(0x00);
assert_eq!(
RefoundMap::from_bytes(&frame),
Err(RefoundMapDecodeError::UnexpectedLength {
expected: exact,
found: exact + 1,
})
);
}
#[test]
fn test_refound_map_zero_ceiling_refused() {
let mut frame = fixture_map().to_bytes();
for byte in &mut frame[13..21] {
*byte = 0;
}
assert_eq!(
RefoundMap::from_bytes(&frame),
Err(RefoundMapDecodeError::ZeroCeiling { station: 1 })
);
}
#[test]
fn test_refound_map_non_ascending_stations_refused() {
let mut frame = Vec::from(&[0x01u8][..]);
frame.extend_from_slice(&2u64.to_be_bytes());
for station in [2u32, 1u32] {
frame.extend_from_slice(&station.to_be_bytes());
frame.extend_from_slice(&1u64.to_be_bytes()); frame.extend_from_slice(&0u64.to_be_bytes()); }
assert_eq!(
RefoundMap::from_bytes(&frame),
Err(RefoundMapDecodeError::NonAscendingStations {
previous: 2,
found: 1,
})
);
let mut duplicated = Vec::from(&[0x01u8][..]);
duplicated.extend_from_slice(&2u64.to_be_bytes());
for _ in 0..2 {
duplicated.extend_from_slice(&1u32.to_be_bytes());
duplicated.extend_from_slice(&1u64.to_be_bytes());
duplicated.extend_from_slice(&0u64.to_be_bytes());
}
assert_eq!(
RefoundMap::from_bytes(&duplicated),
Err(RefoundMapDecodeError::NonAscendingStations {
previous: 1,
found: 1,
})
);
}
#[test]
fn test_refound_map_live_exceeds_ceiling_refused() {
let mut frame = Vec::from(&[0x01u8][..]);
frame.extend_from_slice(&1u64.to_be_bytes());
frame.extend_from_slice(&1u32.to_be_bytes());
frame.extend_from_slice(&1u64.to_be_bytes()); frame.extend_from_slice(&2u64.to_be_bytes()); frame.extend_from_slice(&1u64.to_be_bytes());
frame.extend_from_slice(&1u64.to_be_bytes());
assert_eq!(
RefoundMap::from_bytes(&frame),
Err(RefoundMapDecodeError::LiveExceedsCeiling {
station: 1,
live: 2,
ceiling: 1,
})
);
}
#[test]
fn test_refound_map_index_out_of_range_refused() {
let mut zeroed = fixture_map().to_bytes();
for byte in &mut zeroed[37..45] {
*byte = 0;
}
assert_eq!(
RefoundMap::from_bytes(&zeroed),
Err(RefoundMapDecodeError::IndexOutOfRange {
station: 1,
index: 0,
ceiling: 3,
})
);
let mut above = fixture_map().to_bytes();
above[44] = 0x04;
assert_eq!(
RefoundMap::from_bytes(&above),
Err(RefoundMapDecodeError::IndexOutOfRange {
station: 1,
index: 4,
ceiling: 3,
})
);
}
#[test]
fn test_refound_map_duplicate_index_refused() {
let mut frame = fixture_map().to_bytes();
frame[44] = 0x01;
assert_eq!(
RefoundMap::from_bytes(&frame),
Err(RefoundMapDecodeError::DuplicateIndex {
station: 1,
index: 1,
})
);
}
#[test]
fn test_refound_map_budget_refusals() {
let map = fixture_map();
let frame = map.to_bytes();
assert_eq!(
RefoundMap::from_bytes_with_budget(&frame, RefoundMapDecodeBudget::new(1, 3)),
Err(RefoundMapDecodeError::TooManyStations {
count: 2,
budget: 1,
})
);
assert_eq!(
RefoundMap::from_bytes_with_budget(&frame, RefoundMapDecodeBudget::new(2, 2)),
Err(RefoundMapDecodeError::TooManyEntries {
count: 3,
budget: 2,
})
);
assert_eq!(
RefoundMap::from_bytes_with_budget(&frame, RefoundMapDecodeBudget::new(2, 3)),
Ok(map)
);
}