-
Notifications
You must be signed in to change notification settings - Fork 1
/
tests.ml
160 lines (142 loc) · 6.21 KB
/
tests.ml
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
type _ key =
| I : int key
| S : string key
let pp_m : type a . Format.formatter -> a key -> a -> unit = fun ppf k v ->
match k, v with
| I, x -> Fmt.pf ppf "I %d" x
| S, s -> Fmt.pf ppf "S %s" s
let eq_m : type a. a key -> a -> a -> bool = fun k v v' ->
match k, v, v' with
| I, x, y -> x = y
| S, s, t -> String.equal s t
module K = struct
type 'a t = 'a key
let compare : type a b. a t -> b t -> (a, b) Gmap.Order.t = fun t t' ->
let open Gmap.Order in
match t, t' with
| I, I -> Eq | I, _ -> Lt | _, I -> Gt
| S, S -> Eq
end
module M = Gmap.Make(K)
let m_check =
let module M = struct
type t = M.t
let pp ppf m = M.iter (fun (M.B (k, v)) -> pp_m ppf k v) m
let equal a b = M.equal { f = eq_m } a b
end in
(module M: Alcotest.TESTABLE with type t = M.t)
let b_check =
let module M = struct
type t = M.b
let pp ppf (M.B (k, v)) = pp_m ppf k v
let equal (M.B (k, v)) (M.B (k', v')) = match K.compare k k' with
| Gmap.Order.Eq -> eq_m k v v'
| _ -> false
end in
(module M: Alcotest.TESTABLE with type t = M.t)
let empty () =
Alcotest.(check bool "empty map is empty" true (M.is_empty M.empty));
Alcotest.(check bool "mem on empty map doesn't have A" false (M.mem I M.empty));
Alcotest.(check (option int) "find on empty map doesn't have A" None
(M.find I M.empty));
Alcotest.(check (option string) "find on empty map doesn't have B" None
(M.find S M.empty));
Alcotest.(check (option b_check) "min binding is none" None
(M.min_binding M.empty));
Alcotest.(check (option b_check) "max binding is none" None
(M.max_binding M.empty));
Alcotest.(check (option b_check) "any binding is none" None
(M.any_binding M.empty));
Alcotest.(check (list b_check) "bindings is empty" []
(M.bindings M.empty))
let basic () =
let m = M.singleton I 5 in
Alcotest.(check bool "non-empty map is not empty" false (M.is_empty m));
Alcotest.(check int "non-empty map has cardinal 1" 1 (M.cardinal m));
Alcotest.(check bool "non-empty map has member I" true (M.mem I m));
Alcotest.(check (option int) "non-empty map finds I" (Some 5) (M.find I m));
Alcotest.check m_check "singleton and add are equivalent" m (M.add I 5 M.empty);
Alcotest.(check bool "removing I from map makes it empty" true
(M.is_empty (M.remove I m)));
Alcotest.(check bool "removing S from map makes it not empty" false
(M.is_empty (M.remove S m)));
Alcotest.check m_check "add overwrites" (M.singleton I 10) (M.add I 10 m);
Alcotest.(check (option m_check) "add_unless_bound does not overwrite" None
(M.add_unless_bound I 10 m));
Alcotest.check m_check "update updates" (M.singleton I 20)
(M.update I (fun _ -> Some 20) m);
Alcotest.(check (option b_check) "min_binding is I 5" (Some (M.B (I, 5)))
(M.min_binding m));
Alcotest.(check (option b_check) "max_binding is I 5" (Some (M.B (I, 5)))
(M.max_binding m));
Alcotest.(check (option b_check) "any_binding is I 5" (Some (M.B (I, 5)))
(M.any_binding m));
Alcotest.(check (list b_check) "bindings is [ I 5 ]" [ M.B (I, 5) ]
(M.bindings m))
let bad_eq_false : type a. a key -> a -> a -> bool = fun _ _ _ -> false
let bad_eq_true : type a. a key -> a -> a -> bool = fun _ _ _ -> true
let eq () =
let m = M.singleton I 5 in
Alcotest.(check bool "m equal is ok" true (M.equal { f = eq_m } m m));
Alcotest.(check bool "m equal is ok with singleton" true
(M.equal { f = eq_m } m (M.singleton I 5)));
Alcotest.(check bool "m equal is false" false
(M.equal { f = eq_m } m M.empty));
Alcotest.(check bool "m equal is false" false
(M.equal { f = eq_m } m (M.singleton S "foo")));
Alcotest.(check bool "m equal is false" false
(M.equal { f = eq_m } m (M.singleton I 10)));
Alcotest.(check bool "m equal is false" false
(M.equal { f = eq_m } m (M.add S "foo" (M.singleton I 10))));
Alcotest.(check bool "m bad equal is always false" false
(M.equal { f = bad_eq_false } m m));
Alcotest.(check bool "m bad equal is always true" true
(M.equal { f = bad_eq_true } m m))
let preds () =
let m = M.singleton I 5 in
let m' = M.add S "foobar" m in
let m'' = M.singleton I 10 in
let p (M.B (k, v)) = match k with I -> v = 5 | _ -> false in
Alcotest.(check bool "for_all works" true (M.for_all p m));
Alcotest.(check bool "for_all works m'" false (M.for_all p m'));
Alcotest.(check bool "for_all works m''" false (M.for_all p m''));
Alcotest.(check bool "exists works" true (M.exists p m));
Alcotest.(check bool "exists works m'" true (M.exists p m'));
Alcotest.(check bool "exists works m''" false (M.exists p m''));
Alcotest.check m_check "filter works" m (M.filter p m);
Alcotest.check m_check "filter works m'" m (M.filter p m');
Alcotest.check m_check "filter works m''" M.empty (M.filter p m'')
let map () =
let m = M.singleton I 5 in
let map : type a . a key -> a -> a = fun k _v ->
match k with
| I -> 100
| S -> "Foo"
in
Alcotest.check m_check "mapped m is equal as expected"
(M.singleton I 100) (M.map { f = map } m);
Alcotest.check m_check "mapped m is equal as expected"
(M.add S "Foo" (M.singleton I 100))
(M.map { f = map } (M.add S "barf" m))
let l_wins : type a . a key -> a -> a -> a option = fun _ v _ -> Some v
let r_wins : type a . a key -> a -> a -> a option = fun _ _ v' -> Some v'
let no_wins : type a . a key -> a -> a -> a option = fun _ _ _ -> None
let union () =
let m = M.add I 100 (M.singleton S "foo") in
Alcotest.check m_check "union map left wins is good" m
(M.union { f = l_wins } m (M.singleton S "bar"));
Alcotest.check m_check "union map right wins is good"
(M.add I 100 (M.singleton S "bar"))
(M.union { f = r_wins } m (M.singleton S "bar"));
Alcotest.check m_check "union map right wins is good"
(M.singleton I 100)
(M.union { f = no_wins } m (M.singleton S "bar"))
let tests = [
"empty gmap", `Quick, empty ;
"basic gmap", `Quick, basic ;
"equality", `Quick, eq ;
"predicates", `Quick, preds ;
"map", `Quick, map ;
"union", `Quick, union ;
]
let () = Alcotest.run "gmap tests" [ "gmap suite", tests ]