use std::collections::HashSet;
use prebindgen_flat::flat::Flat;
use super::*;
fn flat_with(sources: &[&str]) -> Flat {
let items = sources
.iter()
.map(|src| {
let item: syn::Item = syn::parse_str(src).expect("parse item");
(item, prebindgen::SourceLocation::default())
})
.collect::<Vec<_>>();
Flat::builder().items(items).build().expect("index")
}
fn ident(n: &str) -> syn::Ident {
syn::parse_str(n).unwrap()
}
#[test]
fn every_unclaimed_item_is_reported_once() {
let flat = flat_with(&[
"pub fn a(x: u64) -> u64 { x }",
"pub fn b(x: u64) -> u64 { x }",
"pub struct S { pub v: u64 }",
"pub enum E { X = 1 }",
]);
let lines = unclaimed_report(&flat, &Claimed::default());
assert_eq!(
lines,
vec![
"prebindgen: skipping undeclared #[prebindgen] fn `a`",
"prebindgen: skipping undeclared #[prebindgen] fn `b`",
"prebindgen: skipping undeclared #[prebindgen] struct/enum `E`",
"prebindgen: skipping undeclared #[prebindgen] struct/enum `S`",
]
);
}
#[test]
fn a_claimed_item_is_not_reported() {
let flat = flat_with(&[
"pub fn a(x: u64) -> u64 { x }",
"pub struct S { pub v: u64 }",
]);
let claimed = Claimed {
functions: HashSet::from([ident("a")]),
types: HashSet::from([TypeKey::parse("S").unwrap()]),
..Claimed::default()
};
assert!(unclaimed_report(&flat, &claimed).is_empty());
}
#[test]
fn an_ignored_item_is_not_reported_as_skipped() {
let flat = flat_with(&[
"pub fn a(x: u64) -> u64 { x }",
"pub struct S { pub v: u64 }",
"pub const K: u64 = 7;",
]);
let claimed = Claimed {
consts: Some(HashSet::new()),
ignored_functions: HashSet::from([ident("a")]),
ignored_types: HashSet::from([TypeKey::parse("S").unwrap()]),
ignored_consts: HashSet::from([ident("K")]),
..Claimed::default()
};
assert!(
unclaimed_report(&flat, &claimed).is_empty(),
"an ignore must suppress the skip line, not just the stale-ignore line"
);
}
#[test]
fn a_stale_ignore_is_reported() {
let flat = flat_with(&["pub fn a(x: u64) -> u64 { x }"]);
let claimed = Claimed {
functions: HashSet::from([ident("a")]),
ignored_functions: HashSet::from([ident("gone_fn")]),
ignored_types: HashSet::from([TypeKey::parse("Gone").unwrap()]),
..Claimed::default()
};
assert_eq!(
unclaimed_report(&flat, &claimed),
vec![
"prebindgen: ignored function `gone_fn` not found among #[prebindgen] items",
"prebindgen: ignored type `Gone` not found among #[prebindgen] items",
]
);
}
#[test]
fn ignoring_an_alias_is_not_stale() {
let flat = flat_with(&[
"pub type Handle = other::Inner;",
"pub fn f(x: u64) -> u64 { x }",
]);
let claimed = Claimed {
functions: HashSet::from([ident("f")]),
ignored_types: HashSet::from([TypeKey::parse("Handle").unwrap()]),
..Claimed::default()
};
assert!(unclaimed_report(&flat, &claimed).is_empty());
assert!(unclaimed_report(&flat, &Claimed::default())
.iter()
.all(|l| !l.contains("Handle")));
}
#[test]
fn an_ignore_predicate_covers_every_kind_and_is_silent_when_unmatched() {
let flat = flat_with(&[
"pub fn helper_a(x: u64) -> u64 { x }",
"pub fn helper_b(x: u64) -> u64 { x }",
"pub struct HelperThing { pub v: u64 }",
"pub const HELPER_MAX: u64 = 1;",
]);
let claimed = Claimed {
consts: Some(HashSet::new()),
ignored_name_predicates: vec![
std::sync::Arc::new(|n: &str| n.to_lowercase().starts_with("helper")),
std::sync::Arc::new(|n: &str| n.starts_with("nothing_")),
],
..Claimed::default()
};
assert!(unclaimed_report(&flat, &claimed).is_empty());
}
#[test]
fn no_const_mechanism_reports_no_consts() {
let flat = flat_with(&["pub const K: u64 = 7;"]);
assert!(unclaimed_report(&flat, &Claimed::default()).is_empty());
let declares_consts = Claimed {
consts: Some(HashSet::new()),
..Claimed::default()
};
assert_eq!(
unclaimed_report(&flat, &declares_consts),
vec!["prebindgen: skipping undeclared #[prebindgen] const `K`"]
);
}