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
106
107
108
109
110
111
112
113
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 buffer i =
Buffer.add_char buffer ' ';
Buffer.add_string buffer (string_of_int i)
let write_string buffer s =
Buffer.add_char buffer ' ';
Buffer.add_string buffer (string_of_int (String.length s));
Buffer.add_char buffer ' ';
Buffer.add_string buffer s
let write_array write_element buffer a =
Buffer.add_char buffer ' ';
Buffer.add_string buffer (string_of_int (Array.length a));
Array.iter (write_element buffer) a
let write_list write_element buffer l =
Buffer.add_char buffer ' ';
Buffer.add_string buffer (string_of_int (List.length l));
List.iter (write_element buffer) l
let write_instrumented_file buffer {filename; points; counts} =
write_string buffer filename;
write_array write_int buffer points;
write_array write_int buffer counts
let write_coverage coverage =
let buffer = Buffer.create 4096 in
Buffer.add_string buffer coverage_file_identifier;
write_list write_instrumented_file buffer coverage;
Buffer.contents buffer
let coverage : coverage Lazy.t =
lazy (Hashtbl.create 17)
let register_file ~filename ~points =
let filename =
if Filename.check_suffix filename ".re.ml" then
Filename.chop_suffix filename ".ml"
else
filename
in
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 reset_counters () =
Hashtbl.iter begin fun _ {counts; _} ->
match Array.length counts with
| 0 -> ()
| n -> Array.fill counts 0 (n - 1) 0
end
(Lazy.force coverage)
(** Helpers for serializing the coverage data in {!coverage}. *)
let flatten_coverage coverage =
Hashtbl.fold (fun _ file acc -> file::acc) coverage []
let runtime_data_to_string () =
match flatten_coverage (Lazy.force coverage) with
| [] ->
None
| data ->
Some (write_coverage data)
let write_coverage coverage =
write_coverage (flatten_coverage coverage)
let prng =
Random.State.make_self_init () [@coverage off]
let random_filename ~prefix =
prefix ^
(string_of_int (abs (Random.State.int prng 1000000000))) ^
".coverage"