#![cfg(feature = "full")]
#![allow(clippy::expect_used, clippy::unwrap_used)]
use clawdstrike::{ForbiddenPathGuard, SecretLeakGuard};
use proptest::prelude::*;
proptest! {
#[test]
fn forbidden_path_no_panic(path in ".*") {
let guard = ForbiddenPathGuard::new();
let _ = guard.is_forbidden(&path);
}
#[test]
fn forbidden_path_deterministic(path in ".*") {
let guard = ForbiddenPathGuard::new();
let r1 = guard.is_forbidden(&path);
let r2 = guard.is_forbidden(&path);
prop_assert_eq!(r1, r2);
}
#[test]
fn safe_paths_allowed(
prefix in "[a-z]{1,10}",
name in "[a-z0-9_]{1,20}",
ext in "[a-z]{1,4}",
) {
prop_assume!(prefix != "pass");
prop_assume!(ext != "reg");
prop_assume!(!name.starts_with("id_rsa"));
prop_assume!(!name.starts_with("id_ed25519"));
prop_assume!(!name.starts_with("id_ecdsa"));
let path = format!("/tmp/{prefix}/{name}.{ext}");
let guard = ForbiddenPathGuard::new();
prop_assert!(!guard.is_forbidden(&path));
}
#[test]
fn ssh_paths_forbidden(
user in "[a-z]{1,10}",
file in "(id_rsa|id_ed25519|authorized_keys|known_hosts)",
) {
let path = format!("/home/{user}/.ssh/{file}");
let guard = ForbiddenPathGuard::new();
prop_assert!(guard.is_forbidden(&path));
}
#[test]
fn aws_paths_forbidden(
user in "[a-z]{1,10}",
file in "(credentials|config)",
) {
let path = format!("/home/{user}/.aws/{file}");
let guard = ForbiddenPathGuard::new();
prop_assert!(guard.is_forbidden(&path));
}
#[test]
fn secret_leak_no_panic(content in prop::collection::vec(any::<u8>(), 0..1000)) {
let guard = SecretLeakGuard::new();
let _ = guard.scan(&content);
}
#[test]
fn secret_leak_deterministic(content in prop::collection::vec(any::<u8>(), 0..500)) {
let guard = SecretLeakGuard::new();
let r1 = guard.scan(&content);
let r2 = guard.scan(&content);
prop_assert_eq!(r1.len(), r2.len());
}
#[test]
fn aws_keys_detected(
suffix in "[A-Z0-9]{16}",
) {
let content = format!("key = AKIA{suffix}");
let guard = SecretLeakGuard::new();
let matches = guard.scan(content.as_bytes());
prop_assert!(!matches.is_empty());
}
#[test]
fn github_tokens_detected(
suffix in "[A-Za-z0-9]{36}",
) {
let content = format!("token: ghp_{suffix}");
let guard = SecretLeakGuard::new();
let matches = guard.scan(content.as_bytes());
prop_assert!(!matches.is_empty());
}
#[test]
fn normal_code_no_secrets(
fn_name in "[a-z_]{1,20}",
var_name in "[a-z_]{1,10}",
value in "[0-9]{1,5}",
) {
let content = format!("fn {fn_name}() {{ let {var_name} = {value}; }}");
let guard = SecretLeakGuard::new();
let matches = guard.scan(content.as_bytes());
prop_assert!(matches.is_empty());
}
}