lib

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

main.rs (8475B)


      1 #![cfg_attr(coverage_nightly, feature(coverage_attribute))]
      2 #![forbid(unsafe_code)]
      3 
      4 #[cfg_attr(coverage_nightly, coverage(off))]
      5 mod contract;
      6 mod coverage;
      7 #[cfg_attr(coverage_nightly, coverage(off))]
      8 mod hygiene;
      9 
     10 use std::env;
     11 use std::path::{Path, PathBuf};
     12 use std::process::ExitCode;
     13 
     14 fn usage() {
     15     eprintln!("usage:");
     16     eprintln!("  cargo xtask contract validate");
     17     eprintln!("  cargo xtask release preflight");
     18     eprintln!("  cargo xtask coverage run-crate --crate <crate> [--out <dir>]");
     19     eprintln!("  cargo xtask coverage required-crates");
     20     eprintln!("  cargo xtask coverage workspace-crates");
     21     eprintln!(
     22         "  cargo xtask coverage report --scope <scope> --summary <file> --lcov <file> --out <file> [--policy-gate | (--fail-under-exec-lines <pct> --fail-under-functions <pct> --fail-under-regions <pct> --fail-under-branches <pct> [--require-branches])]"
     23     );
     24     eprintln!(
     25         "  cargo xtask coverage report-missing --scope <scope> --out <file> --reason <reason>"
     26     );
     27     eprintln!(
     28         "  cargo xtask coverage refresh-summary [--reports-root <dir>] [--out <file>] [--status-out <file>]"
     29     );
     30     eprintln!("  cargo xtask hygiene forbidden-identifiers");
     31 }
     32 
     33 fn workspace_root_with_override(override_root: Option<&str>) -> PathBuf {
     34     if let Some(raw) = override_root {
     35         let trimmed = raw.trim();
     36         if !trimmed.is_empty() {
     37             return PathBuf::from(trimmed);
     38         }
     39     }
     40     let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
     41     let crates_dir = manifest_dir.parent().unwrap_or(manifest_dir);
     42     let root = crates_dir.parent().unwrap_or(crates_dir);
     43     root.to_path_buf()
     44 }
     45 
     46 fn workspace_root() -> PathBuf {
     47     let override_root = env::var("RADROOTS_WORKSPACE_ROOT").ok();
     48     workspace_root_with_override(override_root.as_deref())
     49 }
     50 
     51 fn validate_contract() -> Result<(), String> {
     52     let root = workspace_root();
     53     contract::load_contract_bundle(&root)
     54         .and_then(|bundle| contract::validate_contract_bundle(&bundle))
     55         .and_then(|_| contract::validate_canonical_event_boundary(&root))
     56 }
     57 
     58 #[cfg_attr(coverage_nightly, coverage(off))]
     59 fn release_preflight() -> Result<(), String> {
     60     contract::validate_release_preflight(&workspace_root())
     61 }
     62 
     63 fn run_release(args: &[String]) -> Result<(), String> {
     64     match args.first().map(String::as_str) {
     65         Some("preflight") => release_preflight(),
     66         _ => Err("unknown release subcommand".to_string()),
     67     }
     68 }
     69 
     70 fn run_contract(args: &[String]) -> Result<(), String> {
     71     match args.first().map(String::as_str) {
     72         Some("validate") => validate_contract(),
     73         _ => Err("unknown contract subcommand".to_string()),
     74     }
     75 }
     76 
     77 fn run(args: &[String]) -> Result<(), String> {
     78     match args.first().map(String::as_str) {
     79         Some("contract") => run_contract(&args[1..]),
     80         Some("coverage") => coverage::run(&args[1..]),
     81         Some("hygiene") => hygiene::run(&args[1..], &workspace_root()),
     82         Some("release") => run_release(&args[1..]),
     83         _ => Err("unknown command".to_string()),
     84     }
     85 }
     86 
     87 fn main_with_args(args: Vec<String>) -> ExitCode {
     88     if args.is_empty() {
     89         usage();
     90         return ExitCode::from(2);
     91     }
     92     match run(&args) {
     93         Ok(()) => ExitCode::SUCCESS,
     94         Err(err) => {
     95             eprintln!("{err}");
     96             usage();
     97             ExitCode::from(2)
     98         }
     99     }
    100 }
    101 
    102 #[cfg_attr(coverage_nightly, coverage(off))]
    103 fn main() -> ExitCode {
    104     main_with_args(env::args().skip(1).collect())
    105 }
    106 
    107 #[cfg(test)]
    108 mod tests {
    109     use super::*;
    110     use std::fs;
    111     use std::sync::{Mutex, MutexGuard, OnceLock};
    112     use std::time::{SystemTime, UNIX_EPOCH};
    113 
    114     fn workspace_lock() -> &'static Mutex<()> {
    115         static LOCK: OnceLock<Mutex<()>> = OnceLock::new();
    116         LOCK.get_or_init(|| Mutex::new(()))
    117     }
    118 
    119     fn lock_workspace() -> MutexGuard<'static, ()> {
    120         match workspace_lock().lock() {
    121             Ok(guard) => guard,
    122             Err(poison) => poison.into_inner(),
    123         }
    124     }
    125 
    126     fn unique_temp_dir(prefix: &str) -> PathBuf {
    127         let ns = SystemTime::now()
    128             .duration_since(UNIX_EPOCH)
    129             .expect("system time")
    130             .as_nanos();
    131         std::env::temp_dir().join(format!("radroots_xtask_main_{prefix}_{ns}"))
    132     }
    133 
    134     #[test]
    135     fn workspace_root_resolves() {
    136         let root = workspace_root();
    137         assert!(root.join("Cargo.toml").exists());
    138     }
    139 
    140     #[test]
    141     fn workspace_root_override_takes_precedence() {
    142         let root = workspace_root_with_override(Some("/tmp/radroots-test-root"));
    143         assert_eq!(root, PathBuf::from("/tmp/radroots-test-root"));
    144 
    145         let fallback = workspace_root_with_override(Some("   "));
    146         assert!(fallback.join("Cargo.toml").exists());
    147 
    148         let default_root = workspace_root_with_override(None);
    149         assert!(default_root.join("Cargo.toml").exists());
    150     }
    151 
    152     #[test]
    153     fn run_release_and_dispatchers_cover_error_paths() {
    154         let unknown_release =
    155             run_release(&["unknown".to_string()]).expect_err("unknown release subcommand");
    156         assert!(unknown_release.contains("unknown release subcommand"));
    157 
    158         let unknown_contract =
    159             run_contract(&["unknown".to_string()]).expect_err("unknown contract subcommand");
    160         assert!(unknown_contract.contains("unknown contract subcommand"));
    161 
    162         let unknown_root = run(&["unknown".to_string()]).expect_err("unknown command");
    163         assert!(unknown_root.contains("unknown command"));
    164 
    165         let removed_sdk = run(&["sdk".to_string(), "validate".to_string()])
    166             .expect_err("removed sdk command namespace");
    167         assert!(removed_sdk.contains("unknown command"));
    168     }
    169 
    170     #[test]
    171     fn lock_workspace_recovers_from_poisoned_mutex() {
    172         let handle = std::thread::spawn(|| {
    173             let _guard = workspace_lock().lock().expect("lock workspace");
    174             panic!("poison workspace lock");
    175         });
    176         assert!(handle.join().is_err());
    177 
    178         let _guard = lock_workspace();
    179     }
    180 
    181     #[test]
    182     fn contract_and_coverage_dispatchers_execute() {
    183         let _guard = lock_workspace();
    184         let out_dir = unique_temp_dir("coverage_dispatch");
    185         fs::create_dir_all(&out_dir).expect("create out dir");
    186 
    187         run_contract(&["validate".to_string()]).expect("validate contract");
    188         coverage::run(&["help".to_string()]).expect("coverage help");
    189         coverage::run(&["required-crates".to_string()]).expect("coverage required crates");
    190         coverage::run(&["workspace-crates".to_string()]).expect("coverage workspace crates");
    191 
    192         let summary_path = out_dir.join("summary.json");
    193         let lcov_path = out_dir.join("coverage.info");
    194         let gate_out = out_dir.join("gate-report.json");
    195         fs::write(
    196             &summary_path,
    197             r#"{"data":[{"totals":{"functions":{"percent":100.0},"lines":{"percent":100.0},"regions":{"percent":100.0}}}]}"#,
    198         )
    199         .expect("write summary");
    200         fs::write(&lcov_path, "DA:1,1\nBRDA:1,0,0,1\n").expect("write lcov");
    201         coverage::run(&[
    202             "report".to_string(),
    203             "--scope".to_string(),
    204             "main-test".to_string(),
    205             "--summary".to_string(),
    206             summary_path.display().to_string(),
    207             "--lcov".to_string(),
    208             lcov_path.display().to_string(),
    209             "--out".to_string(),
    210             gate_out.display().to_string(),
    211             "--policy-gate".to_string(),
    212         ])
    213         .expect("coverage report");
    214 
    215         run(&["coverage".to_string(), "help".to_string()]).expect("root run coverage");
    216         run(&["hygiene".to_string(), "forbidden-identifiers".to_string()])
    217             .expect("hygiene forbidden identifiers");
    218 
    219         let _ = fs::remove_dir_all(out_dir);
    220     }
    221 
    222     #[test]
    223     fn usage_and_main_entrypoints_execute() {
    224         usage();
    225         let empty_code = main_with_args(Vec::new());
    226         assert_eq!(empty_code, ExitCode::from(2));
    227         let success_code = main_with_args(vec!["coverage".to_string(), "help".to_string()]);
    228         assert_eq!(success_code, ExitCode::SUCCESS);
    229         let failure_code = main_with_args(vec!["unknown".to_string()]);
    230         assert_eq!(failure_code, ExitCode::from(2));
    231         let _ = main();
    232     }
    233 
    234     #[test]
    235     fn run_contract_dispatches_validate_command() {
    236         let _guard = lock_workspace();
    237         run_contract(&["validate".to_string()]).expect("contract validate");
    238     }
    239 }