package qcheck-multicoretests-util

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file util.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
let rec repeat n prop = fun input ->
  if n<0 then failwith "repeat: negative repetition count";
  if n=0
  then true
  else prop input && repeat (n-1) prop input

exception Timeout

let prop_timeout sec p x =
  Sys.(signal sigalrm (Signal_handle (fun _ -> raise Timeout))) |> ignore;
  ignore (Unix.alarm sec);
  let res = p x in
  ignore (Unix.alarm 0); (*cancel alarm*)
  res

let fork_prop_with_timeout sec p x =
  let a = Unix.fork () in
  match a with
  | 0  ->
    let _ = Unix.alarm sec in
    if p x
    then (ignore (Unix.alarm 0); exit 0) (*cancel alarm*)
    else (ignore (Unix.alarm 0); exit 2) (*cancel alarm*)
  | _  ->
    let _childid, retcode = Unix.wait () in
    (match retcode with
     | WEXITED code -> (0=code)
     | WSIGNALED s when s = Sys.sigalrm -> raise Timeout
     | WSIGNALED _
     | WSTOPPED _  -> false)

let print_vertical ?(fig_indent=3) show cmds =
  let cmds = List.map show cmds in
  let buf = Buffer.create 64 in
  let indent () = Printf.bprintf buf "%s" (String.make fig_indent ' ') in
  let print_seq_col c = Printf.bprintf buf "%s\n" c in
  let () = List.iter (fun c -> indent (); print_seq_col c) cmds in
  Buffer.contents buf

let print_triple_vertical ?(fig_indent=10) ?(res_width=20) ?(center_prefix=true) show (seq,cmds1,cmds2) =
  let seq,cmds1,cmds2 = List.(map show seq, map show cmds1, map show cmds2) in
  let max_width ss = List.fold_left max 0 (List.map String.length ss) in
  let width = List.fold_left max 0 [max_width seq; max_width cmds1; max_width cmds2] in
  let res_width = max width res_width in
  let cmd_indent = String.make ((width-1)/2) ' ' in
  let seq_indent = String.make ((res_width + 3)/2) ' ' in
  let bar_cmd = Printf.sprintf "%-*s" res_width (cmd_indent ^ "|") in
  let center c =
    let clen = String.length c in
    if clen > width (* it's a '|'-string *)
    then c
    else Printf.sprintf "%s%s" (String.make ((width - clen)/2) ' ') c in
  let buf = Buffer.create 64 in
  let indent () = Printf.bprintf buf "%s" (String.make fig_indent ' ') in
  let print_seq_col c = Printf.bprintf buf "%s%-*s\n" seq_indent res_width c in
  let print_par_col c1 c2 = Printf.bprintf buf "%-*s  %-*s\n" res_width c1 res_width c2 in
  let print_hoz_line () =
    Printf.bprintf buf "%-*s\n" res_width (cmd_indent ^ "." ^ (String.make (res_width + 1) '-') ^ ".") in
  let rec print_par_cols cs cs' = match cs,cs' with
    | [],   []    -> ()
    | c::cs,[]    -> indent (); print_par_col (center c) ""; print_par_cols cs []
    | [],   c::cs -> indent (); print_par_col "" (center c); print_par_cols [] cs
    | l::ls,r::rs -> indent (); print_par_col (center l) (center r); print_par_cols ls rs in
  (* actual printing *)
  if center_prefix
  then
    List.iter (fun c -> indent (); print_seq_col (center c)) ([bar_cmd] @ seq @ [bar_cmd])
  else
    List.iter (fun c -> indent (); print_par_col (center c) "") (bar_cmd::seq@[bar_cmd]);
  indent (); print_hoz_line ();
  print_par_cols (bar_cmd::cmds1) (bar_cmd::cmds2);
  Buffer.contents buf

let protect (f : 'a -> 'b) (a : 'a) : ('b, exn) result =
  try Result.Ok (f a)
  with e -> Result.Error e

module Pp = struct
  open Format

  type 'a t = bool -> Format.formatter -> 'a -> unit

  type pp_thunk = Format.formatter -> unit

  let truncate_message = "... (truncated)"

  let truncate_length =
    let truncate_env = "MCTUTILS_TRUNCATE" in
    let ( let* ) = Option.bind in
    let* l = Sys.getenv_opt truncate_env in
    let* l = int_of_string_opt l in
    (* it does not make sense to truncate at less than the length of
       [truncate_message] *)
    if l > 0 then Some (max l (String.length truncate_message - 1)) else None

  let to_show f x =
    match truncate_length with
    | None ->
        let buf = Buffer.create 512 in
        let fmt = formatter_of_buffer buf in
        pp_set_margin fmt max_int;
        fprintf fmt "@[<h 0>%a@]@?" (f false) x;
        let s = Buffer.contents buf in
        Buffer.reset buf;
        s
    | Some trlen ->
        (* if we overflow, we'll have the [truncate_message] at the end of the
           buffer, filling it until [trlen + 1]: we'll use the fact that the
           buffer contains more than [trlen] to indicate that it has already
           overflown *)
        let buf = Buffer.create (trlen + 1) in
        let msglen = String.length truncate_message in
        let out str ofs len =
          let blen = Buffer.length buf in
          (* if we didn't overflow yet... *)
          if blen <= trlen then
            if blen + len > trlen then (
              let fits = trlen - blen - msglen + 1 in
              if fits > 0 then Buffer.add_substring buf str ofs fits
              else Buffer.truncate buf (trlen + 1 - msglen);
              Buffer.add_string buf truncate_message)
            else Buffer.add_substring buf str ofs len
        in
        let ppf = make_formatter out ignore in
        pp_set_margin ppf max_int;
        fprintf ppf "@[<h 0>%a@]@?" (f false) x;
        let s = Buffer.contents buf in
        Buffer.reset buf;
        s

  let of_show f par fmt x =
    fprintf fmt (if par then "@[(%s)@]" else "@[%s@]") (f x)

  let cst0 name fmt = pp_print_string fmt name

  let cst1 (pp : 'a t) name par fmt x =
    let o, c = if par then ("(", ")") else ("", "") in
    fprintf fmt "%s@[<2>%s@ %a@]%s" o name (pp true) x c

  let cst2 (pp1 : 'a t) (pp2 : 'b t) name par fmt x y =
    let o, c = if par then ("(", ")") else ("", "") in
    fprintf fmt "%s@[<2>%s (@,%a,@ %a)@]%s" o name (pp1 false) x (pp2 false) y c

  let cst3 (pp1 : 'a t) (pp2 : 'b t) (pp3 : 'c t) name par fmt x y z =
    let o, c = if par then ("(", ")") else ("", "") in
    fprintf fmt "%s@[<2>%s (@,%a,@ %a,@ %a)@]%s" o name (pp1 false) x
      (pp2 false) y (pp3 false) z c

  let cst4 (pp1 : 'a t) (pp2 : 'b t) (pp3 : 'c t) (pp4 : 'd t) name par fmt x y z w =
    let o, c = if par then ("(", ")") else ("", "") in
    fprintf fmt "%s@[<2>%s (@,%a,@ %a,@ %a,@ %a)@]%s" o name (pp1 false) x
      (pp2 false) y (pp3 false) z (pp4 false) w c

  let cst5 (pp1 : 'a t) (pp2 : 'b t) (pp3 : 'c t) (pp4 : 'd t) (pp5 : 'e t) name par fmt x y z w v =
    let o, c = if par then ("(", ")") else ("", "") in
    fprintf fmt "%s@[<2>%s (@,%a,@ %a,@ %a,@ %a,@ %a)@]%s" o name (pp1 false) x
      (pp2 false) y (pp3 false) z (pp4 false) w (pp5 false) v c

  let pp_exn = of_show Printexc.to_string
  let pp_unit _ fmt () = pp_print_string fmt "()"
  let pp_bool _ fmt b = fprintf fmt "%B" b
  let pp_int par fmt i = fprintf fmt (if par && i < 0 then "(%d)" else "%d") i
  let pp_int32 par fmt i = fprintf fmt (if par && i < 0l then "(%ldl)" else "%ldl") i
  let pp_int64 par fmt i = fprintf fmt (if par && i < 0L then "(%LdL)" else "%LdL") i
  let pp_float par fmt f = fprintf fmt (if par && f < 0.0 then "(%F)" else "%F") f
  let pp_char _ fmt c = fprintf fmt "%C" c
  let pp_string _ fmt s = fprintf fmt "%S" s
  let pp_bytes _ fmt s = fprintf fmt "%S" (Bytes.to_string s)

  let pp_option (pp_s : 'a t) par fmt o =
    match o with
    | None -> cst0 "None" fmt
    | Some s -> cst1 pp_s "Some" par fmt s

  let pp_result (pp_o : 'o t) (pp_e : 'e t) par fmt r =
    let open Result in
    match r with
    | Ok o -> cst1 pp_o "Ok" par fmt o
    | Error e -> cst1 pp_e "Error" par fmt e

  type pp_tuple_item = pp_thunk

  let pp_tuple_item pp x fmt = pp false fmt x

  let pp_tuple _ fmt items =
    fprintf fmt "(@[";
    pp_print_list ~pp_sep:(fun fmt () -> fprintf fmt ",@ ") (fun fmt ppf -> ppf fmt) fmt items;
    fprintf fmt "@])"

  let pp_tuple2 pp1 pp2 p fmt (x1, x2) =
    pp_tuple p fmt [ pp_tuple_item pp1 x1; pp_tuple_item pp2 x2 ]

  let pp_tuple3 pp1 pp2 pp3 p fmt (x1, x2, x3) =
    pp_tuple p fmt
      [ pp_tuple_item pp1 x1; pp_tuple_item pp2 x2; pp_tuple_item pp3 x3 ]

  let pp_tuple4 pp1 pp2 pp3 pp4 p fmt (x1, x2, x3, x4) =
    pp_tuple p fmt
      [
        pp_tuple_item pp1 x1;
        pp_tuple_item pp2 x2;
        pp_tuple_item pp3 x3;
        pp_tuple_item pp4 x4;
      ]

  let pp_tuple5 pp1 pp2 pp3 pp4 pp5 p fmt (x1, x2, x3, x4, x5) =
    pp_tuple p fmt
      [
        pp_tuple_item pp1 x1;
        pp_tuple_item pp2 x2;
        pp_tuple_item pp3 x3;
        pp_tuple_item pp4 x4;
        pp_tuple_item pp5 x5;
      ]

  let pp_tuple6 pp1 pp2 pp3 pp4 pp5 pp6 p fmt (x1, x2, x3, x4, x5, x6) =
    pp_tuple p fmt
      [
        pp_tuple_item pp1 x1;
        pp_tuple_item pp2 x2;
        pp_tuple_item pp3 x3;
        pp_tuple_item pp4 x4;
        pp_tuple_item pp5 x5;
        pp_tuple_item pp6 x6;
      ]

  let pp_tuple7 pp1 pp2 pp3 pp4 pp5 pp6 pp7 p fmt (x1, x2, x3, x4, x5, x6, x7) =
    pp_tuple p fmt
      [
        pp_tuple_item pp1 x1;
        pp_tuple_item pp2 x2;
        pp_tuple_item pp3 x3;
        pp_tuple_item pp4 x4;
        pp_tuple_item pp5 x5;
        pp_tuple_item pp6 x6;
        pp_tuple_item pp7 x7;
      ]

  let pp_tuple8 pp1 pp2 pp3 pp4 pp5 pp6 pp7 pp8 p fmt
      (x1, x2, x3, x4, x5, x6, x7, x8) =
    pp_tuple p fmt
      [
        pp_tuple_item pp1 x1;
        pp_tuple_item pp2 x2;
        pp_tuple_item pp3 x3;
        pp_tuple_item pp4 x4;
        pp_tuple_item pp5 x5;
        pp_tuple_item pp6 x6;
        pp_tuple_item pp7 x7;
        pp_tuple_item pp8 x8;
      ]

  let pp_tuple9 pp1 pp2 pp3 pp4 pp5 pp6 pp7 pp8 pp9 p fmt
      (x1, x2, x3, x4, x5, x6, x7, x8, x9) =
    pp_tuple p fmt
      [
        pp_tuple_item pp1 x1;
        pp_tuple_item pp2 x2;
        pp_tuple_item pp3 x3;
        pp_tuple_item pp4 x4;
        pp_tuple_item pp5 x5;
        pp_tuple_item pp6 x6;
        pp_tuple_item pp7 x7;
        pp_tuple_item pp8 x8;
        pp_tuple_item pp9 x9;
      ]

  let pp_tuple10 pp1 pp2 pp3 pp4 pp5 pp6 pp7 pp8 pp9 pp10 p fmt
      (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) =
    pp_tuple p fmt
      [
        pp_tuple_item pp1 x1;
        pp_tuple_item pp2 x2;
        pp_tuple_item pp3 x3;
        pp_tuple_item pp4 x4;
        pp_tuple_item pp5 x5;
        pp_tuple_item pp6 x6;
        pp_tuple_item pp7 x7;
        pp_tuple_item pp8 x8;
        pp_tuple_item pp9 x9;
        pp_tuple_item pp10 x10;
      ]

  let pp_pair = pp_tuple2

  let pp_list (pp_e : 'a t) _ fmt l =
    fprintf fmt "@[<2>[";
    pp_print_list ~pp_sep:(fun fmt () -> fprintf fmt ";@ ") (pp_e false) fmt l;
    fprintf fmt "@,]@]"

  let pp_seq (pp_e : 'a t) _ fmt s =
    fprintf fmt "@[<2><";
    pp_print_seq ~pp_sep:(fun fmt () -> fprintf fmt ";@ ") (pp_e false) fmt s;
    fprintf fmt "@,>@]"

  let pp_array (pp_e : 'a t) _ fmt a =
    fprintf fmt "@[<2>[|";
    pp_print_seq ~pp_sep:(fun fmt () -> fprintf fmt ";@ ") (pp_e false) fmt (Array.to_seq a);
    fprintf fmt "@,|]@]"

  type pp_field = pp_thunk

  let pp_field name (pp_c : 'a t) c fmt =
    fprintf fmt "@[%s =@ %a@]" name (pp_c false) c

  let pp_record _ fmt fields =
    fprintf fmt "@[<2>{ ";
    pp_print_list ~pp_sep:(fun fmt () -> fprintf fmt ";@ ") (fun fmt ppf -> ppf fmt) fmt fields;
    fprintf fmt "@ }@]"

  let pp_fun_ par fmt f = fprintf fmt (if par then "(%s)" else "%s") (QCheck.Fn.print f)
end

module Equal = struct
  type 'a t = 'a -> 'a -> bool

  let equal_exn = ( = )
  let equal_unit = Unit.equal
  let equal_bool = Bool.equal
  let equal_int = Int.equal
  let equal_int64 = Int64.equal
  let equal_float = Float.equal
  let equal_char = Char.equal
  let equal_string = String.equal
  let equal_option = Option.equal
  let equal_result eq_o eq_e x y = Result.equal ~ok:eq_o ~error:eq_e x y
  let equal_list = List.equal
  let rec equal_seq eq s1 s2 = (* To support OCaml 4.13 as Seq.equal was added in 4.14 *)
    let open Seq in
    match s1 (), s2 () with
    | Nil, Nil -> true
    | Cons (a, an), Cons (b, bn) when eq a b -> equal_seq eq an bn
    | _ -> false
  let equal_array eq x y = equal_seq eq (Array.to_seq x) (Array.to_seq y)
end
OCaml

Innovation. Community. Security.