use clap::Parser;
use keyhog::args::{Cli, ScanArgs};
use keyhog::baseline::Baseline;
use keyhog::benchmark::format_gpu_summary;
use keyhog::config::find_config_file;
#[cfg(unix)]
use keyhog::daemon::default_socket_path;
#[cfg(unix)]
use keyhog::daemon::protocol::{Request, Response, MAX_FRAME_BYTES, WIRE_VERSION};
use keyhog::inline_suppression::filter_inline_suppressions;
use keyhog::path_validation::validate_cli_path_arg;
use keyhog::reporting::report_findings;
use keyhog::test_fixture_suppressions::TestFixtureSuppressions;
use keyhog::value_parsers::{parse_decode_depth, parse_min_confidence};
use keyhog_core::{MatchLocation, RawMatch, Severity};
use std::sync::Arc;
#[test]
fn lib_happy() {
assert_eq!(
keyhog::SCANNED_CHUNKS.load(std::sync::atomic::Ordering::Relaxed),
0
);
}
#[test]
fn lib_error() {
assert!(!keyhog::SCANNER_PANICKED.load(std::sync::atomic::Ordering::Relaxed));
}
#[test]
fn main_happy() {
let cli = Cli::try_parse_from(["keyhog", "--version"]).unwrap();
assert!(cli.version);
}
#[test]
fn main_error() {
assert!(Cli::try_parse_from(["keyhog", "--bad-flag"]).is_err());
}
#[test]
fn args_happy() {
let args = ScanArgs::try_parse_from(["scan", "."]).unwrap();
assert_eq!(args.input.as_deref(), Some(std::path::Path::new(".")));
}
#[test]
fn args_error() {
assert!(ScanArgs::try_parse_from(["scan", "--min-confidence", "not-a-float"]).is_err());
}
#[test]
fn baseline_happy() {
let baseline = Baseline::from_findings(&[]);
assert!(baseline.entries.is_empty());
}
#[test]
fn baseline_error() {
assert!(Baseline::load(std::path::Path::new("/nonexistent/baseline.json")).is_err());
}
#[test]
fn benchmark_happy() {
assert!(!format_gpu_summary().is_empty());
}
#[test]
fn config_happy() {
let dir = tempfile::tempdir().unwrap();
assert!(find_config_file(Some(dir.path())).is_none());
}
#[test]
fn config_error() {
assert!(find_config_file(Some(std::path::Path::new("/nonexistent"))).is_none());
}
#[cfg(unix)]
#[test]
fn daemon_mod_happy() {
let path = default_socket_path();
assert!(!path.as_os_str().is_empty());
}
#[cfg(unix)]
#[test]
fn daemon_client_happy() {
let path = default_socket_path();
assert!(path.to_string_lossy().contains("keyhog") || path.ends_with(".sock"));
}
#[cfg(unix)]
#[test]
fn daemon_frame_happy() {
let json = serde_json::to_string(&Request::Hello).unwrap();
assert!(json.contains("hello"));
}
#[cfg(unix)]
#[test]
fn daemon_frame_error() {
let json = serde_json::to_string(&Response::Hello {
wire_version: WIRE_VERSION,
keyhog_version: "0.0.0".into(),
detector_count: 0,
uptime_secs: 0,
})
.unwrap();
assert!(json.contains("wire_version"));
}
#[cfg(unix)]
#[test]
fn daemon_protocol_happy() {
assert_eq!(WIRE_VERSION, 2);
}
#[cfg(unix)]
#[test]
fn daemon_protocol_error() {
assert!(MAX_FRAME_BYTES > 0);
}
#[cfg(unix)]
#[test]
fn daemon_server_happy() {
let path = default_socket_path();
assert!(!path.as_os_str().is_empty());
}
#[cfg(unix)]
#[test]
fn daemon_server_error() {
assert_ne!(WIRE_VERSION, 0);
}
#[test]
fn inline_suppression_happy() {
let m = RawMatch {
detector_id: Arc::from("demo"),
detector_name: Arc::from("Demo"),
service: Arc::from("demo"),
severity: Severity::Low,
credential: Arc::from("abc"),
credential_hash: [7u8; 32],
companions: Default::default(),
location: MatchLocation {
source: Arc::from("stdin"),
file_path: None,
line: None,
offset: 0,
commit: None,
author: None,
date: None,
},
entropy: None,
confidence: None,
};
assert_eq!(filter_inline_suppressions(vec![m]).len(), 1);
}
#[test]
fn inline_suppression_error() {
assert!(filter_inline_suppressions(vec![]).is_empty());
}
#[test]
fn orchestrator_happy() {
assert!(!format_gpu_summary().is_empty());
}
#[test]
fn orchestrator_error() {
assert!(
validate_cli_path_arg(std::path::Path::new("/nonexistent/keyhog-path"), "scan").is_err()
);
}
#[test]
fn orchestrator_config_happy() {
let args = ScanArgs::try_parse_from(["scan", ".", "--fast"]).unwrap();
assert!(args.fast);
}
#[test]
fn path_validation_error() {
assert!(
validate_cli_path_arg(std::path::Path::new("/nonexistent/keyhog-path"), "scan").is_err()
);
}
#[test]
fn reporting_error() {
let args = ScanArgs::try_parse_from(["scan", ".", "--output", "/"]).unwrap();
assert!(report_findings(&[], &args).is_err());
}
#[test]
fn sources_error() {
let args = ScanArgs::try_parse_from(["scan", "--path", "/nonexistent/keyhog-path"]).unwrap();
assert!(keyhog::sources::build_sources(&args, vec![], None).is_err());
}
#[test]
fn subcommands_mod_happy() {
let cli = Cli::try_parse_from(["keyhog", "scan", "."]).unwrap();
assert!(matches!(cli.command, Some(keyhog::args::Command::Scan(_))));
}
#[test]
fn subcommands_mod_error() {
assert!(Cli::try_parse_from(["keyhog", "not-a-command"]).is_err());
}
#[test]
fn subcommands_backend_error() {
assert!(Cli::try_parse_from(["keyhog", "backend", "--not-real"]).is_err());
}
#[test]
fn subcommands_calibrate_error() {
assert!(Cli::try_parse_from(["keyhog", "calibrate", "--not-real"]).is_err());
}
#[test]
fn subcommands_completion_error() {
assert!(Cli::try_parse_from(["keyhog", "completion"]).is_err());
}
#[test]
fn subcommands_daemon_error() {
assert!(Cli::try_parse_from(["keyhog", "daemon", "not-a-sub"]).is_err());
}
#[test]
fn subcommands_detectors_error() {
assert!(Cli::try_parse_from(["keyhog", "detectors", "--not-real"]).is_err());
}
#[test]
fn subcommands_diff_happy() {
let dir = tempfile::tempdir().unwrap();
let a = dir.path().join("a.json");
let b = dir.path().join("b.json");
std::fs::write(&a, b"[]").unwrap();
std::fs::write(&b, b"[]").unwrap();
assert!(
Cli::try_parse_from(["keyhog", "diff", a.to_str().unwrap(), b.to_str().unwrap()]).is_ok()
);
}
#[test]
fn subcommands_diff_error() {
assert!(Cli::try_parse_from(["keyhog", "diff", "--not-real"]).is_err());
}
#[test]
fn subcommands_explain_error() {
assert!(Cli::try_parse_from(["keyhog", "explain"]).is_err());
}
#[test]
fn subcommands_hook_error() {
assert!(Cli::try_parse_from(["keyhog", "hook"]).is_err());
}
#[test]
fn subcommands_scan_error() {
assert!(Cli::try_parse_from(["keyhog", "scan", "--min-confidence", "bad"]).is_err());
}
#[test]
fn subcommands_scan_system_error() {
assert!(Cli::try_parse_from(["keyhog", "scan-system", "--not-real"]).is_err());
}
#[test]
fn subcommands_watch_error() {
assert!(Cli::try_parse_from(["keyhog", "watch", "--not-real"]).is_err());
}
#[test]
fn test_fixture_suppressions_happy() {
let s = TestFixtureSuppressions::bundled();
assert!(s.exact_count() >= 1);
}
#[test]
fn test_fixture_suppressions_error() {
let s = TestFixtureSuppressions::empty();
assert!(!s.suppresses("sk_live_realistic_token_value"));
}
#[test]
fn value_parsers_happy() {
assert_eq!(parse_min_confidence("0.5").unwrap(), 0.5);
}
#[test]
fn value_parsers_error() {
assert!(parse_decode_depth("not-a-number").is_err());
}