open Ppx_sexp_conv_lib open Conv let%test_module "Exceptions" = (module struct let check_sexp exn string = match sexp_of_exn_opt exn with | None -> raise exn | Some sexp -> let sexp_as_string = Ppx_sexp_conv_lib.Sexp.to_string sexp in if sexp_as_string <> string then failwith sexp_as_string ;; (* first global exceptions, checking different arities since they don't have the same representation *) exception Arg0 [@@deriving sexp] exception Arg1 of int [@@deriving sexp] exception Arg2 of int * int [@@deriving sexp] let%test_unit _ = check_sexp Arg0 "conv_test.ml.Arg0" let%test_unit _ = check_sexp (Arg1 1) "(conv_test.ml.Arg1 1)" let%test_unit _ = check_sexp (Arg2 (2, 3)) "(conv_test.ml.Arg2 2 3)" (* now local exceptions *) let exn (type a) a sexp_of_a = let module M = struct exception E of a [@@deriving sexp] end in M.E a ;; let%test_unit "incompatible exceptions with the same name" = let e_int = exn 1 sexp_of_int in let e_string = exn "a" sexp_of_string in check_sexp e_int "(conv_test.ml.E 1)"; check_sexp e_string "(conv_test.ml.E a)" ;; let%test_unit "sexp converters are finalized properly for local exceptions" = Gc.compact (); Gc.compact (); let size_before = Ppx_sexp_conv_lib.Conv.Exn_converter.For_unit_tests_only.size () in let e = exn 2.5 sexp_of_float in let size_after_local_exn = Ppx_sexp_conv_lib.Conv.Exn_converter.For_unit_tests_only.size () in let e_finalized = ref false in Gc.finalise (fun _ -> e_finalized := true) e; check_sexp e "(conv_test.ml.E 2.5)"; Gc.compact (); Gc.compact (); assert !e_finalized; let size_after_gc = Ppx_sexp_conv_lib.Conv.Exn_converter.For_unit_tests_only.size () in assert (size_before + 1 = size_after_local_exn); assert (size_before = size_after_gc) ;; end) ;;