import os
import re
import sys
import subprocess
from glob import glob
FUZZING = False
ROOT = os.path.dirname(os.path.abspath(__file__))
target_folder = os.path.join(ROOT, "target")
rustup_info = subprocess.check_output("rustup show", shell=True).decode()
arch = re.findall(r"Default host: (.+)", rustup_info)[0]
sysroot = subprocess.check_output("rustc --print sysroot", shell=True).decode().strip()
llvm_path = os.path.join(sysroot, "lib", "rustlib", arch, "bin")
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)
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 = []
subprocess.check_call(
"cargo clean",
shell=True,
cwd=ROOT,
)
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,
},
)
exec_files.extend(
os.path.join(ROOT, file)
for file in re.findall(r"Running \S+ \((target/.+?)\)", out)
)
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:
fuzz_targets = (
subprocess.check_output(
"cargo fuzz list",
shell=True,
cwd=ROOT,
)
.decode()
.split("\n")[:-1]
)
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
)
subprocess.check_call(
"{}/llvm-profdata merge -sparse {} -o {}".format(
llvm_path,
" ".join(cov_files),
final_cov_path,
),
shell=True,
cwd=ROOT,
)
subprocess.check_call(
(
"{}/llvm-cov report --Xdemangler=rustfilt --instr-profile={} -object {} "
).format(
llvm_path,
final_cov_path,
" -object ".join(exec_files),
),
shell=True,
cwd=ROOT,
)