const LIB_SOURCE: &str = include_str!("../src/lib.rs");
#[test]
fn exactly_five_public_functions() {
let allowed: std::collections::BTreeSet<String> =
["compile", "commit", "prove", "verify", "open"]
.iter()
.map(|s| s.to_string())
.collect();
let public_fns = public_fn_names(LIB_SOURCE);
assert_eq!(
public_fns, allowed,
"\nPublic function set does not match the frozen contract.\
\n Expected: {allowed:?}\
\n Found: {public_fns:?}\
\n\nIf you added a function, it must NOT be `pub`.\
\nIf you renamed one, update the frozen contract in FREEZE.md first.",
);
}
#[test]
fn zero_public_types_or_reexports() {
let production = strip_cfg_test(LIB_SOURCE);
let forbidden_prefixes = [
"pub struct ",
"pub enum ",
"pub trait ",
"pub const ",
"pub static ",
"pub type ",
"pub use ",
"pub mod ",
];
let mut violations = Vec::new();
for (i, line) in production.lines().enumerate() {
let trimmed = line.trim();
if trimmed.starts_with("//") || trimmed.starts_with("///") || trimmed.starts_with("#") {
continue;
}
for prefix in &forbidden_prefixes {
if trimmed.starts_with(prefix) {
violations.push(format!(" line {}: {trimmed}", i + 1));
}
}
}
assert!(
violations.is_empty(),
"\nForbidden public items found in lib.rs (production code):\n{}\n\
\nThe façade must expose exactly 5 `pub fn` and nothing else.\
\nIf this is intentional, update FREEZE.md and SECURITY_CHECKLIST.md first.",
violations.join("\n"),
);
}
#[test]
fn byte_array_round_trip() {
let blueprint: Vec<u8> =
qssm_api::compile("age-gate-21").expect("compile should succeed for age-gate-21");
let claim = br#"{"claim":{"age_years":30}}"#;
let salt = [99u8; 32];
let proof: Vec<u8> =
qssm_api::prove(claim, &salt, &blueprint).expect("prove should succeed for valid claim");
let ok: bool = qssm_api::verify(&proof, &blueprint);
assert!(ok, "valid proof must verify");
let secret = b"some-secret";
let commitment: Vec<u8> = qssm_api::commit(secret, &salt);
let revealed: Vec<u8> = qssm_api::open(secret, &salt);
assert_eq!(commitment, revealed, "commit and open must match");
let wrong: Vec<u8> = qssm_api::open(b"wrong-secret", &salt);
assert_ne!(
commitment, wrong,
"different secret must produce different output"
);
}
#[test]
fn compile_bad_template_returns_err() {
let result = qssm_api::compile("no-such-template-42");
assert!(result.is_err());
}
#[test]
fn prove_bad_json_returns_err() {
let blueprint = qssm_api::compile("age-gate-21").unwrap();
let result = qssm_api::prove(b"not json!", &[0u8; 32], &blueprint);
assert!(result.is_err());
}
#[test]
fn prove_bad_blueprint_returns_err() {
let result = qssm_api::prove(br#"{"claim":{}}"#, &[0u8; 32], b"garbage");
assert!(result.is_err());
}
#[test]
fn verify_bad_inputs_returns_false() {
assert!(!qssm_api::verify(b"bad-proof", b"bad-blueprint"));
}
#[test]
#[allow(clippy::type_complexity)]
fn signatures_match_frozen_contract() {
let _: fn(&str) -> Result<Vec<u8>, String> = qssm_api::compile;
let _: fn(&[u8], &[u8; 32]) -> Vec<u8> = qssm_api::commit;
let _: fn(&[u8], &[u8; 32], &[u8]) -> Result<Vec<u8>, String> = qssm_api::prove;
let _: fn(&[u8], &[u8]) -> bool = qssm_api::verify;
let _: fn(&[u8], &[u8; 32]) -> Vec<u8> = qssm_api::open;
}
fn public_fn_names(source: &str) -> std::collections::BTreeSet<String> {
let production = strip_cfg_test(source);
let mut names = std::collections::BTreeSet::new();
for line in production.lines() {
let trimmed = line.trim();
if let Some(rest) = trimmed.strip_prefix("pub fn ") {
if let Some(name) = rest.split('(').next() {
names.insert(name.trim().to_string());
}
}
}
names
}
fn strip_cfg_test(source: &str) -> String {
if let Some(pos) = source.find("#[cfg(test)]") {
source[..pos].to_string()
} else {
source.to_string()
}
}