package hegel

  1. Overview
  2. Docs
Hegel property-based testing library for OCaml

Install

dune-project
 Dependency

Authors

Maintainers

Sources

hegel-0.24.1-opam.tar.gz
md5=d6985126c61aec88003bc03555a0d763
sha512=03e73b752dfb9ea711bc95fd87a777c068a789e7094650c5297fd37ad023292528a6fc69ea88986c02ea3f24c5c24d28353c220fd87595ce047521eecf94e0a8

doc/src/hegel/settings.ml.html

Source file settings.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
module Ffi = Hegel_ffi.Ffi

type health_check =
  | Filter_too_much
  | Too_slow
  | Test_cases_too_large
  | Large_initial_test_case

let health_check_to_string = function
  | Filter_too_much -> "filter_too_much"
  | Too_slow -> "too_slow"
  | Test_cases_too_large -> "test_cases_too_large"
  | Large_initial_test_case -> "large_initial_test_case"
;;

type verbosity =
  | Quiet
  | Normal
  | Verbose
  | Debug

type database =
  | Unset
  | Disabled
  | Path of string

type backend =
  | Default
  | Urandom

type phase =
  | Explicit
  | Reuse
  | Generate
  | Target
  | Shrink

let phase_to_string = function
  | Explicit -> "explicit"
  | Reuse -> "reuse"
  | Generate -> "generate"
  | Target -> "target"
  | Shrink -> "shrink"
;;

type t =
  { test_cases : int
  ; verbosity : verbosity
  ; seed : int option
  ; derandomize : bool
  ; database : database
  ; suppress_health_check : health_check list
  ; phases : phase list
  ; print_blob : bool
  ; report_multiple_failures : bool
  ; show_statistics : bool
  ; backend : backend
  }

(* ------------------------------------------------------------------ *)
(* Translation to and from an engine settings handle                   *)
(* ------------------------------------------------------------------ *)

let ffi_verbosity = function
  | Quiet -> Ffi.Quiet
  | Normal -> Ffi.Normal
  | Verbose -> Ffi.Verbose
  | Debug -> Ffi.Debug
;;

let ffi_backend = function
  | Default -> Ffi.Default
  | Urandom -> Ffi.Urandom
;;

let backend_of_ffi = function
  | Ffi.Default -> Default
  | Ffi.Urandom -> Urandom
;;

let verbosity_of_ffi = function
  | Ffi.Quiet -> Quiet
  | Ffi.Normal -> Normal
  | Ffi.Verbose -> Verbose
  | Ffi.Debug -> Debug
;;

let all_phases = [ Explicit; Reuse; Generate; Target; Shrink ]

let phase_bit = function
  | Explicit -> Ffi.phase_explicit
  | Reuse -> Ffi.phase_reuse
  | Generate -> Ffi.phase_generate
  | Target -> Ffi.phase_target
  | Shrink -> Ffi.phase_shrink
;;

let all_health_checks =
  [ Filter_too_much; Too_slow; Test_cases_too_large; Large_initial_test_case ]
;;

let health_check_bit = function
  | Filter_too_much -> Ffi.hc_filter_too_much
  | Too_slow -> Ffi.hc_too_slow
  | Test_cases_too_large -> Ffi.hc_test_cases_too_large
  | Large_initial_test_case -> Ffi.hc_large_initial_test_case
;;

let bitmask bit_of items = List.fold_left (fun acc x -> acc lor bit_of x) 0 items
let of_bitmask bit_of all mask = List.filter (fun x -> mask land bit_of x <> 0) all

let of_ffi ctx s =
  { test_cases = Ffi.settings_get_test_cases ctx s
  ; verbosity = verbosity_of_ffi (Ffi.settings_get_verbosity ctx s)
  ; seed = Ffi.settings_get_seed ctx s
  ; derandomize = Ffi.settings_get_derandomize ctx s
  ; database =
      (match Ffi.settings_get_database ctx s with
       | None -> Unset
       | Some "" -> Disabled
       | Some dir -> Path dir)
  ; suppress_health_check =
      of_bitmask
        health_check_bit
        all_health_checks
        (Ffi.settings_get_suppress_health_check ctx s)
  ; phases = of_bitmask phase_bit all_phases (Ffi.settings_get_phases ctx s)
  ; print_blob = Ffi.settings_get_print_blob ctx s
  ; report_multiple_failures = Ffi.settings_get_report_multiple_failures ctx s
  ; show_statistics = Ffi.settings_get_show_statistics ctx s
  ; backend = backend_of_ffi (Ffi.settings_get_backend ctx s)
  }
;;

let to_ffi ctx t ~database_key =
  let s = Ffi.settings_new ctx in
  Ffi.settings_test_cases ctx s t.test_cases;
  Ffi.settings_verbosity ctx s (ffi_verbosity t.verbosity);
  Ffi.settings_seed ctx s t.seed;
  Ffi.settings_derandomize ctx s t.derandomize;
  Ffi.settings_report_multiple_failures ctx s t.report_multiple_failures;
  Ffi.settings_show_statistics ctx s t.show_statistics;
  Ffi.settings_backend ctx s (ffi_backend t.backend);
  Ffi.settings_print_blob ctx s t.print_blob;
  Ffi.settings_database
    ctx
    s
    (match t.database with
     | Unset -> None
     | Disabled -> Some ""
     | Path p -> Some p);
  Option.iter (fun k -> Ffi.settings_database_key ctx s (Some k)) database_key;
  Ffi.settings_phases ctx s (bitmask phase_bit t.phases);
  Ffi.settings_suppress_health_check
    ctx
    s
    (bitmask health_check_bit t.suppress_health_check);
  s
;;

(* ------------------------------------------------------------------ *)
(* Profiles                                                            *)
(* ------------------------------------------------------------------ *)

let with_context f =
  let ctx = Ffi.context_new () in
  Fun.protect ~finally:(fun () -> Ffi.context_free ctx) (fun () -> f ctx)
;;

let from_profile name =
  with_context (fun ctx ->
    let s = Ffi.settings_new_for_profile ctx name in
    Fun.protect ~finally:(fun () -> Ffi.settings_free ctx s) (fun () -> of_ffi ctx s))
;;

let default () = from_profile "default"

let create ?test_cases ?seed () =
  let s = default () in
  let s =
    Option.fold ~none:s ~some:(fun test_cases -> { s with test_cases }) test_cases
  in
  Option.fold ~none:s ~some:(fun v -> { s with seed = Some v }) seed
;;

let register_profile name t =
  with_context (fun ctx ->
    let s = to_ffi ctx t ~database_key:None in
    Fun.protect
      ~finally:(fun () -> Ffi.settings_free ctx s)
      (fun () -> Ffi.settings_register_profile ctx name s))
;;

let set_default_profile name = with_context (fun ctx -> Ffi.set_default_profile ctx name)