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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
module Core = Core
module Cli = Cli
module Monad = Monad
module T = Cli.Make (Monad.Identity)
include T
module type TESTABLE = sig
type t
val pp : t Fmt.t
val equal : t -> t -> bool
end
type 'a testable = (module TESTABLE with type t = 'a)
let pp (type a) (t : a testable) =
let (module T) = t in
T.pp
let equal (type a) (t : a testable) =
let (module T) = t in
T.equal
let isnan f = FP_nan = classify_float f
let testable (type a) (pp : a Fmt.t) (equal : a -> a -> bool) : a testable =
let module M = struct
type t = a
let pp = pp
let equal = equal
end in
(module M)
let int32 = testable Fmt.int32 ( = )
let int64 = testable Fmt.int64 ( = )
let int = testable Fmt.int ( = )
let float eps =
let same x y =
(isnan x && isnan y)
|| x = y
|| abs_float (x -. y) <= eps
in
testable Fmt.float same
let char = testable Fmt.char ( = )
let string = testable Fmt.string ( = )
let bool = testable Fmt.bool ( = )
let unit = testable (Fmt.unit "()") ( = )
let list e =
let rec eq l1 l2 =
match (l1, l2) with
| x :: xs, y :: ys -> equal e x y && eq xs ys
| [], [] -> true
| _ -> false
in
testable (Fmt.Dump.list (pp e)) eq
let slist (type a) (a : a testable) compare =
let l = list a in
let eq l1 l2 = equal l (List.sort compare l1) (List.sort compare l2) in
testable (pp l) eq
let array e =
let eq a1 a2 =
let m, n = Array.(length a1, length a2) in
let rec go i = i = m || (equal e a1.(i) a2.(i) && go (i + 1)) in
m = n && go 0
in
testable (Fmt.Dump.array (pp e)) eq
let pair a b =
let eq (a1, b1) (a2, b2) = equal a a1 a2 && equal b b1 b2 in
testable (Fmt.Dump.pair (pp a) (pp b)) eq
let option e =
let eq x y =
match (x, y) with
| Some a, Some b -> equal e a b
| None, None -> true
| _ -> false
in
testable (Fmt.Dump.option (pp e)) eq
let result a e =
let eq x y =
match (x, y) with
| Ok x, Ok y -> equal a x y
| Error x, Error y -> equal e x y
| _ -> false
in
testable (Fmt.Dump.result ~ok:(pp a) ~error:(pp e)) eq
let of_pp pp = testable pp ( = )
let pass (type a) =
let module M = struct
type t = a
let pp fmt _ = Fmt.string fmt "Alcotest.pass"
let equal _ _ = true
end in
(module M : TESTABLE with type t = M.t)
let reject (type a) =
let module M = struct
type t = a
let pp fmt _ = Fmt.string fmt "Alcotest.reject"
let equal _ _ = false
end in
(module M : TESTABLE with type t = M.t)
let show_assert msg =
Format.eprintf "%a %s\n" Fmt.(styled `Yellow string) "ASSERT" msg
let check_err fmt =
Format.ksprintf (fun err -> raise (Core.Check_error err)) fmt
let check t msg x y =
show_assert msg;
if not (equal t x y) then
Fmt.strf "Error %s: expecting@\n%a, got@\n%a." msg (pp t) x (pp t) y
|> failwith
let fail msg =
show_assert msg;
check_err "Error %s." msg
let failf fmt = Fmt.kstrf fail fmt
let neg t = testable (pp t) (fun x y -> not (equal t x y))
let collect_exception f =
try
f ();
None
with e -> Some e
let check_raises msg exn f =
show_assert msg;
match collect_exception f with
| None ->
check_err "Fail %s: expecting %s, got nothing." msg
(Printexc.to_string exn)
| Some e ->
if e <> exn then
check_err "Fail %s: expecting %s, got %s." msg (Printexc.to_string exn)
(Printexc.to_string e)
let () = at_exit (Format.pp_print_flush Format.err_formatter)