diff options
| -rw-r--r-- | test/test_precedence.ml | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/test/test_precedence.ml b/test/test_precedence.ml index 39be06c..369c490 100644 --- a/test/test_precedence.ml +++ b/test/test_precedence.ml @@ -56,15 +56,45 @@ let test_commemoration_only_never_observed () = Alcotest.(check (list string)) "suppressed commemorated" [ "suppressed" ] (List.map (fun (c, _) -> slug_of c) r.P.commemorations) -(* Anything the admit limit drops is recorded in `omitted`, never dropped silently. *) +(* Anything the admit limit drops is recorded in `omitted`, never dropped silently + -- and each input candidate lands in exactly one bucket, not zero or two. *) let test_nothing_silently_lost () = let r = P.resolve rules ctx ~temporal:(cand ~origin:P.Temporal ~rank:Hi "sunday") ~sanctoral:[ cand ~rank:Lo "a"; cand ~rank:Lo "b"; cand ~rank:Lo "c" ] in - Alcotest.(check int) "two admitted" 2 (List.length r.P.commemorations); - Alcotest.(check int) "one recorded as omitted" 1 (List.length r.P.omitted); - let total = 1 + List.length r.P.commemorations + List.length r.P.deferred - + List.length r.P.omitted in - Alcotest.(check int) "every candidate accounted for" 4 total + let bucketed = + (slug_of r.P.observed + :: List.map (fun (c, _) -> slug_of c) r.P.commemorations) + @ List.map slug_of r.P.deferred + @ List.map (fun (c, _) -> slug_of c) r.P.omitted + in + Alcotest.(check (slist string compare)) "every candidate appears exactly once" + [ "a"; "b"; "c"; "sunday" ] bucketed; + Alcotest.(check int) "two admitted" 2 (List.length r.P.commemorations) + +(* The result must not depend on the order sanctoral candidates arrive in; + ties break on slug, not on list position. *) +let test_order_independent () = + let a = cand ~rank:Lo "a" and b = cand ~rank:Lo "b" and c = cand ~rank:Lo "c" in + let t = cand ~origin:P.Temporal ~rank:Hi "sunday" in + let observed_for sanctoral = slug_of (P.resolve rules ctx ~temporal:t ~sanctoral).P.observed in + let comms_for sanctoral = + List.map (fun (x, _) -> slug_of x) (P.resolve rules ctx ~temporal:t ~sanctoral).P.commemorations + in + List.iter + (fun perm -> + Alcotest.(check string) "same observed" (observed_for [ a; b; c ]) (observed_for perm); + Alcotest.(check (list string)) "same commemorations" (comms_for [ a; b; c ]) (comms_for perm)) + [ [ c; b; a ]; [ b; a; c ]; [ c; a; b ] ] + +(* The case the "pass temporal separately" design exists to make safe: a day + with no sanctoral candidate at all. *) +let test_temporal_only_day () = + let r = P.resolve rules ctx ~temporal:(cand ~origin:P.Temporal ~rank:Lo "feria") + ~sanctoral:[] in + Alcotest.(check string) "feria observed" "feria" (slug_of r.P.observed); + Alcotest.(check int) "no commemorations" 0 (List.length r.P.commemorations); + Alcotest.(check int) "nothing deferred" 0 (List.length r.P.deferred); + Alcotest.(check int) "nothing omitted" 0 (List.length r.P.omitted) let suite = ( "Precedence", @@ -73,4 +103,6 @@ let suite = Alcotest.test_case "loser dispositions" `Quick test_loser_dispositions; Alcotest.test_case "commemoration-only never observed" `Quick test_commemoration_only_never_observed; - Alcotest.test_case "nothing silently lost" `Quick test_nothing_silently_lost ] ) + Alcotest.test_case "nothing silently lost" `Quick test_nothing_silently_lost; + Alcotest.test_case "order independent" `Quick test_order_independent; + Alcotest.test_case "temporal-only day" `Quick test_temporal_only_day ] ) |
