forked from vigna/webgraph-rs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
coverage.py
137 lines (123 loc) · 3.59 KB
/
coverage.py
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
#!/usr/bin/python3
"""
To run it needs the following:
cargo install rustfilt
rustup component add --toolchain nightly llvm-tools-preview
"""
import os
import re
import sys
import subprocess
from glob import glob
# Compute the coverage for all fuzzing targets, or not
FUZZING = False
ROOT = os.path.dirname(os.path.abspath(__file__))
target_folder = os.path.join(ROOT, "target")
# Get info about the rust installation
rustup_info = subprocess.check_output("rustup show", shell=True).decode()
arch = re.findall(r"Default host: (.+)", rustup_info)[0]
# Get where LLVM is installed
sysroot = subprocess.check_output("rustc --print sysroot", shell=True).decode().strip()
llvm_path = os.path.join(sysroot, "lib", "rustlib", arch, "bin")
# Check that people can read the doc
if not os.path.exists(os.path.join(llvm_path, "llvm-profdata")):
print("PLEASE run:")
print("rustup component add --toolchain nightly llvm-tools-preview")
print("cargo install rustfilt")
sys.exit(1)
# Settings
test_cov_path = os.path.join(target_folder, "cargo-test-cov-%p-%m.profraw")
final_cov_path = os.path.join(target_folder, "total_coverage.profdata")
doc_tests_bin = os.path.join(target_folder, "doctestbins")
cov_files = []
exec_files = []
# Clean up the targets folder
subprocess.check_call(
"cargo clean",
shell=True,
cwd=ROOT,
)
# Create a folder for the test coverage
os.makedirs(target_folder, exist_ok=True)
out = subprocess.check_output(
"cargo test",
shell=True,
cwd=ROOT,
stderr=subprocess.STDOUT,
universal_newlines=True,
env={
**os.environ,
"CARGO_INCREMENTAL":"0",
"RUSTFLAGS": "-C instrument-coverage",
"RUSTDOCFLAGS":"-Zinstrument-coverage -Z unstable-options --persist-doctests {}".format(doc_tests_bin),
"LLVM_PROFILE_FILE": test_cov_path,
},
)
# For the doctests see:
# https://github.com/rust-lang/rust/issues/79417
# add the test binaries
exec_files.extend(
os.path.join(ROOT, file)
for file in re.findall(r"Running \S+ \((target/.+?)\)", out)
)
# add all the doc tests binaries
exec_files.extend(
file
for file in glob(os.path.join(doc_tests_bin, "**", "*"))
)
cov_files.extend(
os.path.join(os.path.dirname(test_cov_path), file)
for file in os.listdir(os.path.dirname(test_cov_path))
if file.endswith(".profraw")
)
if FUZZING:
# Get the list of fuzzing targets
fuzz_targets = (
subprocess.check_output(
"cargo fuzz list",
shell=True,
cwd=ROOT,
)
.decode()
.split("\n")[:-1]
)
# Generate coverage for all the targets
for fuzz_target in fuzz_targets:
subprocess.check_call(
"cargo fuzz coverage {}".format(fuzz_target),
shell=True,
cwd=ROOT,
)
cov_files.extend(
os.path.join(ROOT, "fuzz", "coverage", fuzz_target, "coverage.profdata")
for fuzz_target in fuzz_targets
)
exec_files.extend(
os.path.join(
ROOT, "target", arch, "coverage", arch, "release", fuzz_target
)
for fuzz_target in fuzz_targets
)
# Merge the coverages into an unique file
subprocess.check_call(
"{}/llvm-profdata merge -sparse {} -o {}".format(
llvm_path,
" ".join(cov_files),
final_cov_path,
),
shell=True,
cwd=ROOT,
)
# Create the report!
subprocess.check_call(
(
"{}/llvm-cov report --Xdemangler=rustfilt --instr-profile={} "
"-ignore-filename-regex='.cargo' -object {}"
).format(
llvm_path,
final_cov_path,
" -object ".join(exec_files),
),
shell=True,
cwd=ROOT,
)