use std::process::Command; fn command() -> Command { Command::new(env!("CARGO_BIN_EXE_panda-rpki")) } #[test] fn top_level_help_and_version_are_successful() { for args in [vec!["--help"], vec!["-h"], vec!["--version"], vec!["-V"]] { let result = command().args(args).output().unwrap(); assert!(result.status.success()); assert!(String::from_utf8_lossy(&result.stdout).contains("panda-rpki")); assert!(result.stderr.is_empty()); } } #[test] fn subcommand_help_does_not_read_a_config() { for mode in ["validate", "daemon"] { let result = command() .args([mode, "--help", "--config", "missing.toml"]) .output() .unwrap(); assert!(result.status.success()); assert!(String::from_utf8_lossy(&result.stdout).contains("--config FILE")); assert!(result.stderr.is_empty()); } } #[test] fn missing_config_and_removed_options_are_rejected_without_outputs() { let directory = tempfile::tempdir().unwrap(); for args in [ vec!["validate"], vec!["validate", "--tal", "input.tal"], vec!["daemon", "--state-root", "data"], vec!["validate", "--config", "missing.toml", "--unknown"], ] { let result = command() .current_dir(directory.path()) .args(args) .output() .unwrap(); assert_eq!(result.status.code(), Some(2)); assert!(result.stdout.is_empty()); assert!(String::from_utf8_lossy(&result.stderr).contains("panda-rpki:")); assert_eq!(std::fs::read_dir(directory.path()).unwrap().count(), 0); } } #[test] fn check_config_is_read_only_for_invalid_inputs() { let directory = tempfile::tempdir().unwrap(); std::fs::write( directory.path().join("validate.toml"), r#" config-version = 1 mode = "validate" out = "output" [[anchors]] id = "missing" tal = "missing.tal" "#, ) .unwrap(); let result = command() .current_dir(directory.path()) .args(["validate", "--config", "validate.toml", "--check-config"]) .output() .unwrap(); assert_eq!(result.status.code(), Some(2)); assert!(!directory.path().join("output").exists()); let result = command() .current_dir(directory.path()) .args(["validate", "--config", "validate.toml", "--print-config"]) .output() .unwrap(); assert_eq!(result.status.code(), Some(2)); assert!(!directory.path().join("output").exists()); } #[test] fn config_mode_and_mutually_exclusive_inspection_flags_are_rejected() { let result = command() .args(["validate", "--check-config", "--print-config"]) .output() .unwrap(); assert_eq!(result.status.code(), Some(2)); assert!(String::from_utf8_lossy(&result.stderr).contains("mutually exclusive")); } #[test] fn all5_examples_load_vendored_constraints_and_disable_ignores_missing_files() { let directory = tempfile::tempdir().unwrap(); let repo = std::path::Path::new(env!("CARGO_MANIFEST_DIR")); for (mode, example) in [ ("validate", "validate-all5.toml"), ("daemon", "daemon-all5.toml"), ] { let raw = std::fs::read_to_string(repo.join("docker/examples").join(example)) .unwrap() .replace("/input", repo.join("tals").to_str().unwrap()) .replace("/output", directory.path().join("out").to_str().unwrap()) .replace("/state", directory.path().join("state").to_str().unwrap()) .replace("/data", directory.path().join("data").to_str().unwrap()); let config = directory.path().join(example); for (enabled, missing, expected) in [(true, false, 0), (true, true, 2), (false, true, 0)] { let mut text = raw.replace( "ta-constraints-enabled = true", &format!("ta-constraints-enabled = {enabled}"), ); if missing { text = text.replace(".constraints\"", ".missing\""); } std::fs::write(&config, text).unwrap(); for inspect in ["--check-config", "--print-config"] { let result = command() .args([mode, "--config", config.to_str().unwrap(), inspect]) .output() .unwrap(); assert_eq!( result.status.code(), Some(expected), "{}", String::from_utf8_lossy(&result.stderr) ); if inspect == "--print-config" && expected == 0 { let printed: serde_json::Value = serde_json::from_slice(&result.stdout).unwrap(); assert_eq!(printed["effective"]["ta-constraints-enabled"], enabled); } } } assert!(!directory.path().join("out").exists()); assert!(!directory.path().join("data").exists()); } }