aboutsummaryrefslogtreecommitdiff
path: root/test/test_citation_coverage.ml
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_citation_coverage.ml')
-rw-r--r--test/test_citation_coverage.ml94
1 files changed, 70 insertions, 24 deletions
diff --git a/test/test_citation_coverage.ml b/test/test_citation_coverage.ml
index 31d49eb..a131d50 100644
--- a/test/test_citation_coverage.ml
+++ b/test/test_citation_coverage.ml
@@ -6,33 +6,78 @@
Same shape as test_lang_coverage.ml, which this file deliberately mirrors:
a miss there is a slug with no name, a miss here is a citation the parser
- cannot read. *)
+ cannot read.
+
+ The walk below also drives the round-trip check (Sigla facade, Task 5):
+ ONE pass over 1970-2070 collects into TWO tables, [bad_parse] and
+ [bad_round_trip], rather than walking the whole range twice for two
+ independent Alcotest cases -- measured, a second walk would cost ~1.5s of
+ a 5.65s fast suite for zero extra coverage. *)
module P = Colitur_citation.Parse
+let bad_parse : (string, string) Hashtbl.t = Hashtbl.create 64
+let bad_round_trip : (string, string) Hashtbl.t = Hashtbl.create 16
+let walked = ref false
+
+(* Parse -> render -> parse must reach the same structure.
+
+ NOTE the [names] function: [Book.default_spelling], NOT [Book.to_string].
+ [to_string] returns the internal id ("corinthians_1"), which is not a
+ registered token, so rendering with it produces something Parse cannot
+ read back -- 0 of 738 round-trip. Measured during Task 4; do not
+ "simplify" this back to to_string. A renderer that emits an unparseable
+ string, or a style whose own output it cannot read, fails here. Compares
+ STRUCTURE, not text: the rendered form legitimately differs from the
+ input (a normalised book spelling, a dropped trailing period), and
+ asserting text equality would just pin those differences. *)
+let sg =
+ Colitur_citation.Sigla.make ~style:Colitur_citation.Render.default_style
+ ~tradition:Colitur_citation.Book.vulgate
+ ~names:(fun id _form -> Colitur_citation.Book.default_spelling id)
+
+let walk () =
+ if not !walked then begin
+ walked := true;
+ let layer =
+ match Test_support.load_ef_layer () with
+ | Ok l -> l
+ | Error e -> Alcotest.failf "%s" e
+ in
+ let ctx = Test_support.ef_context () in
+ for y = 1970 to 2070 do
+ Array.iter
+ (fun (d : (Rite_ef.Vocab_ef.season, Rite_ef.Vocab_ef.rank) Colitur_kernel.Liturgical_day.t) ->
+ List.iter
+ (fun (c : Colitur_kernel.Citation.t) ->
+ let r = c.Colitur_kernel.Citation.reference in
+ match P.parse r with
+ | Error e -> if not (Hashtbl.mem bad_parse r) then Hashtbl.add bad_parse r e
+ | Ok first ->
+ let rendered = Colitur_citation.Sigla.format sg r in
+ (match P.parse rendered with
+ | Error e ->
+ Hashtbl.replace bad_round_trip r ("re-parse failed: " ^ e)
+ | Ok again ->
+ if again <> first then
+ Hashtbl.replace bad_round_trip r ("structure changed: " ^ rendered)))
+ d.Colitur_kernel.Liturgical_day.citations)
+ (Colitur_kernel.Calendar.year ctx layer y)
+ done
+ end
+
let test_every_citation_parses () =
- let layer =
- match Test_support.load_ef_layer () with
- | Ok l -> l
- | Error e -> Alcotest.failf "%s" e
- in
- let ctx = Test_support.ef_context () in
- let bad = Hashtbl.create 64 in
- for y = 1970 to 2070 do
- Array.iter
- (fun (d : (Rite_ef.Vocab_ef.season, Rite_ef.Vocab_ef.rank) Colitur_kernel.Liturgical_day.t) ->
- List.iter
- (fun (c : Colitur_kernel.Citation.t) ->
- let r = c.Colitur_kernel.Citation.reference in
- match P.parse r with
- | Ok _ -> ()
- | Error e -> if not (Hashtbl.mem bad r) then Hashtbl.add bad r e)
- d.Colitur_kernel.Liturgical_day.citations)
- (Colitur_kernel.Calendar.year ctx layer y)
- done;
- if Hashtbl.length bad > 0 then begin
- Hashtbl.iter (fun r e -> Printf.eprintf "UNPARSED %S: %s\n" r e) bad;
- Alcotest.failf "%d citation(s) did not parse" (Hashtbl.length bad)
+ walk ();
+ if Hashtbl.length bad_parse > 0 then begin
+ Hashtbl.iter (fun r e -> Printf.eprintf "UNPARSED %S: %s\n" r e) bad_parse;
+ Alcotest.failf "%d citation(s) did not parse" (Hashtbl.length bad_parse)
+ end
+
+let test_round_trip () =
+ walk ();
+ if Hashtbl.length bad_round_trip > 0 then begin
+ Hashtbl.iter (fun r e -> Printf.eprintf "ROUND-TRIP %S: %s\n" r e) bad_round_trip;
+ Alcotest.failf "%d citation(s) failed round-trip" (Hashtbl.length bad_round_trip)
end
(* This project has ONE test executable. Every test_<module>.ml exposes a
@@ -40,4 +85,5 @@ let test_every_citation_parses () =
Alcotest.run here. Marked `Slow like test_lang_coverage's own year walk. *)
let suite =
( "citation-coverage",
- [ Alcotest.test_case "every citation parses" `Slow test_every_citation_parses ] )
+ [ Alcotest.test_case "every citation parses" `Slow test_every_citation_parses;
+ Alcotest.test_case "sigla round-trip" `Slow test_round_trip ] )