aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-14 16:52:29 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-14 16:52:29 +0200
commit2c0187f42cc45864932aba2529f876be86ddba39 (patch)
tree4f13748309da87763c97a313fa3050c5f0fd63b3 /test
parentbca1a206589bc41bbcb367a7ae9b217c02f0e892 (diff)
downloadcolitur-2c0187f42cc45864932aba2529f876be86ddba39.tar.gz
colitur-2c0187f42cc45864932aba2529f876be86ddba39.zip
kernel(lectionary): fix round 1 -- load never raises
Sexplib.Sexp.load_sexp raises bare Failure for several malformed inputs (unterminated list/string, empty file, more than one sexp) rather than Sexplib.Sexp.Parse_error, so those cases escaped Lectionary.load as an uncaught exception -- breaking the .mli's own promise and the kernel's never-raises-on-fallible-construction constraint. Mirrors the catch-all already present in Layer.load and Overlay.load, plus a second catch-all on the t_of_sexp branch for defence in depth. Adds test_load_never_raises, covering all of the above plus a missing file, using Filename.temp_file rather than a hardcoded path. Verified the new test fails against the pre-fix load (uncaught Failure) and passes against the fix.
Diffstat (limited to 'test')
-rw-r--r--test/test_lectionary.ml27
1 files changed, 26 insertions, 1 deletions
diff --git a/test/test_lectionary.ml b/test/test_lectionary.ml
index 45a01ab..fba890a 100644
--- a/test/test_lectionary.ml
+++ b/test/test_lectionary.ml
@@ -53,8 +53,33 @@ let test_sexp_round_trip () =
let l' = Lectionary.t_of_sexp (Lectionary.sexp_of_t l) in
Alcotest.(check bool) "round trips" true (l = l')
+let with_temp_file contents f =
+ let path = Filename.temp_file "lectionary_test" ".sexp" in
+ let oc = open_out path in
+ output_string oc contents;
+ close_out oc;
+ Fun.protect ~finally:(fun () -> Sys.remove path) (fun () -> f path)
+
+let load_is_error contents what =
+ with_temp_file contents (fun path ->
+ match Lectionary.load path with
+ | Error _ -> ()
+ | Ok _ -> Alcotest.fail (what ^ ": expected Error, got Ok"))
+
+let test_load_never_raises () =
+ load_is_error "((ef-advent-sunday-1 (" "unterminated list";
+ load_is_error "((ef-advent-sunday-1 ((part First) (reference \"x" "unterminated string";
+ load_is_error "" "empty file";
+ load_is_error "() ()" "more than one sexp";
+ load_is_error "not-a-list" "wrong shape";
+ load_is_error "((\"NOT A SLUG\" ()))" "invalid slug";
+ match Lectionary.load "/nonexistent/path/lectionary.sexp" with
+ | Error _ -> ()
+ | Ok _ -> Alcotest.fail "missing file: expected Error, got Ok"
+
let suite =
[ ("find present", `Quick, test_find_present);
("find absent", `Quick, test_find_absent);
("duplicate slug rejected", `Quick, test_duplicate_slug_rejected);
- ("sexp round-trip", `Quick, test_sexp_round_trip) ]
+ ("sexp round-trip", `Quick, test_sexp_round_trip);
+ ("load never raises", `Quick, test_load_never_raises) ]