Source file bisect_common.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
type instrumented_file = {
filename : string;
points : int array;
counts : int array;
}
type coverage = (string, instrumented_file) Hashtbl.t
let coverage_file_identifier = "BISECT-COVERAGE-4"
let write_int formatter i =
Format.fprintf formatter " %i" i
let write_string formatter s =
Format.fprintf formatter " %i %s" (String.length s) s
let write_array write_element formatter a =
Format.fprintf formatter " %i" (Array.length a);
Array.iter (write_element formatter) a
let write_list write_element formatter l =
Format.fprintf formatter " %i" (List.length l);
List.iter (write_element formatter) l
let write_instrumented_file formatter {filename; points; counts} =
write_string formatter filename;
write_array write_int formatter points;
write_array write_int formatter counts
let write_coverage formatter coverage =
Format.fprintf formatter "%s" coverage_file_identifier;
write_list write_instrumented_file formatter coverage;
Format.pp_print_flush formatter ()
let coverage : coverage Lazy.t =
lazy (Hashtbl.create 17)
let register_file ~filename ~points =
let counts = Array.make (Array.length points) 0 in
let coverage = Lazy.force coverage in
if not (Hashtbl.mem coverage filename) then
Hashtbl.add coverage filename {filename; points; counts};
`Visit (fun index ->
let current_count = counts.(index) in
if current_count < max_int then
counts.(index) <- current_count + 1)
let flatten_coverage coverage =
Hashtbl.fold (fun _ file acc -> file::acc) coverage []
let flatten_data () =
flatten_coverage (Lazy.force coverage)
let reset_counters () =
Lazy.force coverage
|> Hashtbl.iter begin fun _ {counts; _} ->
match Array.length counts with
| 0 -> ()
| n -> Array.fill counts 0 (n - 1) 0
end
(** Helpers for serializing the coverage data in {!coverage}. *)
let runtime_data_to_string () =
match flatten_data () with
| [] ->
None
| data ->
let buffer = Buffer.create 4096 in
write_coverage (Format.formatter_of_buffer buffer) data;
Some (Buffer.contents buffer)
let write_runtime_coverage coverage channel =
write_coverage (Format.formatter_of_out_channel channel) (flatten_coverage coverage)
let write_runtime_data channel =
write_coverage (Format.formatter_of_out_channel channel) (flatten_data ())
let prng =
Random.State.make_self_init () [@coverage off]
let random_filename ~prefix =
Printf.sprintf "%s%09d.coverage"
prefix (abs (Random.State.int prng 1000000000))