use proptest::prelude::*;
use wm_core::{Galaxy, Gana, HolographicCoords};
#[test]
fn gana_has_exactly_28_variants() {
assert_eq!(Gana::COUNT, 28);
assert_eq!(Gana::all().len(), 28);
}
#[test]
fn gana_indices_are_contiguous_and_unique() {
let mut seen = std::collections::HashSet::new();
for (i, gana) in Gana::all().iter().enumerate() {
let idx = *gana as u8;
assert_eq!(
idx as usize, i,
"Gana {gana:?} has index {idx} but position {i}"
);
assert!(
seen.insert(idx),
"Duplicate u8 index {idx} for Gana {gana:?}"
);
}
}
#[test]
fn gana_from_index_roundtrips_all_variants() {
for i in 0..28u8 {
let gana = Gana::from_index(i).unwrap_or_else(|| panic!("index {i} should map to a Gana"));
assert_eq!(gana as u8, i);
}
assert!(
Gana::from_index(28).is_none(),
"index 28 should be out of bounds"
);
assert!(Gana::from_index(255).is_none());
}
#[test]
fn gana_serialization_roundtrip_preserves_identity() {
for gana in Gana::all() {
let json = serde_json::to_string(&gana).unwrap();
let back: Gana = serde_json::from_str(&json).unwrap();
assert_eq!(gana, back, "Serialization roundtrip failed for {gana:?}");
}
}
#[test]
fn gana_display_and_debug_are_non_empty() {
for gana in Gana::all() {
let display = format!("{gana}");
let debug = format!("{gana:?}");
assert!(!display.is_empty());
assert!(!debug.is_empty());
}
}
#[test]
fn gana_descriptions_are_non_empty_and_unique() {
let mut descs: Vec<_> = Gana::all().iter().map(|g| g.description()).collect();
let total = descs.len();
descs.sort_unstable();
descs.dedup();
for gana in Gana::all() {
assert!(
!gana.description().is_empty(),
"Empty description for {gana:?}"
);
}
assert!(
descs.len() >= 25,
"Only {} unique descriptions, expected >= 25",
descs.len()
);
let _ = total;
}
proptest! {
#[test]
fn gana_index_bijection(idx in 0u8..28) {
let gana = Gana::from_index(idx).unwrap();
prop_assert_eq!(gana as u8, idx);
}
#[test]
fn gana_serde_roundtrip(idx in 0u8..28) {
let gana = Gana::from_index(idx).unwrap();
let json = serde_json::to_string(&gana).unwrap();
let back: Gana = serde_json::from_str(&json).unwrap();
prop_assert_eq!(gana, back);
}
}
#[test]
fn galaxy_has_exactly_17_variants() {
assert_eq!(Galaxy::COUNT, 17);
assert_eq!(Galaxy::all().len(), 17);
}
#[test]
fn galaxy_db_names_are_all_unique() {
let names: Vec<_> = Galaxy::all().iter().map(|g| g.db_name()).collect();
let unique: std::collections::HashSet<_> = names.iter().collect();
assert_eq!(names.len(), unique.len(), "Galaxy db_names must be unique");
}
#[test]
fn galaxy_db_names_are_non_empty_lowercase_ascii() {
for galaxy in Galaxy::all() {
let name = galaxy.db_name();
assert!(!name.is_empty(), "Empty db_name for {galaxy:?}");
assert!(
name.chars()
.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit()),
"Non-lowercase-ascii db_name: {name} for {galaxy:?}"
);
}
}
#[test]
fn galaxy_display_matches_db_name() {
for galaxy in Galaxy::all() {
assert_eq!(format!("{galaxy}"), galaxy.db_name());
}
}
#[test]
fn coords_encode_decode_roundtrip_preserves_all_fields() {
let coords = HolographicCoords {
galaxy: 7,
sector: 1337,
radial: 0.123,
angular: std::f32::consts::PI,
temporal: 1_700_000_000_000_000,
consciousness: 0.777,
};
let key = coords.encode_key();
let decoded = HolographicCoords::decode_key(&key).unwrap();
assert_eq!(decoded.galaxy, coords.galaxy);
assert_eq!(decoded.sector, coords.sector);
assert_eq!(decoded.temporal, coords.temporal);
assert!((decoded.radial - coords.radial).abs() < f32::EPSILON);
assert!((decoded.angular - coords.angular).abs() < f32::EPSILON);
assert!((decoded.consciousness - coords.consciousness).abs() < f32::EPSILON);
}
#[test]
fn coords_encode_produces_23_byte_key() {
let coords = HolographicCoords {
galaxy: 0,
sector: 0,
radial: 0.0,
angular: 0.0,
temporal: 0,
consciousness: 0.0,
};
assert_eq!(coords.encode_key().len(), 23);
}
#[test]
fn coords_decode_rejects_short_keys() {
assert!(HolographicCoords::decode_key(&[0; 22]).is_none());
assert!(HolographicCoords::decode_key(&[]).is_none());
}
#[test]
fn coords_distance_to_self_is_zero() {
let coords = HolographicCoords {
galaxy: 3,
sector: 42,
radial: 0.75,
angular: 1.5,
temporal: 1700000000,
consciousness: 0.8,
};
assert_eq!(coords.distance_to(&coords), 0.0);
}
#[test]
fn coords_distance_is_symmetric() {
let a = HolographicCoords {
galaxy: 0,
sector: 10,
radial: 0.3,
angular: 0.5,
temporal: 1000,
consciousness: 0.4,
};
let b = HolographicCoords {
galaxy: 1,
sector: 20,
radial: 0.9,
angular: 2.0,
temporal: 5000,
consciousness: 0.9,
};
assert!((a.distance_to(&b) - b.distance_to(&a)).abs() < f32::EPSILON);
}
#[test]
fn coords_distance_bounded_in_zero_to_one() {
let a = HolographicCoords {
galaxy: 0,
sector: 0,
radial: 0.0,
angular: 0.0,
temporal: 0,
consciousness: 0.0,
};
let b = HolographicCoords {
galaxy: 0,
sector: 0,
radial: 1.0,
angular: std::f32::consts::TAU,
temporal: u64::MAX,
consciousness: 1.0,
};
let d = a.distance_to(&b);
assert!((0.0..=1.0).contains(&d), "Distance {d} should be in [0, 1]");
}
#[test]
fn coords_new_uses_given_galaxy_index() {
let coords = HolographicCoords::new(Galaxy::Citta, 1000);
assert_eq!(coords.galaxy, Galaxy::Citta as u8);
}
proptest! {
#[test]
fn coords_roundtrip(
galaxy in 0u8..15,
sector in 0u16..,
radial in 0.0f32..1.0,
angular in 0.0f32..std::f32::consts::TAU,
temporal in 0u64..u64::MAX / 2,
consciousness in 0.0f32..1.0,
) {
let coords = HolographicCoords {
galaxy, sector, radial, angular, temporal, consciousness,
};
let key = coords.encode_key();
let decoded = HolographicCoords::decode_key(&key).unwrap();
prop_assert_eq!(decoded.galaxy, galaxy);
prop_assert_eq!(decoded.sector, sector);
prop_assert_eq!(decoded.temporal, temporal);
prop_assert!((decoded.radial - radial).abs() < f32::EPSILON);
prop_assert!((decoded.angular - angular).abs() < f32::EPSILON);
prop_assert!((decoded.consciousness - consciousness).abs() < f32::EPSILON);
}
#[test]
fn coords_distance_self_zero(
galaxy in 0u8..15,
sector in 0u16..,
radial in 0.0f32..1.0,
angular in 0.0f32..std::f32::consts::TAU,
temporal in 0u64..,
consciousness in 0.0f32..1.0,
) {
let coords = HolographicCoords {
galaxy, sector, radial, angular, temporal, consciousness,
};
prop_assert_eq!(coords.distance_to(&coords), 0.0);
}
#[test]
fn coords_distance_symmetric(
a_galaxy in 0u8..15, b_galaxy in 0u8..15,
a_sector in 0u16.., b_sector in 0u16..,
a_radial in 0.0f32..1.0, b_radial in 0.0f32..1.0,
a_angular in 0.0f32..std::f32::consts::TAU, b_angular in 0.0f32..std::f32::consts::TAU,
a_temporal in 0u64..u64::MAX/2, b_temporal in 0u64..u64::MAX/2,
a_consc in 0.0f32..1.0, b_consc in 0.0f32..1.0,
) {
let a = HolographicCoords {
galaxy: a_galaxy, sector: a_sector, radial: a_radial,
angular: a_angular, temporal: a_temporal, consciousness: a_consc,
};
let b = HolographicCoords {
galaxy: b_galaxy, sector: b_sector, radial: b_radial,
angular: b_angular, temporal: b_temporal, consciousness: b_consc,
};
let d_ab = a.distance_to(&b);
let d_ba = b.distance_to(&a);
prop_assert!((d_ab - d_ba).abs() < 0.001);
}
}