use super::*;
use crate::config::RawConfig;
fn config(root: &std::path::Path, guard: &str) -> Config {
let raw: RawConfig = toml::from_str(&format!("[[guards]]\n{guard}")).unwrap();
Config::from_raw(root.to_path_buf(), raw, false)
}
#[test]
fn scans_tree() {
let tmp = tempfile::tempdir().unwrap();
let r = tmp.path();
std::fs::create_dir_all(r.join("libs/open/src")).unwrap();
std::fs::create_dir_all(r.join("services/shop")).unwrap();
let fake_key = format!("{}{}", "AK", "IA".to_string() + &"X".repeat(16));
std::fs::write(r.join("libs/open/src/a.rs"), format!("// built for Acme-Internal\nlet k = \"{fake_key}\";\n"))
.unwrap();
std::fs::write(r.join("libs/open/.env"), "X=1\n").unwrap();
std::fs::write(r.join("services/shop/b.rs"), "acme-internal is fine here\n").unwrap();
std::fs::write(r.join("terms.txt"), "# private\nacme-internal\n").unwrap();
let cfg = config(
r,
"name = \"public\"\npaths = [\"libs/open/**\"]\nrange = \"all\"\ndeny_terms_file = \"terms.txt\"\ndeny_files = [\"**/.env*\"]\nsecrets = true\n",
);
let mut f = run(&cfg, &[], None).unwrap();
f.sort_by_key(|a| (a.path.clone(), a.line));
let got: Vec<(String, usize)> = f.iter().map(|x| (x.path.clone(), x.line)).collect();
assert_eq!(
got,
[
("libs/open/.env".to_string(), 1),
("libs/open/src/a.rs".to_string(), 1),
("libs/open/src/a.rs".to_string(), 2)
]
);
assert!(!f[1].message.contains("acme-internal"));
}
#[test]
fn patterns_skip_urls_exemptions_and_allowed_text() {
let tmp = tempfile::tempdir().unwrap();
let r = tmp.path();
std::fs::create_dir_all(r.join("pub/docs")).unwrap();
std::fs::write(
r.join("pub/a.md"),
"see https://example.com/internal/x\ninternal/build.sh\nthe internal/README example\n",
)
.unwrap();
std::fs::write(r.join("pub/docs/b.md"), "internal/build.sh\n").unwrap();
let cfg = config(
r,
"name = \"g\"\npaths = [\"pub/**\"]\nrange = \"all\"\nallow = [\"internal/readme\"]\n[[guards.deny_regex]]\nre = 'internal/[a-z.]+'\nlabel = \"internal path\"\nnot_in_url = true\nexempt = [\"pub/docs/**\"]\nmust_hit = [\"run internal/build.sh\"]\nmust_pass = [\"https://example.com/internal/x\"]\n",
);
let f = run(&cfg, &[], None).unwrap();
let got: Vec<(String, usize)> = f.iter().map(|x| (x.path.clone(), x.line)).collect();
assert_eq!(got, [("pub/a.md".to_string(), 2)], "{f:?}");
assert!(f[0].message.contains("internal path"));
}
#[test]
fn a_fixture_that_no_longer_holds_stops_the_run() {
let tmp = tempfile::tempdir().unwrap();
let cfg = config(
tmp.path(),
"name = \"g\"\nrange = \"all\"\n[[guards.deny_regex]]\nre = 'secret-[0-9]+'\nmust_hit = [\"secret-abc\"]\n",
);
let e = run(&cfg, &[], None).unwrap_err().to_string();
assert!(e.contains("does not match its must_hit fixture"), "{e}");
}
#[test]
fn a_whole_tree_run_over_nothing_fails_and_gzip_is_read() {
use std::io::Write;
let tmp = tempfile::tempdir().unwrap();
let r = tmp.path();
let none = config(r, "name = \"g\"\npaths = [\"missing/**\"]\nrange = \"all\"\ndeny_terms = [\"x\"]\n");
assert!(run(&none, &[], None).unwrap()[0].message.contains("scanned no file"));
std::fs::create_dir_all(r.join("pkg")).unwrap();
let mut gz = flate2::write::GzEncoder::new(vec![], flate2::Compression::default());
gz.write_all(b"hello acme-internal\n").unwrap();
std::fs::write(r.join("pkg/a.txt.gz"), gz.finish().unwrap()).unwrap();
let cfg = config(
r,
"name = \"g\"\npaths = [\"pkg/**\"]\nrange = \"all\"\ndeny_terms = [\"acme-internal\"]\ndecompress = true\n",
);
assert_eq!(run(&cfg, &[], None).unwrap().len(), 1);
}
#[test]
fn an_empty_or_missing_published_path_is_a_hit() {
let tmp = tempfile::tempdir().unwrap();
let r = tmp.path();
std::fs::create_dir_all(r.join("pub/full")).unwrap();
std::fs::create_dir_all(r.join("pub/empty")).unwrap();
std::fs::write(r.join("pub/full/a.md"), "fine\n").unwrap();
let raw: RawConfig = toml::from_str(
"[public]\npaths = [\"pub/full\", \"pub/empty\", \"pub/gone\"]\n[[guards]]\nname = \"g\"\npublic = true\nrange = \"all\"\ndeny_terms = [\"x-internal\"]\n",
)
.unwrap();
let cfg = Config::from_raw(r.to_path_buf(), raw, false);
let mut got: Vec<(String, bool)> =
run(&cfg, &[], None).unwrap().into_iter().map(|f| (f.path, f.message.contains("not present"))).collect();
got.sort();
assert_eq!(got, [("pub/empty".to_string(), false), ("pub/gone".to_string(), true)]);
}