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
type 'a t = { gen : 'a Gen.t; print : 'a -> string }
let make ~gen ~print = { gen; print }
let gen t = t.gen
let print t = t.print
let pp_list pp_elem xs = "[" ^ String.concat "; " (List.map pp_elem xs) ^ "]"
let pp_array pp_elem xs =
"[|" ^ String.concat "; " (Array.to_list (Array.map pp_elem xs)) ^ "|]"
let pp_option pp_elem = function
| None -> "None"
| Some x -> "Some (" ^ pp_elem x ^ ")"
let pp_result pp_ok pp_err = function
| Ok x -> "Ok (" ^ pp_ok x ^ ")"
| Error e -> "Error (" ^ pp_err e ^ ")"
let pp_pair pp_a pp_b (a, b) = "(" ^ pp_a a ^ ", " ^ pp_b b ^ ")"
let pp_triple pp_a pp_b pp_c (a, b, c) =
"(" ^ pp_a a ^ ", " ^ pp_b b ^ ", " ^ pp_c c ^ ")"
let pp_quad pp_a pp_b pp_c pp_d (a, b, c, d) =
"(" ^ pp_a a ^ ", " ^ pp_b b ^ ", " ^ pp_c c ^ ", " ^ pp_d d ^ ")"
let cut_exp_zero s =
match String.split_on_char 'e' s with
| [ significand; exponent ] -> (
match exponent.[0] with
| '+' -> Printf.sprintf "%se+%i" significand (int_of_string exponent)
| _ -> Printf.sprintf "%se%i" significand (int_of_string exponent))
| _ -> s
let pp_float f =
if Float.is_nan f && Float.sign_bit f then "-nan"
else if Sys.win32 then cut_exp_zero (string_of_float f)
else string_of_float f
let unit = make ~gen:Gen.unit ~print:(fun () -> "()")
let bool = make ~gen:Gen.bool ~print:string_of_bool
let int = make ~gen:Gen.int ~print:string_of_int
let int_range low high = make ~gen:(Gen.int_range low high) ~print:string_of_int
let int32 = make ~gen:Gen.int32 ~print:(fun i -> Int32.to_string i ^ "l")
let int32_range low high =
make ~gen:(Gen.int32_range low high) ~print:(fun i -> Int32.to_string i ^ "l")
let int64 = make ~gen:Gen.int64 ~print:(fun i -> Int64.to_string i ^ "L")
let int64_range low high =
make ~gen:(Gen.int64_range low high) ~print:(fun i -> Int64.to_string i ^ "L")
let float = make ~gen:Gen.float ~print:pp_float
let char = make ~gen:Gen.char ~print:(fun c -> Printf.sprintf "%C" c)
let string = make ~gen:Gen.string ~print:(fun s -> Printf.sprintf "%S" s)
let bytes =
make ~gen:Gen.bytes ~print:(fun b -> Printf.sprintf "%S" (Bytes.to_string b))
let option arb = make ~gen:(Gen.option arb.gen) ~print:(pp_option arb.print)
let result ok_arb err_arb =
make
~gen:(Gen.result ok_arb.gen err_arb.gen)
~print:(pp_result ok_arb.print err_arb.print)
let list arb = make ~gen:(Gen.list arb.gen) ~print:(pp_list arb.print)
let array arb = make ~gen:(Gen.array arb.gen) ~print:(pp_array arb.print)
let pair a b = make ~gen:(Gen.pair a.gen b.gen) ~print:(pp_pair a.print b.print)
let triple a b c =
make
~gen:(Gen.triple a.gen b.gen c.gen)
~print:(pp_triple a.print b.print c.print)
let quad a b c d =
make
~gen:(Gen.quad a.gen b.gen c.gen d.gen)
~print:(pp_quad a.print b.print c.print d.print)
let oneof arbs =
match arbs with
| [] -> invalid_arg "Arbitrary.oneof: empty list"
| first :: _ ->
make ~gen:(Gen.oneof (List.map (fun a -> a.gen) arbs)) ~print:first.print
let oneofl ~print xs = make ~gen:(Gen.oneofl xs) ~print
let map ~print f arb = make ~gen:(Gen.map f arb.gen) ~print
let filter p arb =
make ~gen:(Gen.add_shrink_invariant p arb.gen) ~print:arb.print