use platform_data::{LinkReference, LinksConstants};
#[test]
fn test_external_range_starts_after_continue_u32() {
let constants = LinksConstants::<u32>::external();
assert!(!constants.is_external(constants.r#continue));
assert!(!constants.is_reference(constants.r#continue));
assert_eq!(constants.r#continue, 2_147_483_647);
assert_eq!(constants.internal_range, 1..=2_147_483_641);
assert_eq!(constants.external_range, Some(2_147_483_648..=u32::MAX));
}
fn assert_external_boundaries<T: LinkReference>() {
let half = T::MAX / T::from_byte(2);
let first_external = half + T::from_byte(1);
for constants in [
LinksConstants::<T>::external(),
LinksConstants::via_only_external(true),
LinksConstants::via_external(T::from_byte(5), true),
] {
assert_eq!(constants.r#continue, half);
assert_eq!(
constants.internal_range,
T::from_byte(1)..=half - T::from_byte(6)
);
assert_eq!(constants.external_range, Some(first_external..=T::MAX));
assert!(!constants.is_reference(constants.null));
for service in [
constants.r#continue,
constants.r#break,
constants.skip,
constants.any,
constants.itself,
constants.error,
] {
assert!(!constants.is_internal(service));
assert!(!constants.is_external(service));
assert!(!constants.is_reference(service));
}
for internal in [
*constants.internal_range.start(),
*constants.internal_range.end(),
] {
assert!(constants.is_internal(internal));
assert!(!constants.is_external(internal));
assert!(constants.is_reference(internal));
}
for external in [first_external, T::MAX] {
assert!(!constants.is_internal(external));
assert!(constants.is_external(external));
assert!(constants.is_reference(external));
}
}
}
#[test]
fn test_external_boundaries_for_all_unsigned_address_types() {
assert_external_boundaries::<u8>();
assert_external_boundaries::<u16>();
assert_external_boundaries::<u32>();
assert_external_boundaries::<u64>();
assert_external_boundaries::<u128>();
assert_external_boundaries::<usize>();
}
#[test]
#[should_panic(
expected = "external range must not overlap the internal range or reserved service values"
)]
fn test_full_new_rejects_external_overlap_with_continue() {
LinksConstants::<u32>::full_new(2, 1..=100, Some(100..=200));
}
#[test]
fn test_via_ranges_rejects_overlapping_external_ranges() {
for external in [1..=10, 20..=30, 94..=99, 95..=100, 1..=200] {
assert!(
std::panic::catch_unwind(|| {
LinksConstants::<u32>::via_ranges(10..=100, Some(external.clone()))
})
.is_err(),
"accepted overlapping external range {external:?}"
);
}
}
#[test]
fn test_via_ranges_preserves_disjoint_and_empty_external_ranges() {
for external in [
None,
Some(1..=9),
Some(101..=200),
Some(std::ops::RangeInclusive::new(200, 101)),
] {
let constants = LinksConstants::<u32>::via_ranges(10..=100, external.clone());
assert_eq!(constants.internal_range, 10..=94);
assert_eq!(constants.r#continue, 100);
assert_eq!(constants.external_range, external);
for service in [95, 96, 97, 98, 99, 100] {
assert!(!constants.is_reference(service));
}
}
}
#[test]
fn test_new_creates_internal_constants() {
let constants: LinksConstants<u64> = LinksConstants::new();
assert!(constants.external_range.is_none());
assert!(constants.internal_range.start() <= constants.internal_range.end());
}
#[test]
fn test_default_creates_internal_constants() {
let constants: LinksConstants<u64> = LinksConstants::default();
assert!(constants.external_range.is_none());
}
#[test]
fn test_internal_creates_internal_only_constants() {
let constants: LinksConstants<u64> = LinksConstants::internal();
assert!(constants.external_range.is_none());
assert_eq!(*constants.internal_range.start(), 1);
}
#[test]
fn test_external_creates_constants_with_external_range() {
let constants: LinksConstants<u64> = LinksConstants::external();
assert!(constants.external_range.is_some());
let external_range = constants.external_range.as_ref().unwrap();
assert!(external_range.start() <= external_range.end());
}
#[test]
fn test_via_only_external_false() {
let constants: LinksConstants<u64> = LinksConstants::via_only_external(false);
assert!(constants.external_range.is_none());
}
#[test]
fn test_via_only_external_true() {
let constants: LinksConstants<u64> = LinksConstants::via_only_external(true);
assert!(constants.external_range.is_some());
}
#[test]
fn test_via_external_with_custom_target_part() {
let constants: LinksConstants<u64> = LinksConstants::via_external(5, true);
assert_eq!(constants.target_part, 5);
assert!(constants.external_range.is_some());
}
#[test]
fn test_via_ranges_with_custom_ranges() {
let internal = 1u64..=1000;
let external = Some(1001u64..=2000);
let constants: LinksConstants<u64> = LinksConstants::via_ranges(internal.clone(), external);
assert_eq!(*constants.internal_range.start(), *internal.start());
assert!(constants.external_range.is_some());
}
#[test]
fn test_via_ranges_without_external() {
let internal = 1u64..=1000;
let constants: LinksConstants<u64> = LinksConstants::via_ranges(internal, None);
assert!(constants.external_range.is_none());
}
#[test]
fn test_full_new_sets_all_fields() {
let constants: LinksConstants<u64> = LinksConstants::full_new(3, 1..=100, Some(101..=200));
assert_eq!(constants.index_part, 0);
assert_eq!(constants.source_part, 1);
assert_eq!(constants.target_part, 3);
assert_eq!(constants.null, 0);
assert_eq!(constants.r#continue, 100);
assert_eq!(constants.r#break, 99);
assert_eq!(constants.skip, 98);
assert_eq!(constants.any, 97);
assert_eq!(constants.itself, 96);
assert_eq!(constants.error, 95);
assert_eq!(*constants.internal_range.start(), 1);
assert_eq!(*constants.internal_range.end(), 94); assert!(constants.external_range.is_some());
}
#[test]
fn test_is_internal_for_address_in_internal_range() {
let constants: LinksConstants<u64> = LinksConstants::new();
assert!(constants.is_internal(1));
assert!(constants.is_internal(100));
}
#[test]
fn test_is_internal_for_address_outside_range() {
let constants: LinksConstants<u64> = LinksConstants::full_new(2, 10..=100, None);
assert!(!constants.is_internal(5)); }
#[test]
fn test_is_external_with_no_external_range() {
let constants: LinksConstants<u64> = LinksConstants::internal();
assert!(!constants.is_external(100));
}
#[test]
fn test_is_external_with_external_range() {
let constants: LinksConstants<u64> = LinksConstants::external();
let external_range = constants.external_range.as_ref().unwrap();
assert!(constants.is_external(*external_range.start()));
}
#[test]
fn test_is_reference_internal() {
let constants: LinksConstants<u64> = LinksConstants::new();
assert!(constants.is_reference(1));
}
#[test]
fn test_is_reference_external() {
let constants: LinksConstants<u64> = LinksConstants::external();
let external_range = constants.external_range.as_ref().unwrap();
assert!(constants.is_reference(*external_range.start()));
}
#[test]
fn test_is_reference_neither() {
let constants: LinksConstants<u64> = LinksConstants::full_new(2, 10..=100, None);
assert!(!constants.is_reference(5));
}
#[test]
fn test_constants_clone() {
let constants: LinksConstants<u64> = LinksConstants::external();
let cloned = constants.clone();
assert_eq!(constants, cloned);
}
#[test]
fn test_constants_debug() {
let constants: LinksConstants<u64> = LinksConstants::new();
let debug_str = format!("{constants:?}");
assert!(debug_str.contains("LinksConstants"));
}
#[test]
fn test_with_different_types() {
let constants_u8: LinksConstants<u8> = LinksConstants::new();
assert!(constants_u8.is_internal(1));
let constants_u16: LinksConstants<u16> = LinksConstants::new();
assert!(constants_u16.is_internal(1));
let constants_u32: LinksConstants<u32> = LinksConstants::new();
assert!(constants_u32.is_internal(1));
let constants_usize: LinksConstants<usize> = LinksConstants::new();
assert!(constants_usize.is_internal(1));
}
#[test]
fn test_via_external_false() {
let constants: LinksConstants<u64> = LinksConstants::via_external(7, false);
assert_eq!(constants.target_part, 7);
assert!(constants.external_range.is_none());
}
#[test]
fn test_default_internal_external_ranges() {
let constants: LinksConstants<u64> = LinksConstants::via_external(2, true);
assert!(constants.external_range.is_some());
assert!(*constants.internal_range.end() < u64::MAX);
}