use keyhog_core::{Chunk, ChunkMetadata, RawMatch};
use keyhog_scanner::{CompiledScanner, ScanBackend};
use std::collections::BTreeSet;
use std::sync::OnceLock;
use crate::support::paths::detector_dir;
fn scanner() -> &'static CompiledScanner {
static SCANNER: OnceLock<CompiledScanner> = OnceLock::new();
SCANNER.get_or_init(|| {
let detectors = keyhog_core::load_detectors(&detector_dir())
.expect("detector corpus must load from on-disk TOMLs");
CompiledScanner::compile(detectors).expect("detector corpus must compile")
})
}
fn chunk(text: &str, path: &str, base_offset: usize) -> Chunk {
Chunk {
data: text.into(),
metadata: ChunkMetadata {
source_type: "gap-backend-parity".into(),
path: Some(path.into()),
base_offset,
..Default::default()
},
}
}
type Key = (String, String, usize);
fn key_set(matches: &[RawMatch]) -> BTreeSet<Key> {
matches
.iter()
.map(|m| {
(
m.detector_id.as_ref().to_string(),
m.credential.as_ref().to_string(),
m.location.offset,
)
})
.collect()
}
fn flat_key_set(per_chunk: &[Vec<RawMatch>]) -> BTreeSet<Key> {
per_chunk
.iter()
.flat_map(|c| c.iter())
.map(|m| {
(
m.detector_id.as_ref().to_string(),
m.credential.as_ref().to_string(),
m.location.offset,
)
})
.collect()
}
const CPU_BACKENDS: [ScanBackend; 2] = [ScanBackend::SimdCpu, ScanBackend::CpuFallback];
const AWS_KEY: &str = "AKIAQYLPMN5HFIQR7BBB"; const GH_PAT: &str =
"github_pat_ABCDEFGHIJKLMNOPQRSTUV_abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQ0qzktM";
const SENDGRID: &str = "SG.AbCdEfGhIjKlMnOpQrStUv.A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0UvW";
const SLACK_BOT: &str = "xoxb-1234567890-1234567890-abcdefghijklmnopqrstuvwx";
const STRIPE_LIVE: &str = "sk_live_4eC39HqLyjWDarjtT1zdp7dc";
#[test]
fn aws_key_same_finding_set_simd_and_cpu() {
let c = chunk(
&format!("const AWS_ACCESS_KEY_ID = \"{AWS_KEY}\";\n"),
"config.rs",
0,
);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert_eq!(
simd, cpu,
"SimdCpu and CpuFallback must emit the identical finding set for an AWS key"
);
assert!(
simd.iter()
.any(|(id, cred, _)| id == "aws-access-key" && cred == AWS_KEY),
"expected aws-access-key={AWS_KEY} in {simd:?}"
);
}
#[test]
fn github_pat_same_finding_set_simd_and_cpu() {
let c = chunk(&format!("token: {GH_PAT}\n"), "ci.yml", 0);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert_eq!(simd, cpu, "GitHub fine-grained PAT parity broke");
assert!(
simd.iter()
.any(|(id, cred, _)| id == "github-pat-fine-grained" && cred == GH_PAT),
"expected github-pat-fine-grained={GH_PAT} in {simd:?}"
);
}
#[test]
fn sendgrid_same_finding_set_simd_and_cpu() {
let c = chunk(&format!("SENDGRID_API_KEY={SENDGRID}\n"), "app.env", 0);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert_eq!(simd, cpu, "SendGrid key parity broke");
assert!(
simd.iter()
.any(|(id, cred, _)| id == "sendgrid-api-key" && cred == SENDGRID),
"expected sendgrid-api-key={SENDGRID} in {simd:?}"
);
}
#[test]
fn slack_bot_same_finding_set_simd_and_cpu() {
let c = chunk(
&format!("SLACK_BOT_TOKEN = '{SLACK_BOT}'\n"),
"settings.py",
0,
);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert_eq!(simd, cpu, "Slack bot token parity broke");
assert!(
simd.iter()
.any(|(id, cred, _)| id == "slack-bot-token" && cred == SLACK_BOT),
"expected slack-bot-token={SLACK_BOT} in {simd:?}"
);
}
#[test]
fn stripe_same_finding_set_simd_and_cpu() {
let c = chunk(
&format!("stripe_key = \"{STRIPE_LIVE}\"\n"),
"billing.rb",
0,
);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert_eq!(simd, cpu, "Stripe live key parity broke");
assert!(
simd.iter()
.any(|(id, cred, _)| id == "stripe-secret-key" && cred == STRIPE_LIVE),
"expected stripe-secret-key={STRIPE_LIVE} in {simd:?}"
);
}
#[test]
fn multi_secret_corpus_same_finding_set_simd_and_cpu() {
let text = format!(
"aws = \"{AWS_KEY}\"\n\
gh: {GH_PAT}\n\
SENDGRID_API_KEY={SENDGRID}\n\
slack = '{SLACK_BOT}'\n\
stripe_secret = \"{STRIPE_LIVE}\"\n"
);
let c = chunk(&text, "secrets.env", 0);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert_eq!(
simd,
cpu,
"multi-secret corpus finding-set diverged between SimdCpu and CpuFallback:\n\
only-in-simd={:?}\n only-in-cpu={:?}",
simd.difference(&cpu).collect::<Vec<_>>(),
cpu.difference(&simd).collect::<Vec<_>>()
);
for (id, cred) in [
("aws-access-key", AWS_KEY),
("github-pat-fine-grained", GH_PAT),
("sendgrid-api-key", SENDGRID),
("slack-bot-token", SLACK_BOT),
("stripe-secret-key", STRIPE_LIVE),
] {
assert!(
simd.iter().any(|(i, c, _)| i == id && c == cred),
"expected {id}={cred} in shared finding set {simd:?}"
);
}
}
#[test]
fn negative_twin_no_secret_both_backends_empty() {
let c = chunk(
"fn compute_total(items: &[Item]) -> u64 { items.iter().map(|i| i.qty).sum() }\n",
"math.rs",
0,
);
let simd = scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds");
let cpu = scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds");
assert!(
simd.is_empty(),
"plain code must yield zero findings on SimdCpu, got {}",
simd.len()
);
assert_eq!(
key_set(&simd),
key_set(&cpu),
"empty-set parity broke on plain code"
);
}
#[test]
fn wrong_prefix_negative_twin_both_backends_silent() {
let c = chunk("key = \"AKIBQYLPMN5HFIQR7BBB\"\n", "cfg.env", 0);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert!(
!simd.iter().any(|(id, _, _)| id == "aws-access-key"),
"AKIB prefix must NOT match aws-access-key, got {simd:?}"
);
assert_eq!(simd, cpu, "wrong-prefix negative-twin parity broke");
}
#[test]
fn aws_case_evasion_lowercase_silent_both_backends() {
let c = chunk("akiaqylpmn5hfiqr7bbb placeholder\n", "readme.md", 0);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert!(
!simd.iter().any(|(id, _, _)| id == "aws-access-key"),
"lowercase akia must not match case-sensitive aws regex, got {simd:?}"
);
assert_eq!(simd, cpu, "case-evasion negative parity broke");
}
#[test]
fn repeated_secret_offsets_identical_across_backends() {
let text = format!("a=\"{AWS_KEY}\"\nb=\"{AWS_KEY}\"\n");
let c = chunk(&text, "two.env", 0);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert_eq!(simd, cpu, "two-key offset parity broke");
let aws_offsets: BTreeSet<usize> = simd
.iter()
.filter(|(id, cred, _)| id == "aws-access-key" && cred == AWS_KEY)
.map(|(_, _, off)| *off)
.collect();
let first_off = 3usize;
let second_off = 3 + AWS_KEY.len() + 2 + 3 ;
assert!(
aws_offsets.contains(&first_off),
"first AWS key must start at byte offset {first_off}, got {aws_offsets:?}"
);
assert!(
aws_offsets.contains(&second_off),
"second AWS key must start at byte offset {second_off}, got {aws_offsets:?}"
);
}
#[test]
fn entropy_fallback_finding_set_backend_invariant() {
let token = "Zk9Qw3Rt7Yx2Mn5Bv8Cs1Lp4Df6Gh0Jk3Wq7Er2Ty9Ui4Op6A";
let c = chunk(&format!("api_key = \"{token}\"\n"), "service.env", 0);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert_eq!(
simd,
cpu,
"entropy fallback must be backend-invariant:\n only-simd={:?}\n only-cpu={:?}",
simd.difference(&cpu).collect::<Vec<_>>(),
cpu.difference(&simd).collect::<Vec<_>>()
);
}
#[test]
fn entropy_source_file_gate_parity() {
let token = "Zk9Qw3Rt7Yx2Mn5Bv8Cs1Lp4Df6Gh0Jk3Wq7Er2Ty9Ui4Op6A";
let c = chunk(
&format!("const TABLE: &str = \"{token}\";\n"),
"data_table.rs",
0,
);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert_eq!(simd, cpu, "source-file entropy gate parity broke");
}
#[test]
fn low_entropy_repeated_value_no_entropy_finding_both_backends() {
let c = chunk(
"api_key = \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n",
"low.env",
0,
);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert!(
!simd.iter().any(|(id, _, _)| id.starts_with("entropy-")),
"all-'a' run must not produce an entropy finding, got {simd:?}"
);
assert_eq!(simd, cpu, "low-entropy negative parity broke");
}
#[test]
fn default_scan_matches_a_cpu_backend() {
let c = chunk(
&format!("aws=\"{AWS_KEY}\"\nstripe=\"{STRIPE_LIVE}\"\n"),
"auto.env",
0,
);
let auto = key_set(&scanner().scan(&c).expect("test scan succeeds"));
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert_eq!(simd, cpu, "precondition: CPU backends already diverge");
assert_eq!(
auto, cpu,
"scan() must match the explicit CpuFallback reference finding set"
);
}
#[test]
fn idempotent_rescans_same_backend_same_set() {
let c = chunk(&format!("token: {GH_PAT}\n"), "repeat.yml", 0);
for backend in CPU_BACKENDS {
let first = key_set(
&scanner()
.scan_with_backend(&c, backend)
.expect("selected backend scan succeeds"),
);
let second = key_set(
&scanner()
.scan_with_backend(&c, backend)
.expect("selected backend scan succeeds"),
);
assert_eq!(
first, second,
"{backend:?} re-scan produced a different finding set"
);
}
}
#[test]
fn coalesced_equals_sum_of_per_chunk_scans() {
let chunks = vec![
chunk(&format!("a=\"{AWS_KEY}\"\n"), "a.env", 0),
chunk("// nothing to see here\n", "b.rs", 0),
chunk(&format!("gh={GH_PAT}\n"), "c.yml", 0),
chunk(&format!("s='{SLACK_BOT}'\n"), "d.py", 0),
];
let coalesced = scanner()
.scan_coalesced(&chunks)
.expect("coalesced test scan succeeds");
let coalesced_set = flat_key_set(&coalesced);
let mut per_chunk: BTreeSet<Key> = BTreeSet::new();
for c in &chunks {
per_chunk.extend(key_set(&scanner().scan(c).expect("test scan succeeds")));
}
assert_eq!(
coalesced_set,
per_chunk,
"coalesced batch finding set diverged from per-chunk scans:\n\
only-coalesced={:?}\n only-per-chunk={:?}",
coalesced_set.difference(&per_chunk).collect::<Vec<_>>(),
per_chunk.difference(&coalesced_set).collect::<Vec<_>>()
);
}
#[test]
fn coalesced_result_vector_is_per_chunk_aligned() {
let chunks = vec![
chunk(&format!("a=\"{AWS_KEY}\"\n"), "a.env", 0),
chunk("plain comment\n", "b.rs", 0),
chunk(&format!("s='{SLACK_BOT}'\n"), "c.py", 0),
];
let results = scanner()
.scan_coalesced(&chunks)
.expect("coalesced test scan succeeds");
assert_eq!(
results.len(),
chunks.len(),
"coalesced result vec must be 1:1 with input chunks"
);
assert!(
results[0]
.iter()
.any(|m| m.detector_id.as_ref() == "aws-access-key"),
"chunk 0 must carry the aws-access-key finding in its own slot"
);
assert_eq!(
results[1].len(),
0,
"chunk 1 (no secret) must have an empty result slot, got {}",
results[1].len()
);
assert!(
results[2]
.iter()
.any(|m| m.detector_id.as_ref() == "slack-bot-token"),
"chunk 2 must carry the slack-bot-token finding in its own slot"
);
}
fn split_pair(secret: &str, split_in_secret: usize, path: &str) -> (Chunk, Chunk, usize) {
let pad = "padding_line\n".repeat(8);
let mut a = pad.clone();
a.push_str(&secret[..split_in_secret]);
let len_a = a.len();
let mut b = secret[split_in_secret..].to_string();
b.push('\n');
let ca = chunk(&a, path, 0);
let cb = chunk(&b, path, len_a);
(ca, cb, len_a)
}
#[test]
fn sendgrid_split_reassembled_coalesced() {
let (ca, cb, _len_a) = split_pair(SENDGRID, 18, "split.txt");
let results = scanner()
.scan_coalesced(&[ca, cb])
.expect("coalesced test scan succeeds");
let found = results
.iter()
.flatten()
.any(|m| m.detector_id.as_ref() == "sendgrid-api-key" && m.credential.as_ref() == SENDGRID);
assert!(
found,
"sendgrid key straddling a gapless chunk seam must reassemble via boundary scan"
);
}
#[test]
fn aws_split_reassembled_both_cpu_backends() {
for backend in CPU_BACKENDS {
let (ca, cb, _len_a) = split_pair(AWS_KEY, 8, "aws-split.txt");
let results = scanner()
.scan_chunks_with_backend(&[ca, cb], backend)
.expect("selected backend scan succeeds");
let found = results.iter().flatten().any(|m| {
m.detector_id.as_ref() == "aws-access-key" && m.credential.as_ref() == AWS_KEY
});
assert!(
found,
"{backend:?}: AWS key split across the seam must reassemble"
);
}
}
#[test]
fn boundary_match_attributed_to_right_hand_chunk() {
let (ca, cb, _len_a) = split_pair(SENDGRID, 18, "attrib.txt");
let results = scanner()
.scan_chunks_with_backend(&[ca, cb], ScanBackend::SimdCpu)
.expect("selected backend scan succeeds");
assert_eq!(results.len(), 2, "expected two result slots");
let left_has = results[0]
.iter()
.any(|m| m.detector_id.as_ref() == "sendgrid-api-key" && m.credential.as_ref() == SENDGRID);
let right_has = results[1]
.iter()
.any(|m| m.detector_id.as_ref() == "sendgrid-api-key" && m.credential.as_ref() == SENDGRID);
assert!(
!left_has,
"reassembled boundary finding must NOT land in the left chunk's slot"
);
assert!(
right_has,
"reassembled boundary finding must land in the right chunk's slot"
);
}
#[test]
fn boundary_finding_offset_is_absolute_file_offset() {
let pad = "padding_line\n".repeat(8);
let pad_len = pad.len();
let (ca, cb, _len_a) = split_pair(SENDGRID, 18, "offset.txt");
let results = scanner()
.scan_chunks_with_backend(&[ca, cb], ScanBackend::SimdCpu)
.expect("selected backend scan succeeds");
let m = results
.iter()
.flatten()
.find(|m| m.detector_id.as_ref() == "sendgrid-api-key" && m.credential.as_ref() == SENDGRID)
.expect("sendgrid boundary match must exist");
assert_eq!(
m.location.offset, pad_len,
"boundary match offset must be the absolute file offset of the secret start (after the {pad_len}-byte pad)"
);
}
#[test]
fn overlapping_chunks_not_double_reassembled() {
let pad = "x\n".repeat(8);
let a_text = format!("{pad}{SENDGRID}"); let len_a = a_text.len();
let overlap = 10usize;
let b_text = format!("{}\n", &a_text[len_a - overlap..]);
let ca = chunk(&a_text, "ov.txt", 0);
let cb = chunk(&b_text, "ov.txt", len_a - overlap);
let results = scanner()
.scan_chunks_with_backend(&[ca, cb], ScanBackend::SimdCpu)
.expect("selected backend scan succeeds");
let count = results
.iter()
.flatten()
.filter(|m| {
m.detector_id.as_ref() == "sendgrid-api-key" && m.credential.as_ref() == SENDGRID
})
.count();
assert_eq!(
count, 1,
"overlapping chunks must not double-report the secret (boundary path must skip overlap), got {count}"
);
}
#[test]
fn gapped_chunks_not_reassembled() {
let (ca, _cb, len_a) = split_pair(SENDGRID, 18, "gap.txt");
let mut b = SENDGRID[18..].to_string();
b.push('\n');
let cb_gapped = chunk(&b, "gap.txt", len_a + 100);
let results = scanner()
.scan_chunks_with_backend(&[ca, cb_gapped], ScanBackend::SimdCpu)
.expect("selected backend scan succeeds");
let found = results
.iter()
.flatten()
.any(|m| m.detector_id.as_ref() == "sendgrid-api-key" && m.credential.as_ref() == SENDGRID);
assert!(
!found,
"a secret split across a GAP must not be reassembled (data between chunks is unavailable)"
);
}
#[test]
fn different_file_chunks_not_reassembled() {
let (mut ca, mut cb, _len_a) = split_pair(SENDGRID, 18, "ignored.txt");
ca.metadata.path = Some("file-A.txt".into());
cb.metadata.path = Some("file-B.txt".into());
let results = scanner()
.scan_chunks_with_backend(&[ca, cb], ScanBackend::SimdCpu)
.expect("selected backend scan succeeds");
let found = results
.iter()
.flatten()
.any(|m| m.detector_id.as_ref() == "sendgrid-api-key" && m.credential.as_ref() == SENDGRID);
assert!(
!found,
"secret split across two DIFFERENT files must not be reassembled"
);
}
#[test]
fn single_chunk_no_boundary_scan() {
let (ca, _cb, _len_a) = split_pair(SENDGRID, 18, "solo.txt");
let results = scanner()
.scan_chunks_with_backend(std::slice::from_ref(&ca), ScanBackend::SimdCpu)
.expect("selected backend scan succeeds");
let found = results
.iter()
.flatten()
.any(|m| m.detector_id.as_ref() == "sendgrid-api-key");
assert!(
!found,
"a lone left-half chunk must not produce a sendgrid finding"
);
}
#[test]
fn boundary_does_not_duplicate_fully_contained_secret() {
let secret_line = format!("SENDGRID_API_KEY={SENDGRID}\n");
let ca = chunk(&secret_line, "whole.txt", 0);
let len_a = secret_line.len();
let cb = chunk("trailing content with no secret\n", "whole.txt", len_a);
let results = scanner()
.scan_chunks_with_backend(&[ca, cb], ScanBackend::SimdCpu)
.expect("selected backend scan succeeds");
let count = results
.iter()
.flatten()
.filter(|m| {
m.detector_id.as_ref() == "sendgrid-api-key" && m.credential.as_ref() == SENDGRID
})
.count();
assert_eq!(
count, 1,
"fully-contained secret must be reported exactly once across the seam, got {count}"
);
}
#[test]
fn boundary_recovers_under_both_coalesced_and_dispatch() {
let (ca1, cb1, _l1) = split_pair(AWS_KEY, 8, "dual.txt");
let coalesced = scanner()
.scan_coalesced(&[ca1, cb1])
.expect("coalesced test scan succeeds");
let via_coalesced = coalesced
.iter()
.flatten()
.any(|m| m.detector_id.as_ref() == "aws-access-key" && m.credential.as_ref() == AWS_KEY);
let (ca2, cb2, _l2) = split_pair(AWS_KEY, 8, "dual.txt");
let dispatched = scanner()
.scan_chunks_with_backend(&[ca2, cb2], ScanBackend::CpuFallback)
.expect("selected backend scan succeeds");
let via_dispatch = dispatched
.iter()
.flatten()
.any(|m| m.detector_id.as_ref() == "aws-access-key" && m.credential.as_ref() == AWS_KEY);
assert!(
via_coalesced,
"coalesced path must recover the split AWS key"
);
assert!(via_dispatch, "dispatch path must recover the split AWS key");
}
#[test]
fn fixed_corpus_differential_all_cpu_backends_agree() {
let token = "Zk9Qw3Rt7Yx2Mn5Bv8Cs1Lp4Df6Gh0Jk3Wq7Er2Ty9Ui4Op6A";
let corpus = format!(
"# config\n\
AWS_ACCESS_KEY_ID = {AWS_KEY}\n\
let unrelated = compute_things(42);\n\
GITHUB_TOKEN: {GH_PAT}\n\
// a comment line\n\
sendgrid: {SENDGRID}\n\
api_key = \"{token}\"\n\
slack_bot = '{SLACK_BOT}'\n\
stripe = \"{STRIPE_LIVE}\"\n"
);
let c = chunk(&corpus, "mixed.env", 0);
let mut sets: Vec<BTreeSet<Key>> = Vec::new();
for backend in CPU_BACKENDS {
sets.push(key_set(
&scanner()
.scan_with_backend(&c, backend)
.expect("selected backend scan succeeds"),
));
}
assert_eq!(
sets[0],
sets[1],
"fixed-corpus finding set must be identical across SimdCpu and CpuFallback:\n\
only-simd={:?}\n only-cpu={:?}",
sets[0].difference(&sets[1]).collect::<Vec<_>>(),
sets[1].difference(&sets[0]).collect::<Vec<_>>()
);
for (id, cred) in [
("aws-access-key", AWS_KEY),
("github-pat-fine-grained", GH_PAT),
("sendgrid-api-key", SENDGRID),
("slack-bot-token", SLACK_BOT),
("stripe-secret-key", STRIPE_LIVE),
] {
assert!(
sets[0].iter().any(|(i, c, _)| i == id && c == cred),
"expected {id}={cred} in the agreed finding set"
);
}
}
#[test]
fn detector_ids_and_severities_match_toml_truth() {
let c = chunk(
&format!("aws={AWS_KEY}\nstripe={STRIPE_LIVE}\nslack={SLACK_BOT}\n"),
"ids.env",
0,
);
for backend in CPU_BACKENDS {
let matches = scanner()
.scan_with_backend(&c, backend)
.expect("selected backend scan succeeds");
let ids: BTreeSet<&str> = matches.iter().map(|m| m.detector_id.as_ref()).collect();
assert!(
ids.contains("aws-access-key"),
"{backend:?}: missing aws-access-key id, got {ids:?}"
);
assert!(
ids.contains("stripe-secret-key"),
"{backend:?}: missing stripe-secret-key id, got {ids:?}"
);
assert!(
ids.contains("slack-bot-token"),
"{backend:?}: missing slack-bot-token id, got {ids:?}"
);
}
}
struct XorShift(u64);
impl XorShift {
fn next_u64(&mut self) -> u64 {
let mut x = self.0;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
self.0 = x;
x
}
}
#[test]
fn property_random_benign_text_never_diverges_between_backends() {
let mut rng = XorShift(0x9E3779B97F4A7C15);
let alphabet: &[u8] =
b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 _=/.\n\"'";
for iter in 0..200u32 {
let len = 16 + (rng.next_u64() as usize % 240);
let mut s = String::with_capacity(len);
for _ in 0..len {
let b = alphabet[(rng.next_u64() as usize) % alphabet.len()];
s.push(b as char);
}
let c = chunk(&s, "rand.txt", 0);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert_eq!(
simd,
cpu,
"backend divergence on random input (iter {iter}):\n input={s:?}\n \
only-simd={:?}\n only-cpu={:?}",
simd.difference(&cpu).collect::<Vec<_>>(),
cpu.difference(&simd).collect::<Vec<_>>()
);
}
}
#[test]
fn property_planted_aws_keys_recovered_by_both_backends() {
let mut rng = XorShift(0xDEADBEEFCAFEF00D);
for iter in 0..60u32 {
let pre_len = rng.next_u64() as usize % 120;
let mut s = String::new();
for _ in 0..pre_len {
s.push((b'a' + (rng.next_u64() as u8 % 26)) as char);
}
s.push_str(" key=\"");
let plant_off = s.len();
s.push_str(AWS_KEY);
s.push_str("\"\n");
let c = chunk(&s, "plant.env", 0);
let simd = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::SimdCpu)
.expect("selected backend scan succeeds"),
);
let cpu = key_set(
&scanner()
.scan_with_backend(&c, ScanBackend::CpuFallback)
.expect("selected backend scan succeeds"),
);
assert_eq!(
simd, cpu,
"planted-key parity broke (iter {iter}): input={s:?}"
);
assert!(
simd.contains(&("aws-access-key".to_string(), AWS_KEY.to_string(), plant_off)),
"iter {iter}: planted AWS key at offset {plant_off} not recovered; got {simd:?}"
);
}
}