diff --git a/src/lib.rs b/src/lib.rs index 60cd2d7..36100ee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,7 +84,38 @@ mod smoke { #[test] fn levels_generate_canonical_yaml() { let registry = levels::registry(); - assert_eq!(registry.len(), 3); + assert_eq!(registry.len(), 11, "all 11 levels must be registered"); + + // Invariants every level must satisfy, regardless of how it generates. + for (i, level) in registry.iter().enumerate() { + let want_id = i as u8 + 1; + assert_eq!( + level.id(), + want_id, + "level at registry index {i} must report id {want_id}" + ); + + let seed = 0x5EED_0000 + i as u64; + let g = level.generate(seed); + + // The target must be valid YAML. + serde_yaml::from_str::(&g.target_yaml) + .unwrap_or_else(|e| panic!("level {want_id} target is not valid YAML: {e}")); + + // Generation is deterministic for a given seed. + let again = level.generate(seed); + assert_eq!( + g.target_yaml, again.target_yaml, + "level {want_id} must be deterministic for a given seed" + ); + + // The canonical target must be a perfect match against itself. + assert_eq!( + similarity::semantic_or_textual(&g.target_yaml, &g.target_yaml), + 1.0, + "level {want_id} target must score 1.0 against itself" + ); + } // Level 1: any null-equivalent passes via the semantic short-circuit. let g1 = registry[0].generate(0); @@ -95,24 +126,17 @@ mod smoke { 1.0, "`---` should be accepted as the minimum YAML" ); - assert_eq!( - similarity::semantic_or_textual(&g1.target_yaml, "null"), - 1.0 - ); + assert_eq!(similarity::semantic_or_textual(&g1.target_yaml, "null"), 1.0); - // Level 2: deterministic per seed, non-empty mapping. + // Level 2: non-empty mapping. let g2 = registry[1].generate(42); let v2: serde_yaml::Value = serde_yaml::from_str(&g2.target_yaml).unwrap(); - let m = v2.as_mapping().expect("level 2 produces a mapping"); - assert!(!m.is_empty()); - let g2_again = registry[1].generate(42); - assert_eq!( - g2.target_yaml, g2_again.target_yaml, - "same seed should produce the same target" - ); + assert!(!v2 + .as_mapping() + .expect("level 2 produces a mapping") + .is_empty()); - // Level 3: deterministic per seed; produces a mapping of mappings, - // each inner mapping has a `type` key. + // Level 3: a mapping of mappings; each inner mapping has a `type` key. let g3 = registry[2].generate(123); let v3: serde_yaml::Value = serde_yaml::from_str(&g3.target_yaml).unwrap(); let m3 = v3.as_mapping().expect("level 3 produces a mapping"); @@ -124,7 +148,5 @@ mod smoke { "each direction must carry a `type` key" ); } - let g3_again = registry[2].generate(123); - assert_eq!(g3.target_yaml, g3_again.target_yaml); } }