diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/test_colitur.ml | 3 | ||||
| -rw-r--r-- | test/test_emit.ml | 77 |
2 files changed, 79 insertions, 1 deletions
diff --git a/test/test_colitur.ml b/test/test_colitur.ml index dadc77d..b61eed6 100644 --- a/test/test_colitur.ml +++ b/test/test_colitur.ml @@ -10,4 +10,5 @@ let () = Test_escape.suite; Test_template.suite; Test_template.render_suite; - Test_view.suite ] + Test_view.suite; + Test_emit.suite ] diff --git a/test/test_emit.ml b/test/test_emit.ml new file mode 100644 index 0000000..a8fd45c --- /dev/null +++ b/test/test_emit.ml @@ -0,0 +1,77 @@ +module V = Colitur_render.View +module Csv = Colitur_render.Emit_csv +module Json = Colitur_render.Emit_json + +let view_2027 () = Test_view.view_of 2027 + +let test_csv_header_and_rows () = + let out = Csv.year (view_2027 ()) in + let lines = String.split_on_char '\n' out |> List.filter (fun l -> l <> "") in + Alcotest.(check int) "366 lines: header + 365 days" 366 (List.length lines); + Alcotest.(check string) "header" + "date,rite,season,week,slug,rank,colour,subject,name_la,name_en,first,gospel,comms" + (List.hd lines); + Alcotest.(check bool) "first row is 1 January" true + (String.length (List.nth lines 1) > 10 && String.sub (List.nth lines 1) 0 10 = "2027-01-01") + +(* RFC 4180: a field containing a comma, quote or newline is quoted, and an + embedded quote is doubled. Feast names contain commas ("St. Joseph, Spouse + of the Bl. Virgin Mary"), so this is live on real data, not hypothetical. *) +let test_csv_quotes_commas () = + Alcotest.(check string) "comma quoted" "\"a,b\"" (Csv.escape_field "a,b"); + Alcotest.(check string) "quote doubled" "\"a\"\"b\"" (Csv.escape_field "a\"b"); + Alcotest.(check string) "plain unquoted" "ab" (Csv.escape_field "ab"); + let out = Csv.year (view_2027 ()) in + let joseph = + List.find + (fun l -> String.length l > 10 && String.sub l 0 10 = "2027-03-19") + (String.split_on_char '\n' out) + in + Alcotest.(check bool) "the comma in Joseph's name is quoted, not a field break" true + (String.length (String.split_on_char ',' joseph |> List.hd) = 10) + +let test_json_parses_back () = + let out = Json.year (view_2027 ()) in + Alcotest.(check bool) "starts as an object" true (out.[0] = '{'); + let count sub = + let n = String.length sub in + let rec go i acc = + if i + n > String.length out then acc + else go (i + 1) (if String.sub out i n = sub then acc + 1 else acc) + in + go 0 0 + in + Alcotest.(check bool) "has a days array" true (count "\"days\":[" >= 1); + (* Every ISO date the view produced appears in the JSON -- that is the + property under test, not a specific occurrence count. The count is NOT + 1: the view deliberately offers both artefacts at every level (view.mli) + -- the flat top-level [days], each month's own [days], and that month's + [weeks] grid cell -- so an ordinary date's "iso" field appears 3 times. + Verified against the real 2027 engine output (all 365 dates checked); + the one exception is legitimate, not a bug: 2027-04-05 appears 6 times + because the Annunciation (25 March, impeded by Holy Week) transfers to + it under RG 96/98, and its own "to" target string is the identical + literal, tripled by the same structural redundancy. *) + Alcotest.(check int) "1 January appears (flat days + month days + week grid)" 3 + (count "\"2027-01-01\""); + Alcotest.(check int) "31 December appears (flat days + month days + week grid)" 3 + (count "\"2027-12-31\"") + +let test_json_escapes () = + Alcotest.(check string) "quote" "\"a\\\"b\"" (Json.escape_string "a\"b"); + Alcotest.(check string) "backslash" "\"a\\\\b\"" (Json.escape_string "a\\b"); + Alcotest.(check string) "newline" "\"a\\nb\"" (Json.escape_string "a\nb"); + Alcotest.(check string) "tab" "\"a\\tb\"" (Json.escape_string "a\tb"); + (* Control characters below 0x20 must be \u-escaped (RFC 8259 section 7). *) + Alcotest.(check string) "control" "\"a\\u0001b\"" (Json.escape_string "a\001b") + +let test_utf8_passes_through_json () = + Alcotest.(check string) "polish" "\"\xc5\x9awi\xc4\x99tej\"" (Json.escape_string "\xc5\x9awi\xc4\x99tej") + +let suite = + ( "Emit/csv+json", + [ Alcotest.test_case "csv header and rows" `Quick test_csv_header_and_rows; + Alcotest.test_case "csv quotes commas" `Quick test_csv_quotes_commas; + Alcotest.test_case "json parses back" `Quick test_json_parses_back; + Alcotest.test_case "json escapes" `Quick test_json_escapes; + Alcotest.test_case "json passes utf8 through" `Quick test_utf8_passes_through_json ] ) |
