From 5cc4ff6c0c443e8dbfec9feec5a3d8a7d883c4e0 Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Mon, 8 Jun 2026 22:27:02 +0200 Subject: [PATCH] test(simulation): address PR #165 review (T-1031) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hoshe review findings — close silent-pass gaps in the §8 drainage tests: - assert_drainage_monotonicity now returns whether it actually checked (chunk had both wet and dry tiles); the three sweep tests (Alluvial/Meander/Braided Delta) assert at least one chunk exercised the law, so a regression that zeroes all channels fails loudly instead of passing vacuously. - The fjord-floor test scans the full 64x64 chunk instead of a single Y=32 row and asserts the deep-water trough exists, so the sea-level floor law can no longer be skipped by a probe that missed the trough. - Remove the unreferenced make_test_terrain_analysis helper (was behind #[allow(dead_code)] with a 'future use' comment — the maintenance trap the review flagged); make_dry_terrain_analysis covers the validation bodies. Co-Authored-By: Claude Opus 4.8 (1M context) --- server/tests/derivation_harness.rs | 122 ++++++++++++++++------------- 1 file changed, 68 insertions(+), 54 deletions(-) diff --git a/server/tests/derivation_harness.rs b/server/tests/derivation_harness.rs index 2d75597e6..46835c0b9 100644 --- a/server/tests/derivation_harness.rs +++ b/server/tests/derivation_harness.rs @@ -246,16 +246,22 @@ fn golden_seed_determinism_regression() { // level; BraidedDelta/CliffCoast/FjordWall floors at sea level." // Tested by deriving a full 64×64 chunk and checking min(wet_elev) ≤ max(dry_elev). +/// Returns `true` if the monotonicity assertion was actually exercised (the chunk +/// produced both wet and dry tiles). A `false` return means the chunk had no wet +/// tiles, so the law was trivially satisfied without checking anything — callers +/// sweep several chunks and assert at least one returned `true`, so a derivation +/// regression that silently zeroes all channels fails loudly instead of passing. +#[must_use] fn assert_drainage_monotonicity( seed: u64, body_id: &str, label: &str, region: &RegionProfile, chunk_pos: (i32, i32), -) { +) -> bool { let chunk = derive_chunk_context(seed, body_id, region, chunk_pos); if !chunk.has_active_channel { - return; // No channel → monotonicity trivially satisfied. + return false; // No channel → monotonicity trivially satisfied. } let mut max_dry_elev = i32::MIN; @@ -295,7 +301,9 @@ fn assert_drainage_monotonicity( chunk_pos.0, chunk_pos.1 ); + return true; } + false } #[test] @@ -311,9 +319,15 @@ fn law_drainage_monotonicity_alluvial_sweep() { Some(15.0), VegetationClass::Forest, ); + let mut checked = false; for (cx, cy) in [(0, 0), (1, 0), (0, 1), (4, 4), (8, 3)] { - assert_drainage_monotonicity(42, "GJ144d", "AlluvialPlain", ®ion, (cx, cy)); + checked |= assert_drainage_monotonicity(42, "GJ144d", "AlluvialPlain", ®ion, (cx, cy)); } + assert!( + checked, + "AlluvialPlain sweep exercised no wet tiles — the monotonicity law was never \ + actually checked; a derivation regression could silently pass this test." + ); } #[test] @@ -329,9 +343,15 @@ fn law_drainage_monotonicity_meander_sweep() { Some(14.0), VegetationClass::Forest, ); + let mut checked = false; for (cx, cy) in [(0, 0), (2, 1), (5, 5)] { - assert_drainage_monotonicity(99, "GJ447c", "MeanderReach", ®ion, (cx, cy)); + checked |= assert_drainage_monotonicity(99, "GJ447c", "MeanderReach", ®ion, (cx, cy)); } + assert!( + checked, + "MeanderReach sweep exercised no wet tiles — the monotonicity law was never \ + actually checked; a derivation regression could silently pass this test." + ); } #[test] @@ -353,30 +373,45 @@ fn law_drainage_monotonicity_fjord_floor_at_sea_level() { let mut deep_elevs: Vec = vec![]; let mut dry_elevs: Vec = vec![]; - for dx in 0..64i32 { - let col = derive_voxel_column(42, "fjord_body", ®ion, &chunk, dx, 32); - match col.water { - Water::Deep => deep_elevs.push(col.elevation_m), - Water::Dry => dry_elevs.push(col.elevation_m), - _ => {} + // Scan the full 64×64 chunk, not a single row — the deep-water trough axis is + // not guaranteed to intersect any fixed Y, so a single-row probe could miss it + // entirely and silently pass without ever checking the sea-level claim. + for dy in 0..64i32 { + for dx in 0..64i32 { + let col = derive_voxel_column(42, "fjord_body", ®ion, &chunk, dx, dy); + match col.water { + Water::Deep => deep_elevs.push(col.elevation_m), + Water::Dry => dry_elevs.push(col.elevation_m), + _ => {} + } } } - if !deep_elevs.is_empty() && !dry_elevs.is_empty() { - let max_deep = *deep_elevs.iter().max().unwrap(); - let min_dry = *dry_elevs.iter().min().unwrap(); - // Fjord floor (deep water) must be below wall elevation. - assert!( - max_deep <= min_dry, - "§8 FjordWall drainage: deep-water max elev {max_deep} m must be \ - ≤ dry wall min elev {min_dry} m" - ); - // Fjord floor must be near sea level (D-239 §8). - assert!( - max_deep <= 5, - "§8 FjordWall: deep-water floor elev {max_deep} m must be near sea level (≤5 m)" - ); - } + // A glaciated fjord chunk MUST carve a deep-water trough — if it doesn't, the + // derivation regressed and the sea-level law below would never run. Fail loudly. + assert!( + !deep_elevs.is_empty(), + "§8 FjordWall: no deep-water tiles found in the fjord chunk — the trough \ + derivation regressed; the sea-level floor law was never exercised." + ); + assert!( + !dry_elevs.is_empty(), + "§8 FjordWall: no dry wall tiles found in the fjord chunk." + ); + + let max_deep = *deep_elevs.iter().max().unwrap(); + let min_dry = *dry_elevs.iter().min().unwrap(); + // Fjord floor (deep water) must be below wall elevation. + assert!( + max_deep <= min_dry, + "§8 FjordWall drainage: deep-water max elev {max_deep} m must be \ + ≤ dry wall min elev {min_dry} m" + ); + // Fjord floor must be near sea level (D-239 §8). + assert!( + max_deep <= 5, + "§8 FjordWall: deep-water floor elev {max_deep} m must be near sea level (≤5 m)" + ); } #[test] @@ -392,9 +427,16 @@ fn law_drainage_monotonicity_braided_delta() { Some(18.0), VegetationClass::Scrub, ); + let mut checked = false; for (cx, cy) in [(0, 0), (1, 1)] { - assert_drainage_monotonicity(17, "delta_body", "BraidedDelta", ®ion, (cx, cy)); + checked |= + assert_drainage_monotonicity(17, "delta_body", "BraidedDelta", ®ion, (cx, cy)); } + assert!( + checked, + "BraidedDelta sweep exercised no wet tiles — the monotonicity law was never \ + actually checked; a derivation regression could silently pass this test." + ); } // ── §8 Law 2: Lithology → Landform ────────────────────────────────────────── @@ -1433,34 +1475,6 @@ fn make_region( } } -/// Build a minimal flat `TerrainAnalysis` for use in body-level derive calls. -/// Same geometry as the region_profile.rs unit tests (64×32 grid, sea_level=0.3). -/// -/// Retained as the gentle-slope counterpart to `make_dry_terrain_analysis` (which -/// the validation bodies currently use); kept for future morphology-gate tests that -/// need a sloped, partially-oceanic grid rather than the flat all-dry one. -#[allow(dead_code)] -fn make_test_terrain_analysis() -> TerrainAnalysis { - let (w, h) = (64u32, 32u32); - let n = (w * h) as usize; - let data: Vec = (0..n) - .map(|i| { - let r = (i / w as usize) as f32 / h as f32; - let c = (i % w as usize) as f32 / w as f32; - (r * 0.6 + c * 0.4).min(1.0) - }) - .collect(); - let hm = BodyHeightmap { - body_id: "test".into(), - width: w, - height: h, - data, - sea_level: 0.3, - }; - let dr = drainage::analyze(&hm.data, hm.width, hm.height, hm.sea_level); - TerrainAnalysis::analyze(&hm, &dr) -} - /// Build a flat all-dry `TerrainAnalysis` for validation body derivation. /// /// All cells have elevation = 0.5 with sea_level = 0.3 → ocean_fraction_q = 0 at