extern crate alloc;
use alloc::vec::Vec;
use crate::metis::{
Anchor, Locus, Metatheses, MetathesesDecodeBudget, MetathesesDecodeError, Rhapsody,
};
use super::{canonical_record, d, rank, testimony};
use crate::metis::dot::RawDot;
#[test]
fn test_metatheses_to_bytes_layout() {
let record = canonical_record();
let frame = record.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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ]
);
assert_eq!(Metatheses::from_bytes(&frame), Ok(record));
}
#[test]
fn test_metatheses_empty_frame() {
let record = Metatheses::new();
let frame = record.to_bytes();
assert_eq!(
frame,
[0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
);
assert_eq!(Metatheses::from_bytes(&frame), Ok(record));
}
#[test]
fn test_metatheses_before_anchor_round_trips() {
let mut record = Metatheses::new();
assert!(record.insert(
d(1, 1),
testimony(
(2, 5),
Anchor::Before(RawDot {
station: 1,
counter: 4
}),
11
)
));
let frame = record.to_bytes();
assert_eq!(frame[33], 0x02, "the before-anchored row carries tag 0x02");
let decoded = Metatheses::from_bytes(&frame).expect("a before-anchored frame decodes");
assert_eq!(decoded, record);
assert_eq!(decoded.to_bytes(), frame);
}
#[test]
fn test_metatheses_anchor_tags_agree_with_rhapsody() {
let mut rhapsody = Rhapsody::new();
assert!(rhapsody.weave(
d(1, 1),
Locus {
anchor: Anchor::Origin,
rank: rank(7),
}
));
assert!(rhapsody.weave(
d(1, 2),
Locus {
anchor: Anchor::Before(RawDot {
station: 1,
counter: 1
}),
rank: rank(9),
}
));
let rhapsody_frame = rhapsody.to_bytes();
let mut record = Metatheses::new();
assert!(record.insert(d(1, 1), testimony((1, 1), Anchor::Origin, 7)));
assert!(record.insert(
d(1, 2),
testimony(
(1, 1),
Anchor::Before(RawDot {
station: 1,
counter: 1
}),
9
)
));
let metatheses_frame = record.to_bytes();
assert_eq!(rhapsody_frame[17], metatheses_frame[33]);
assert_eq!(rhapsody_frame[47], metatheses_frame[75]);
assert_eq!(rhapsody_frame[47], 0x02);
}
#[test]
fn test_metatheses_zero_target_round_trips() {
let mut record = Metatheses::new();
assert!(record.insert(d(1, 1), testimony((3, 0), Anchor::Origin, 7)));
let frame = record.to_bytes();
let decoded = Metatheses::from_bytes(&frame).expect("a zero-target frame decodes");
assert_eq!(decoded, record);
assert_eq!(decoded.to_bytes(), frame);
}
#[test]
fn test_metatheses_zero_anchor_round_trips() {
let mut record = Metatheses::new();
assert!(record.insert(
d(1, 1),
testimony(
(2, 2),
Anchor::After(RawDot {
station: 3,
counter: 0
}),
7
)
));
let frame = record.to_bytes();
let decoded = Metatheses::from_bytes(&frame).expect("a zero-anchor frame decodes");
assert_eq!(decoded, record);
assert_eq!(decoded.to_bytes(), frame);
}
#[test]
fn test_metatheses_unknown_version_refused() {
let mut frame = canonical_record().to_bytes();
frame[0] = 0x02;
assert_eq!(
Metatheses::from_bytes(&frame),
Err(MetathesesDecodeError::UnknownVersion(0x02))
);
assert_eq!(
Metatheses::from_bytes(&[]),
Err(MetathesesDecodeError::UnexpectedLength {
expected: 9,
found: 0,
})
);
}
#[test]
fn test_metatheses_truncation_refused() {
let frame = canonical_record().to_bytes();
let cut = &frame[..frame.len() - 10];
assert!(matches!(
Metatheses::from_bytes(cut),
Err(MetathesesDecodeError::UnexpectedLength { .. })
));
let mut hostile = Vec::from(&[0x01u8][..]);
hostile.extend_from_slice(&u64::MAX.to_be_bytes());
assert!(matches!(
Metatheses::from_bytes(&hostile),
Err(MetathesesDecodeError::UnexpectedLength { .. })
));
}
#[test]
fn test_metatheses_impossible_count_refuses_before_rows() {
let mut frame = canonical_record().to_bytes();
frame[1..9].copy_from_slice(&3u64.to_be_bytes());
frame[34] = 0x7f;
assert!(matches!(
Metatheses::from_bytes(&frame),
Err(MetathesesDecodeError::UnexpectedLength { .. })
));
}
#[test]
fn test_metatheses_trailing_bytes_refused() {
let mut frame = canonical_record().to_bytes();
let exact = frame.len();
frame.push(0x00);
assert_eq!(
Metatheses::from_bytes(&frame),
Err(MetathesesDecodeError::UnexpectedLength {
expected: exact,
found: exact + 1,
})
);
}
#[test]
fn test_metatheses_zero_testimony_dot_refused() {
let mut frame = canonical_record().to_bytes();
for byte in &mut frame[13..21] {
*byte = 0;
}
assert_eq!(
Metatheses::from_bytes(&frame),
Err(MetathesesDecodeError::ZeroDot { station: 1 })
);
}
#[test]
fn test_metatheses_non_ascending_refused() {
let mut record = Metatheses::new();
assert!(record.insert(d(1, 3), testimony((1, 1), Anchor::Origin, 7)));
assert!(record.insert(d(1, 4), testimony((1, 1), Anchor::Origin, 9)));
let frame = record.to_bytes();
let mut swapped = frame.clone();
swapped[9..51].copy_from_slice(&frame[51..93]);
swapped[51..93].copy_from_slice(&frame[9..51]);
assert_eq!(
Metatheses::from_bytes(&swapped),
Err(MetathesesDecodeError::NonAscendingTestimonies {
previous: (1, 4),
found: (1, 3),
})
);
let mut duplicated = frame;
duplicated[62] = 0x03;
assert_eq!(
Metatheses::from_bytes(&duplicated),
Err(MetathesesDecodeError::NonAscendingTestimonies {
previous: (1, 3),
found: (1, 3),
})
);
}
#[test]
fn test_metatheses_bad_anchor_tag_refused() {
let mut frame = canonical_record().to_bytes();
frame[33] = 0x03;
assert_eq!(
Metatheses::from_bytes(&frame),
Err(MetathesesDecodeError::BadAnchorTag { tag: 0x03 })
);
}
#[test]
fn test_metatheses_bad_rank_refused() {
let mut frame = canonical_record().to_bytes();
frame[34] = 0x7f;
assert!(matches!(
Metatheses::from_bytes(&frame),
Err(MetathesesDecodeError::Rank(_))
));
}
#[test]
fn test_metatheses_budget_refusal() {
let record = canonical_record();
let frame = record.to_bytes();
assert_eq!(
Metatheses::from_bytes_with_budget(&frame, MetathesesDecodeBudget::new(1)),
Err(MetathesesDecodeError::TooManyTestimonies {
count: 2,
budget: 1,
})
);
assert_eq!(
Metatheses::from_bytes_with_budget(&frame, MetathesesDecodeBudget::new(2)),
Ok(record)
);
}