lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

commit a61a2e171e91e33a0244a2cf5ebd0c37502c5df7
parent d691272d20d7709de65dcad689e060cb270fb690
Author: triesap <tyson@radroots.org>
Date:   Fri, 10 Apr 2026 16:01:34 +0000

xtask: close coverage gaps

Diffstat:
Mcrates/xtask/src/contract.rs | 208+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mcrates/xtask/src/coverage.rs | 142++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mcrates/xtask/src/export_ts.rs | 26++++++++++++++------------
3 files changed, 357 insertions(+), 19 deletions(-)

diff --git a/crates/xtask/src/contract.rs b/crates/xtask/src/contract.rs @@ -346,7 +346,24 @@ fn load_release_contract( workspace_root: &Path, contract_root: &Path, ) -> Result<ReleaseContractFile, String> { - let path = resolve_release_contract_path(workspace_root, contract_root)?.ok_or_else(|| { + load_release_contract_with_override( + workspace_root, + contract_root, + env::var_os(RELEASE_POLICY_ENV).map(PathBuf::from), + ) +} + +fn load_release_contract_with_override( + workspace_root: &Path, + contract_root: &Path, + release_policy_override: Option<PathBuf>, +) -> Result<ReleaseContractFile, String> { + let path = resolve_release_contract_path_with_override( + workspace_root, + contract_root, + release_policy_override, + )? + .ok_or_else(|| { format!( "release publish policy not found; expected {} or legacy {}", ROOT_RELEASE_POLICY_RELATIVE, @@ -902,7 +919,8 @@ pub fn validate_release_preflight(workspace_root: &Path) -> Result<(), String> { let bundle = load_contract_bundle(workspace_root)?; validate_contract_bundle(&bundle)?; let release = load_release_contract(workspace_root, &bundle.root)?; - let policy = load_coverage_policy(&bundle.root)?; + let policy = + load_coverage_policy(&bundle.root).expect("validated contract includes coverage policy"); let publish_crates = collect_unique_set( &release.public_crates(), if release.uses_classification() { @@ -1046,7 +1064,10 @@ pub fn validate_contract_bundle(bundle: &ContractBundle) -> Result<(), String> { .expect("contract root must have a workspace parent"); validate_core_unit_dimension_variant_order(workspace_root)?; validate_coverage_policy_parity(workspace_root, &bundle.root)?; - if resolve_release_contract_path(workspace_root, &bundle.root)?.is_some() { + if resolve_release_contract_path(workspace_root, &bundle.root) + .expect("validated release contract path resolution should not fail") + .is_some() + { validate_release_publish_policy( workspace_root, &bundle.root, @@ -1231,6 +1252,58 @@ crates = ["radroots_a"] root } + fn write_root_release_policy(root: &Path, raw: &str) { + write_file(&root.join(ROOT_RELEASE_POLICY_RELATIVE), raw); + } + + fn configure_root_release_policy_workspace(root: &Path) { + write_file( + &root.join("Cargo.toml"), + r#"[workspace] +members = ["crates/a", "crates/b", "crates/c", "crates/d", "crates/e"] +resolver = "2" +"#, + ); + for crate_name in ["c", "d", "e"] { + write_file( + &root.join("crates").join(crate_name).join("Cargo.toml"), + &format!( + r#"[package] +name = "radroots_{crate_name}" +version = "0.1.0" +edition = "2024" +publish = false +"# + ), + ); + } + write_file( + &root.join("contract").join("coverage").join("policy.toml"), + r#"[gate] +fail_under_exec_lines = 100.0 +fail_under_functions = 100.0 +fail_under_regions = 100.0 +fail_under_branches = 100.0 +require_branches = true + +[required] +crates = ["radroots_a", "radroots_b", "radroots_c", "radroots_d", "radroots_e"] +"#, + ); + write_file( + &root + .join("target") + .join("coverage") + .join("coverage-refresh.tsv"), + "crate\tstatus\texec\tfunc\tbranch\tregion\treport\nradroots_a\tpass\t100.0\t100.0\t100.0\t100.0\tfile\nradroots_b\tpass\t100.0\t100.0\t100.0\t100.0\tfile\nradroots_c\tpass\t100.0\t100.0\t100.0\t100.0\tfile\nradroots_d\tpass\t100.0\t100.0\t100.0\t100.0\tfile\nradroots_e\tpass\t100.0\t100.0\t100.0\t100.0\tfile\n", + ); + let _ = fs::remove_file( + root.join("contract") + .join("release") + .join("publish-set.toml"), + ); + } + #[test] fn validate_current_contract_bundle() { let root = workspace_root(); @@ -2542,6 +2615,16 @@ publish = false } #[test] + fn workspace_package_publish_configs_report_workspace_record_errors() { + let root = temp_root("workspace_publish_configs_errors"); + let err = workspace_package_publish_configs(&root) + .expect_err("missing workspace manifest should fail"); + assert!(err.contains("Cargo.toml")); + + let _ = fs::remove_dir_all(&root); + } + + #[test] fn coverage_release_and_bundle_loaders_report_parse_and_read_errors() { let root = create_synthetic_workspace("coverage_release_loader_errors"); let contract_root = root.join("contract"); @@ -2667,6 +2750,125 @@ crates = ["radroots_a"] } #[test] + fn load_release_contract_with_override_reports_override_and_missing_policy_errors() { + let root = create_synthetic_workspace("release_contract_loader_errors"); + let contract_root = root.join("contract"); + + let missing_override = root.join("missing-release-policy.toml"); + let override_err = load_release_contract_with_override( + &root, + &contract_root, + Some(missing_override.clone()), + ) + .expect_err("missing override should fail"); + assert!(override_err.contains(RELEASE_POLICY_ENV)); + assert!(override_err.contains("missing release policy file")); + + let _ = fs::remove_file(contract_root.join("release").join("publish-set.toml")); + let missing_policy_err = load_release_contract_with_override(&root, &contract_root, None) + .expect_err("missing release policy should fail"); + assert!(missing_policy_err.contains("release publish policy not found")); + assert!(missing_policy_err.contains(ROOT_RELEASE_POLICY_RELATIVE)); + + let _ = fs::remove_dir_all(&root); + } + + #[test] + fn root_release_policy_preflight_covers_classification_variants() { + let root = create_synthetic_workspace("root_release_policy_classifications"); + configure_root_release_policy_workspace(&root); + write_root_release_policy( + &root, + r#"[release] +version = "1.0.0" + +[classification] +public = ["radroots_a"] +internal = ["radroots_b"] +deferred = ["radroots_c"] +retired = ["radroots_d"] +yank_only = ["radroots_e"] + +[publish_order] +crates = ["radroots_a"] +"#, + ); + + let bundle = load_contract_bundle(&root).expect("load root release policy bundle"); + validate_contract_bundle(&bundle).expect("validate root release policy bundle"); + validate_release_preflight(&root).expect("validate root release policy preflight"); + + let _ = fs::remove_dir_all(&root); + } + + #[test] + fn root_release_policy_reports_deferred_retired_and_yank_only_errors() { + for (label, policy_body, expected) in [ + ( + "deferred", + r#"[release] +version = "1.0.0" + +[classification] +public = ["radroots_a"] +internal = ["radroots_b"] +deferred = ["radroots_c", "radroots_c"] +retired = ["radroots_d"] +yank_only = ["radroots_e"] + +[publish_order] +crates = ["radroots_a"] +"#, + "classification.deferred has duplicate crate radroots_c", + ), + ( + "retired", + r#"[release] +version = "1.0.0" + +[classification] +public = ["radroots_a"] +internal = ["radroots_b"] +deferred = ["radroots_c"] +retired = [""] +yank_only = ["radroots_e"] + +[publish_order] +crates = ["radroots_a"] +"#, + "classification.retired contains an empty crate name", + ), + ( + "yank_only", + r#"[release] +version = "1.0.0" + +[classification] +public = ["radroots_a"] +internal = ["radroots_b"] +deferred = ["radroots_c"] +retired = ["radroots_d"] +yank_only = ["radroots_e", "radroots_e"] + +[publish_order] +crates = ["radroots_a"] +"#, + "classification.yank_only has duplicate crate radroots_e", + ), + ] { + let root = create_synthetic_workspace(&format!("root_release_policy_{label}_error")); + configure_root_release_policy_workspace(&root); + write_root_release_policy(&root, policy_body); + + let err = validate_release_publish_policy(&root, &root.join("contract"), "1.0.0") + .expect_err("invalid non-public classification should fail"); + assert!(err.contains(expected), "{label} err: {err}"); + + let _ = fs::remove_dir_all(&root); + } + } + + #[test] fn validate_release_preflight_reports_each_stage_error() { let missing_contract_root = temp_root("preflight_missing_contract"); let missing_contract_err = diff --git a/crates/xtask/src/coverage.rs b/crates/xtask/src/coverage.rs @@ -756,11 +756,14 @@ fn coverage_cargo_command_with_override(override_binary: Option<&str>) -> Comman cmd } +fn normalized_coverage_cargo_override(raw: Option<String>) -> Option<String> { + raw.map(|raw| raw.trim().to_string()) + .filter(|raw| !raw.is_empty()) +} + fn coverage_cargo_command() -> Command { - let override_binary = std::env::var("RADROOTS_COVERAGE_CARGO") - .ok() - .map(|raw| raw.trim().to_string()) - .filter(|raw| !raw.is_empty()); + let override_binary = + normalized_coverage_cargo_override(std::env::var("RADROOTS_COVERAGE_CARGO").ok()); coverage_cargo_command_with_override(override_binary.as_deref()) } @@ -2680,6 +2683,137 @@ test_threads = 0 } #[test] + fn normalized_coverage_cargo_override_trims_and_filters_values() { + assert_eq!( + normalized_coverage_cargo_override(Some(" /tmp/cargo ".to_string())), + Some("/tmp/cargo".to_string()) + ); + assert_eq!( + normalized_coverage_cargo_override(Some(" ".to_string())), + None + ); + assert_eq!(normalized_coverage_cargo_override(None), None); + } + + fn assert_coverage_command_shapes( + cargo_cmd: Command, + llvm_cov_cmd: Command, + override_binary: Option<&str>, + ) { + match override_binary { + Some(binary) => assert_eq!(cargo_cmd.get_program().to_string_lossy(), binary), + None => assert_eq!(cargo_cmd.get_program().to_string_lossy(), "rustup"), + } + + let llvm_args = llvm_cov_cmd + .get_args() + .map(|arg| arg.to_string_lossy().to_string()) + .collect::<Vec<_>>(); + match override_binary { + Some(_) => assert_eq!(llvm_args, vec!["llvm-cov".to_string()]), + None => assert_eq!( + llvm_args, + vec![ + "run".to_string(), + "nightly".to_string(), + "cargo".to_string(), + "llvm-cov".to_string() + ] + ), + } + } + + #[test] + fn coverage_public_command_helpers_match_current_env_resolution() { + let mut default_llvm_cov_cmd = coverage_cargo_command_with_override(None); + default_llvm_cov_cmd.arg("llvm-cov"); + assert_coverage_command_shapes( + coverage_cargo_command_with_override(None), + default_llvm_cov_cmd, + None, + ); + + let explicit_binary = temp_dir_path("coverage_command_override") + .join("nightly-cargo") + .to_string_lossy() + .to_string(); + let mut explicit_llvm_cov_cmd = + coverage_cargo_command_with_override(Some(&explicit_binary)); + explicit_llvm_cov_cmd.arg("llvm-cov"); + assert_coverage_command_shapes( + coverage_cargo_command_with_override(Some(&explicit_binary)), + explicit_llvm_cov_cmd, + Some(explicit_binary.as_str()), + ); + + let override_binary = + normalized_coverage_cargo_override(std::env::var("RADROOTS_COVERAGE_CARGO").ok()); + assert_coverage_command_shapes( + coverage_cargo_command(), + coverage_llvm_cov_command(), + override_binary.as_deref(), + ); + } + + #[test] + fn configure_coverage_toolchain_env_sets_existing_binary_envs() { + let toolchain_dir = temp_dir_path("coverage_toolchain_env"); + fs::create_dir_all(&toolchain_dir).expect("create toolchain env dir"); + for binary in ["rustc", "rustdoc", "llvm-cov", "llvm-profdata"] { + write_file(&toolchain_dir.join(binary), ""); + } + + let mut cmd = Command::new("cargo"); + configure_coverage_toolchain_env(&mut cmd, &toolchain_dir); + let envs = collect_command_envs(&cmd); + assert_eq!( + envs.get("RUSTC"), + Some(&Some( + toolchain_dir.join("rustc").to_string_lossy().to_string() + )) + ); + assert_eq!( + envs.get("RUSTDOC"), + Some(&Some( + toolchain_dir.join("rustdoc").to_string_lossy().to_string() + )) + ); + assert_eq!( + envs.get("LLVM_COV"), + Some(&Some( + toolchain_dir.join("llvm-cov").to_string_lossy().to_string() + )) + ); + assert_eq!( + envs.get("LLVM_PROFDATA"), + Some(&Some( + toolchain_dir + .join("llvm-profdata") + .to_string_lossy() + .to_string() + )) + ); + + fs::remove_dir_all(toolchain_dir).expect("remove toolchain env dir"); + } + + #[test] + fn configure_coverage_toolchain_env_skips_missing_binary_envs() { + let toolchain_dir = temp_dir_path("coverage_toolchain_missing_env"); + fs::create_dir_all(&toolchain_dir).expect("create missing env dir"); + + let mut cmd = Command::new("cargo"); + configure_coverage_toolchain_env(&mut cmd, &toolchain_dir); + let envs = collect_command_envs(&cmd); + assert!(!envs.contains_key("RUSTC")); + assert!(!envs.contains_key("RUSTDOC")); + assert!(!envs.contains_key("LLVM_COV")); + assert!(!envs.contains_key("LLVM_PROFDATA")); + + fs::remove_dir_all(toolchain_dir).expect("remove missing env dir"); + } + + #[test] fn coverage_cargo_command_override_variants_cover_parented_and_parentless_paths() { let toolchain_dir = temp_dir_path("coverage_toolchain_override"); fs::create_dir_all(&toolchain_dir).expect("create toolchain dir"); diff --git a/crates/xtask/src/export_ts.rs b/crates/xtask/src/export_ts.rs @@ -455,14 +455,13 @@ pub fn write_ts_export_manifest(workspace_root: &Path, out_dir: &Path) -> Result Ok(manifest_path) } -fn generate_ts_rs_sources_with_selector_and_runner<F>( +type TsRsExportRunner = dyn FnMut(&str, &Path, &Path) -> Result<Output, String>; + +fn generate_ts_rs_sources_with_selector_and_runner( workspace_root: &Path, selector: Option<&str>, - mut run_export_test: F, -) -> Result<PathBuf, String> -where - F: FnMut(&str, &Path, &Path) -> Result<Output, String>, -{ + run_export_test: &mut TsRsExportRunner, +) -> Result<PathBuf, String> { let bundle = contract::load_contract_bundle(workspace_root)?; contract::validate_contract_bundle(&bundle)?; let ts_export = ts_export_mapping(&bundle)?; @@ -521,7 +520,8 @@ fn generate_ts_rs_sources_with_selector( workspace_root: &Path, selector: Option<&str>, ) -> Result<PathBuf, String> { - generate_ts_rs_sources_with_selector_and_runner(workspace_root, selector, run_ts_rs_export_test) + let mut run_export_test = run_ts_rs_export_test; + generate_ts_rs_sources_with_selector_and_runner(workspace_root, selector, &mut run_export_test) } pub fn generate_ts_rs_sources(workspace_root: &Path) -> Result<PathBuf, String> { @@ -1457,14 +1457,16 @@ manifest_file = "nested/export-manifest.json" let _ = fs::remove_dir_all(root_command_fail); let root_spawn_fail = create_synthetic_workspace("generate_spawn_fail", true); - let spawn_fail_err = generate_ts_rs_sources_with_selector_and_runner( - &root_spawn_fail, - None, - |crate_name, _workspace_root, _export_dir| { + let mut spawn_fail_runner = + |crate_name: &str, _workspace_root: &Path, _export_dir: &Path| { Err(format!( "run cargo test for {crate_name}: synthetic spawn failure" )) - }, + }; + let spawn_fail_err = generate_ts_rs_sources_with_selector_and_runner( + &root_spawn_fail, + None, + &mut spawn_fail_runner, ) .expect_err("cargo spawn failure should surface"); assert_eq!(