use super::*;
use crate::metis::{Admission, Endorsement, EndorsementDecodeBudget, EndorsementDecodeError};
fn endorsement() -> Endorsement {
let admission = Admission::new(address(1, (2, 3)), [5, 9]).expect("two joiners are a boundary");
Endorsement::from_parts(admission, [0xA5; 32])
}
#[test]
fn test_endorsement_golden_layout() {
let record = endorsement();
let frame = record.to_bytes();
let mut expected = vec![0x01];
expected.extend_from_slice(&1u64.to_be_bytes()); expected.extend_from_slice(&2u32.to_be_bytes()); expected.extend_from_slice(&3u64.to_be_bytes()); expected.extend_from_slice(&2u32.to_be_bytes()); expected.extend_from_slice(&5u32.to_be_bytes());
expected.extend_from_slice(&9u32.to_be_bytes());
expected.extend_from_slice(&[0xA5; 32]);
assert_eq!(frame, expected);
assert_eq!(record.encoded_len(), frame.len());
let decoded = Endorsement::from_bytes(&frame).expect("the golden frame decodes");
assert_eq!(decoded, record);
assert_eq!(decoded.to_bytes(), frame);
}
#[test]
fn test_endorsement_unknown_version_refuses() {
let mut frame = endorsement().to_bytes();
frame[0] = 0x7F;
assert_eq!(
Endorsement::from_bytes(&frame),
Err(EndorsementDecodeError::UnknownVersion(0x7F))
);
}
#[test]
fn test_endorsement_trailing_bytes_refuse() {
let mut frame = endorsement().to_bytes();
let exact = frame.len();
frame.push(0);
assert_eq!(
Endorsement::from_bytes(&frame),
Err(EndorsementDecodeError::UnexpectedLength {
expected: exact,
found: exact + 1
})
);
}
#[test]
fn test_endorsement_zero_base_parts_refuse() {
let frame = endorsement().to_bytes();
let mut zeroed = frame.clone();
for byte in &mut zeroed[1..9] {
*byte = 0;
}
assert_eq!(
Endorsement::from_bytes(&zeroed),
Err(EndorsementDecodeError::Address(
InvalidEpochAddress::ZeroGeneration
))
);
let mut zeroed = frame;
for byte in &mut zeroed[13..21] {
*byte = 0;
}
assert_eq!(
Endorsement::from_bytes(&zeroed),
Err(EndorsementDecodeError::Address(
InvalidEpochAddress::ZeroDeclarationCounter { station: 2 }
))
);
}
#[test]
fn test_endorsement_empty_admission_refuses() {
let populated = endorsement().to_bytes();
let mut frame = populated[..25].to_vec();
frame[21..25].copy_from_slice(&0u32.to_be_bytes());
frame.extend_from_slice(&populated[33..]);
assert_eq!(frame.len(), 57);
assert_eq!(
Endorsement::from_bytes(&frame),
Err(EndorsementDecodeError::EmptyAdmission)
);
}
#[test]
fn test_endorsement_non_ascending_joiners_refuse() {
let frame = endorsement().to_bytes();
let mut swapped = frame.clone();
swapped[25..29].copy_from_slice(&9u32.to_be_bytes());
swapped[29..33].copy_from_slice(&5u32.to_be_bytes());
assert_eq!(
Endorsement::from_bytes(&swapped),
Err(EndorsementDecodeError::NonAscendingJoiners {
previous: 9,
found: 5
})
);
let mut doubled = frame;
doubled[29..33].copy_from_slice(&5u32.to_be_bytes());
assert_eq!(
Endorsement::from_bytes(&doubled),
Err(EndorsementDecodeError::NonAscendingJoiners {
previous: 5,
found: 5
})
);
}
#[test]
fn test_endorsement_budget_refusals() {
let record = endorsement();
let frame = record.to_bytes();
assert_eq!(
Endorsement::from_bytes_with_budget(&frame, EndorsementDecodeBudget::new(2)),
Ok(record.clone())
);
assert_eq!(
Endorsement::from_bytes_with_budget(&frame, EndorsementDecodeBudget::default_ceiling()),
Ok(record)
);
assert_eq!(
Endorsement::from_bytes_with_budget(&frame, EndorsementDecodeBudget::new(1)),
Err(EndorsementDecodeError::TooManyJoiners {
count: 2,
budget: 1
})
);
}
#[test]
fn test_endorsement_impossible_count_refuses_in_o1() {
let mut frame = endorsement().to_bytes();
frame[21..25].copy_from_slice(&u32::MAX.to_be_bytes());
let floor = u64::from(u32::MAX) * 4 + 32;
let expected = usize::try_from(25u64.saturating_add(floor)).unwrap_or(usize::MAX);
assert_eq!(
Endorsement::from_bytes(&frame),
Err(EndorsementDecodeError::UnexpectedLength {
expected,
found: frame.len()
})
);
let mut short = endorsement().to_bytes();
let _ = short.pop();
assert_eq!(
Endorsement::from_bytes(&short),
Err(EndorsementDecodeError::UnexpectedLength {
expected: 25 + 2 * 4 + 32,
found: short.len()
})
);
}
#[test]
fn test_endorsement_short_input_refuses() {
let frame = endorsement().to_bytes();
assert_eq!(
Endorsement::from_bytes(&frame[..40]),
Err(EndorsementDecodeError::UnexpectedLength {
expected: 57,
found: 40
})
);
}
#[test]
fn test_endorsement_station_zero_is_the_consumers_law() {
let admission = Admission::new(address(1, (0, 3)), [0, 7]).expect("a boundary");
let record = Endorsement::from_parts(admission, [0x11; 32]);
let frame = record.to_bytes();
let decoded = Endorsement::from_bytes(&frame).expect("station zero decodes");
assert_eq!(decoded, record);
assert_eq!(decoded.to_bytes(), frame);
}