aboutsummaryrefslogtreecommitdiff
path: root/test/test_validate_of.ml
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_validate_of.ml')
-rw-r--r--test/test_validate_of.ml111
1 files changed, 63 insertions, 48 deletions
diff --git a/test/test_validate_of.ml b/test/test_validate_of.ml
index 5c64710..bcf61cc 100644
--- a/test/test_validate_of.ml
+++ b/test/test_validate_of.ml
@@ -15,13 +15,20 @@
including their own three pinned defects -- see below).
THE KNOWN, PINNED-NOT-FIXED GAPS (Task 5's own report; do not relitigate
- here, only avoid papering over them). Originally three; now two -- see
- item 2's own CLOSED note:
- 1. Normae n. 35(a)'s Holy Family fallback is unreached whenever
- Christmas Day is itself a Sunday (test_rite_of.ml's own
- [is_known_holy_family_fallback_gap]/
- [test_holy_family_fallback_1583_known_wrong_ferial]) -- fires on
- roughly one year in seven, first hit at 1583.
+ here, only avoid papering over them). Originally three; now ONE -- items
+ 1 and 2 are both CLOSED (see each one's own CLOSED note):
+ 1. CLOSED, W2 fix (CLAUDE.md, temporal_of.ml). Used to read: "Normae
+ n. 35(a)'s Holy Family fallback is unreached whenever Christmas Day
+ is itself a Sunday (test_rite_of.ml's own
+ [is_known_holy_family_fallback_gap]/[test_holy_family_fallback_1583_
+ known_wrong_ferial]) -- fires on roughly one year in seven, first hit
+ at 1583." {!Rite_of.Temporal_of.temporal} now consults
+ {!Rite_of.Temporal_of.holy_family} directly, independent of weekday,
+ so this fires on ZERO years now, verified across the whole domain by
+ [test_exhaustive_domain_sweep]'s own [holy_family_gap_years] counter
+ below -- not merely assumed from the fix. [is_known_holy_family_
+ fallback_gap] itself is kept, as a dedicated "this must never recur"
+ check, not deleted -- the same discipline item 2 already established.
2. CLOSED, fix wave I8 (final-review.md, 2026-08-25-colitur-of-phases-
3-5). Used to read: "The lectionary (data/of/lectionary.sexp) was
audited against only one civil year (2026) -- surfaces here as
@@ -118,13 +125,20 @@ let contains ~substring s =
let rec go i = i + lx <= ls && (String.sub s i lx = substring || go (i + 1)) in
lx = 0 || go 0
+(* CLOSED, W2 fix (CLAUDE.md, temporal_of.ml): see this file's own header,
+ item 1. Kept as an explicit "this must never fire again" check, no
+ longer part of [is_known_gap]'s own filter below -- the same discipline
+ [is_known_nativity_gap] just above already established. *)
let is_known_holy_family_fallback_gap (f : Val.failure) =
f.Val.check = "anchor" && contains ~substring:"of-holy-family" f.Val.detail
-(* Fix wave I8: [is_known_nativity_gap] deliberately excluded -- see its own
- header just above. A recurrence now surfaces as an ordinary unexpected
- failure everywhere this predicate is used to filter. *)
-let is_known_gap f = is_known_holy_family_fallback_gap f
+(* Fix wave I8 + W2: both [is_known_nativity_gap] and
+ [is_known_holy_family_fallback_gap] are deliberately excluded now -- see
+ each one's own header just above. A recurrence of either now surfaces as
+ an ordinary unexpected failure everywhere this predicate is used to
+ filter. Kept as a named hook (not inlined to [false] at each call site)
+ so a future gap has an obvious place to land. *)
+let is_known_gap (_ : Val.failure) = false
let unexplained_failures year = List.filter (fun f -> not (is_known_gap f)) (run year)
@@ -152,13 +166,16 @@ let test_landmark_years () = List.iter check_year_allowing_known_gaps [ 1583; 20
Christmas-Day-is-Sunday shape can both still occur inside the truncated
walk) -- only "seasons" is additionally allowed here, and only here. *)
let test_year_9999_does_not_raise () =
+ (* [is_known_gap] now filters nothing (both gaps CLOSED) -- kept in the
+ pipeline anyway so a future gap has the same obvious place to land, but
+ [fs] here is really just [run 9999] unfiltered. *)
let fs = List.filter (fun f -> not (is_known_gap f)) (run 9999) in
Alcotest.(check bool) "no coverage failures (temporal stayed total through the clamp)" true
(not (List.exists (fun f -> f.Val.check = "coverage") fs));
Alcotest.(check bool) "seasons check flags the truncated final year as incomplete" true
(List.exists (fun f -> f.Val.check = "seasons") fs);
- Alcotest.(check (list string)) "nothing OTHER than the documented seasons truncation (and the three known \
- gaps, already filtered) fired"
+ Alcotest.(check (list string)) "nothing OTHER than the documented seasons truncation fired (both known \
+ gaps are CLOSED)"
[ "seasons" ]
(List.sort_uniq compare (List.map (fun f -> f.Val.check) fs))
@@ -166,18 +183,15 @@ let test_year_9999_does_not_raise () =
(* THE CONFIDENCE-TO-9999 CORE: random years across the whole domain, *)
(* mirroring test_validate.ml's own [prop_invariants] exactly, one rite *)
(* down -- 200 samples by default; every EXHAUSTIVE year under *)
-(* [COLITUR_EXHAUSTIVE_SWEEP=1] (below). Filtered of the three known gaps, *)
-(* same discipline [check_year_allowing_known_gaps] already applies to the *)
-(* landmark years -- a property that asserted [run y = []] UNFILTERED *)
-(* would not test anything new (it would just fail on ~1/7 of its own *)
-(* samples, the Holy Family gap's own real incidence), and one that *)
-(* filtered EVERYTHING unconditionally would risk hiding a genuinely NEW *)
-(* failure behind the same three names -- which is exactly why *)
-(* [is_known_gap] is the narrow, field-checked pair of predicates above, *)
-(* not a blanket "ignore anything on 25 December" rule. *)
+(* [COLITUR_EXHAUSTIVE_SWEEP=1] (below). Both known gaps are now CLOSED *)
+(* (this file's own header), so [is_known_gap] filters nothing any more -- *)
+(* [unexplained_failures y = []] below is really [run y = []] UNFILTERED, *)
+(* a strictly stronger assertion than this property used to make while *)
+(* either gap was still open. [is_known_gap] is kept in the pipeline (not *)
+(* inlined away) so a future gap has the same obvious, narrow, field- *)
+(* checked place to land that the two closed ones already used. *)
let prop_invariants =
- QCheck.Test.make ~count:200 ~name:"OF temporal invariants hold across 1583..9998 (modulo the three known, \
- pinned gaps)"
+ QCheck.Test.make ~count:200 ~name:"OF temporal invariants hold across 1583..9998 (no known gaps remain)"
(QCheck.int_range 1583 9998)
(fun y -> unexplained_failures y = [])
@@ -283,12 +297,13 @@ let test_exhaustive_domain_sweep () =
for y = 1583 to 9998 do
let fs = run y in
let hf = List.exists is_known_holy_family_fallback_gap fs in
- (* Fix wave I8: expected to be [false] every single year now -- kept
- as a live measurement, not deleted, so a regression anywhere in
- the domain increments this counter AND (via [is_known_gap] no
- longer absorbing it) fails the loop below immediately, on the
- first year it recurs, rather than only being caught by the
- summary assertion after the full sweep completes. *)
+ (* Fix wave I8 + W2: expected to be [false] every single year now for
+ BOTH counters -- kept as a live measurement, not deleted, so a
+ regression anywhere in the domain increments the relevant counter
+ AND (via [is_known_gap] no longer absorbing either shape) fails the
+ loop below immediately, on the first year it recurs, rather than
+ only being caught by the summary assertion after the full sweep
+ completes. *)
let nat = List.exists is_known_nativity_gap fs in
if hf then incr holy_family_gap_years;
if nat then incr nativity_gap_years;
@@ -309,24 +324,25 @@ let test_exhaustive_domain_sweep () =
(not (List.exists (fun f -> f.Val.check = "coverage") fs_9999));
Alcotest.(check bool) "9999: seasons check flags the truncated final year as incomplete" true
(List.exists (fun f -> f.Val.check = "seasons") fs_9999);
- Alcotest.(check (list string)) "9999: nothing OTHER than the documented seasons truncation (and the two \
- remaining known, pinned gaps) fired"
+ Alcotest.(check (list string)) "9999: nothing OTHER than the documented seasons truncation fired (both \
+ known gaps are CLOSED)"
[ "seasons" ]
(List.sort_uniq compare
(List.map (fun f -> f.Val.check) (List.filter (fun f -> not (is_known_gap f)) fs_9999)));
- (* The Holy Family gap is real and not vacuous across the FULL domain,
- not merely on the handful of years the sampled property happens to
- draw -- it fires on roughly one year in seven (whenever 25 December
- is a Sunday). Pinned as a range, not an exact count, deliberately:
- the exact figure is a real, computable fact about the Gregorian
- calendar's own 400-year cycle, but pinning it to the digit would
- make this test fail the moment a future COLITUR_EXHAUSTIVE_SWEEP
- run's own domain bounds shift by even one year at either edge, for a
- reason having nothing to do with colitur's own correctness. *)
- Alcotest.(check bool) "the Holy Family fallback gap fires on a real, non-trivial fraction of years \
- (roughly one in seven)"
- true
- (!holy_family_gap_years > 1000 && !holy_family_gap_years < 1400);
+ (* CLOSED, W2 fix: the Holy Family gap used to fire on roughly one year
+ in seven (whenever 25 December is a Sunday) -- real and not vacuous
+ across the FULL domain, not merely the handful of years the sampled
+ property happens to draw. {!Rite_of.Temporal_of.temporal} now
+ consults {!Rite_of.Temporal_of.holy_family} directly, independent of
+ weekday, so this now fires on ZERO years -- across the WHOLE domain,
+ not merely the 4 landmark years test_rite_of.ml's own
+ [test_landmark_years] already checks, which is the entire reason
+ this dedicated exhaustive counter is kept rather than deleted
+ alongside the rest of the old gap-tracking, mirroring the Nativity
+ counter's own already-established pattern just below. *)
+ Alcotest.(check int) "the Holy Family fallback gap fires on NONE of the 8 416 swept years (W2 fix -- was \
+ roughly one in seven, ~1200)"
+ 0 !holy_family_gap_years;
(* CLOSED, fix wave I8: the Nativity gap used to fire on literally every
one of the 8 416 swept years (25 December always exists). Now
exactly zero -- across the WHOLE domain, not merely the 4 landmark
@@ -340,10 +356,9 @@ let test_exhaustive_domain_sweep () =
let suite =
( "Validate (OF, real data: Rite_of.context)",
- [ Alcotest.test_case "landmark years validate cleanly (modulo the two remaining known gaps)" `Quick
+ [ Alcotest.test_case "landmark years validate cleanly (both known gaps are CLOSED)" `Quick
test_landmark_years;
- Alcotest.test_case "year 9999 does not raise; seasons flags the clamp, nothing else (beyond the known \
- gaps) fires" `Quick
+ Alcotest.test_case "year 9999 does not raise; seasons flags the clamp, nothing else fires" `Quick
test_year_9999_does_not_raise;
Alcotest.test_case "exhaustive domain sweep (1583..9999), committed not sampled" `Slow
test_exhaustive_domain_sweep ]