Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or https://opensource.org/license/mit/.5use std::env;6use std::fs::File;7use std::path::{Path, PathBuf};8use std::process::{Command, ExitCode};9use std::str;11/// A type for a complete and readable error message.12type AppError = String;13type AppResult = Result<(), AppError>;15const LLVM_PROFDATA: &str = "llvm-profdata";16const LLVM_COV: &str = "llvm-cov";17const GIT: &str = "git";19fn exit_help(err: &str) -> AppError {20format!(21r#"22Error: {err}24Usage: program ./build_dir boost_unittest_filter26Refer to the devtools/README.md for more details."#27)28}30fn sanity_check(test_exe: &Path) -> AppResult {31for tool in [LLVM_PROFDATA, LLVM_COV, GIT] {32let output = Command::new(tool).arg("--help").output();33match output {34Ok(output) if output.status.success() => {}35_ => Err(exit_help(&format!("The tool {tool} is not installed")))?,36}37}38if !test_exe.exists() {39Err(exit_help(&format!(40"Test executable ({}) not found",41test_exe.display()42)))?;43}44Ok(())45}47fn app() -> AppResult {48// Parse args49let args = env::args().collect::<Vec<_>>();50let build_dir = args.get(1).ok_or(exit_help("Must set build dir"))?;51if build_dir == "--help" {52Err(exit_help("--help requested"))?;53}54let filter = args55.get(2)56// Require filter for now. In the future it could be optional and the tool could provide a57// default filter.58.ok_or(exit_help("Must set boost test filter"))?;59if args.get(3).is_some() {60Err(exit_help("Too many args"))?;61}63let build_dir = Path::new(build_dir);64let test_exe = build_dir.join("bin/test_bitcoin");66sanity_check(&test_exe)?;68deterministic_coverage(build_dir, &test_exe, filter)69}71fn deterministic_coverage(build_dir: &Path, test_exe: &Path, filter: &str) -> AppResult {72let profraw_file = build_dir.join("test_det_cov.profraw");73let profdata_file = build_dir.join("test_det_cov.profdata");74let run_single = |run_id: char| -> Result<PathBuf, AppError> {75println!("Run with id {run_id}");76let cov_txt_path = build_dir.join(format!("test_det_cov.show.{run_id}.txt"));77if !Command::new(test_exe)78.env("LLVM_PROFILE_FILE", &profraw_file)79.env("BOOST_TEST_RUN_FILTERS", filter)80.env("RANDOM_CTX_SEED", "21")81.status()82.map_err(|e| format!("test failed with {e}"))?83.success()84{85Err("test failed".to_string())?;86}87if !Command::new(LLVM_PROFDATA)88.arg("merge")89.arg("--sparse")90.arg(&profraw_file)91.arg("-o")92.arg(&profdata_file)93.status()94.map_err(|e| format!("{LLVM_PROFDATA} merge failed with {e}"))?95.success()96{97Err(format!("{LLVM_PROFDATA} merge failed. This can be a sign of compiling without code coverage support."))?;98}99let cov_file = File::create(&cov_txt_path)100.map_err(|e| format!("Failed to create coverage txt file ({e})"))?;101if !Command::new(LLVM_COV)102.args([103"show",104"--show-line-counts-or-regions",105"--show-branches=count",106"--show-expansions",107"--show-instantiation-summary",108"-Xdemangler=llvm-cxxfilt",109&format!("--instr-profile={}", profdata_file.display()),110])111.arg(test_exe)112.stdout(cov_file)113.status()114.map_err(|e| format!("{LLVM_COV} show failed with {e}"))?115.success()116{117Err(format!("{LLVM_COV} show failed"))?;118}119Ok(cov_txt_path)120};121let check_diff = |a: &Path, b: &Path| -> AppResult {122let same = Command::new(GIT)123.args(["--no-pager", "diff", "--no-index"])124.arg(a)125.arg(b)126.status()127.map_err(|e| format!("{GIT} diff failed with {e}"))?128.success();129if !same {130Err("The coverage was not deterministic between runs.".to_string())?;131}132Ok(())133};134let r0 = run_single('a')?;135let r1 = run_single('b')?;136check_diff(&r0, &r1)?;137println!("✨ The coverage was deterministic across two runs. ✨");138Ok(())139}141fn main() -> ExitCode {142match app() {143Ok(()) => ExitCode::SUCCESS,144Err(err) => {145eprintln!("⚠️\n{err}");146ExitCode::FAILURE147}148}149}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.