1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
open Base
type 'a test_pred =
?here:Lexing.position list -> ?message:string -> ('a -> bool) -> 'a -> unit
type 'a test_eq =
?here:Lexing.position list
-> ?message:string
-> ?equal:('a -> 'a -> bool)
-> 'a
-> 'a
-> unit
type 'a test_result =
?here:Lexing.position list
-> ?message:string
-> ?equal:('a -> 'a -> bool)
-> expect:'a
-> 'a
-> unit
exception E of string * Sexp.t [@@deriving sexp]
let exn_sexp_style ~message ~pos ~here ~tag body =
let message =
match message with
| None -> tag
| Some s -> s ^ ": " ^ tag
in
let sexp =
Sexp.List
(body
@ [ Sexp.List [ Sexp.Atom "Loc"; Sexp.Atom pos ] ]
@
match here with
| [] -> []
| _ ->
[ Sexp.List [ Sexp.Atom "Stack"; [%sexp_of: Source_code_position.t list] here ] ]
)
in
E (message, sexp)
;;
let[@cold] exn_test_pred ~message ~pos ~here ~sexpifier t =
exn_sexp_style
~message
~pos
~here
~tag:"predicate failed"
[ Sexp.List [ Sexp.Atom "Value"; sexpifier t ] ]
;;
let test_pred ~pos ~sexpifier ~here ?message predicate t =
if not (predicate t) then raise (exn_test_pred ~message ~pos ~here ~sexpifier t)
;;
let r_diff : (from_:string -> to_:string -> unit) option ref = ref None
let set_diff_function f = r_diff := f
let[@cold] test_result_or_eq_failed ~sexpifier ~expect ~got =
let got = sexpifier got in
let expect = sexpifier expect in
(match !r_diff with
| None -> ()
| Some diff ->
let from_ = Sexp.to_string_hum expect in
let to_ = Sexp.to_string_hum got in
diff ~from_ ~to_);
`Fail (expect, got)
;;
let test_result_or_eq ~sexpifier ~comparator ~equal ~expect ~got =
let pass =
match equal with
| None -> comparator got expect = 0
| Some f -> f got expect
in
if pass then `Pass else test_result_or_eq_failed ~sexpifier ~expect ~got
;;
let[@cold] exn_test_eq ~message ~pos ~here ~t1 ~t2 =
exn_sexp_style ~message ~pos ~here ~tag:"comparison failed" [ t1; Sexp.Atom "vs"; t2 ]
;;
let test_eq ~pos ~sexpifier ~comparator ~here ?message ?equal t1 t2 =
match test_result_or_eq ~sexpifier ~comparator ~equal ~expect:t1 ~got:t2 with
| `Pass -> ()
| `Fail (t1, t2) -> raise (exn_test_eq ~message ~pos ~here ~t1 ~t2)
;;
let[@cold] exn_test_result ~message ~pos ~here ~expect ~got =
exn_sexp_style
~message
~pos
~here
~tag:"got unexpected result"
[ Sexp.List [ Sexp.Atom "expected"; expect ]; Sexp.List [ Sexp.Atom "got"; got ] ]
;;
let[@warning "-16"] test_result
~pos
~sexpifier
~comparator
~here
?message
?equal
~expect
~got
=
match test_result_or_eq ~sexpifier ~comparator ~equal ~expect ~got with
| `Pass -> ()
| `Fail (expect, got) -> raise (exn_test_result ~message ~pos ~here ~expect ~got)
;;