use super::analysis_source_boundary::{
assert_every_registered_wrapper_is_modelled, assert_functions_are_declared_once,
assert_manifest_states_no_delta, assert_no_test_lives_outside_the_root,
};
use super::cache_ownership::assert_cache_modules_are_discovered;
use super::inventory::{
CACHE_SOURCES, PRODUCTION_SOURCES, SOURCES, TEST_ROOT, TEST_SUPPORT_SOURCES,
};
use super::scan::{compact, naming};
pub const CACHE_PREDICATES: &[&str] = &[
"cached_graph_analysis_is_thread_shareable_and_deterministic",
"cached_graph_analysis_matches_every_direct_operation",
"cached_graph_analysis_rechecks_every_limit_before_hits",
"cached_graph_analysis_retention_is_bounded_lru",
"cached_graph_analysis_reuses_exact_arc_products_and_none",
"graph_cache_clear_eviction_and_drop_keep_live_handles_valid",
"graph_cache_counter_updates_are_saturating_and_single_owned",
"graph_cache_exact_build_matches_direct_graph_and_json",
"graph_cache_exact_hits_share_graph_and_short_circuit_work",
"graph_cache_exact_identity_guards_the_complete_resolution_claim",
"graph_cache_exact_retention_is_bounded_lru",
"graph_cache_hits_reapply_graph_limits_in_direct_order",
"graph_cache_poison_recovery_is_explicit_and_total",
"graph_cache_projection_has_one_planner_and_assembler",
"graph_cache_public_boundary_is_exact",
"graph_cache_rejects_invalid_pairs_before_observation",
"graph_cache_reuses_only_exact_source_unit_claims",
"graph_cache_revision_matrix_matches_direct_graph_and_json",
"graph_cache_source_boundary_is_exact",
"graph_cache_source_projection_retention_is_bounded_lru",
"graph_cache_tied_definition_identities_survive_dense_remapping",
];
const TRACKED_INPUTS: &[&str] = &["\"../../src/", "\"../graph.rs\"", "\"../../Cargo.toml\""];
const TRACKED_FRAGMENTS: &[&str] = &["$name", "\".rs\""];
const TEST_ROOT_PATH: &str = "tests/graph.rs";
const CACHE_FAMILY_SOURCES: &[&str] = &["src/rust/cache.rs", "src/rust/reuse.rs"];
const CAPABILITY_SPELLINGS: &[&str] = &[
"std::fs",
"std::net",
"std::process",
"File::open",
"File::create",
"TcpStream",
"UdpSocket",
"Command::new",
"read_to_string",
"read_dir",
"include!",
"include_str!",
"include_bytes!",
];
pub fn assert_cache_source_boundary_is_exact() {
assert_manifest_states_no_delta();
assert_no_test_lives_outside_the_root();
assert_cache_modules_are_discovered();
assert_every_cache_predicate_is_registered_once();
assert_every_registered_wrapper_is_modelled();
assert_reads_no_lifecycle_file();
assert_states_no_capability();
assert_states_no_trait_object();
assert_functions_are_declared_once(PRODUCTION_SOURCES, 200, "this crate");
assert_functions_are_declared_once(&cache_family(), 18, "the cache family");
}
fn cache_family() -> Vec<&'static str> {
CACHE_SOURCES
.iter()
.chain(CACHE_FAMILY_SOURCES.iter())
.copied()
.collect()
}
fn assert_every_cache_predicate_is_registered_once() {
for predicate in CACHE_PREDICATES {
assert_eq!(
TEST_ROOT
.matches(&format!("#[test]\nfn {predicate}()"))
.count(),
1,
"{predicate} is registered exactly once, with its bare identity"
);
}
}
fn assert_reads_no_lifecycle_file() {
let offenders: Vec<String> = TEST_SUPPORT_SOURCES
.iter()
.chain(SOURCES.iter())
.map(|entry| (entry.path, entry.text))
.chain(std::iter::once((TEST_ROOT_PATH, TEST_ROOT)))
.flat_map(|(path, text)| {
included_arguments(text)
.into_iter()
.filter(|argument| !is_tracked(argument))
.map(move |argument| format!("{path} reads {argument}"))
})
.collect();
assert!(
offenders.is_empty(),
"every compiled-in input is a tracked root of this crate: {offenders:?}"
);
}
fn is_tracked(argument: &str) -> bool {
match argument.strip_prefix(&assembly()) {
Some(listed) => listed.strip_suffix(')').is_some_and(|pieces| {
pieces
.split(',')
.all(|piece| TRACKED_FRAGMENTS.contains(&piece))
}),
None => TRACKED_INPUTS.iter().any(|root| argument.starts_with(root)),
}
}
fn included_arguments(text: &str) -> Vec<String> {
let code = compact(text);
inclusions()
.iter()
.flat_map(|needle| {
code.match_indices(needle.as_str())
.map(|(at, opening)| enclosed(&code, at + opening.len()))
.collect::<Vec<String>>()
})
.collect()
}
fn enclosed(code: &str, from: usize) -> String {
let mut depth = 1_usize;
let mut taken = String::new();
for character in code[from..].chars() {
match character {
'(' => depth += 1,
')' => depth -= 1,
_ => (),
}
if depth == 0 {
return taken;
}
taken.push(character);
}
panic!("an inclusion at {from} states no closing parenthesis: {taken}")
}
fn inclusions() -> Vec<String> {
["include", "include_bytes", "include_str"]
.into_iter()
.map(|spelling| format!("{spelling}{}(", '!'))
.collect()
}
fn assembly() -> String {
format!("concat{}(", '!')
}
fn assert_states_no_capability() {
let offenders = naming(PRODUCTION_SOURCES, CAPABILITY_SPELLINGS, "the capability");
assert!(
offenders.is_empty(),
"graph production sources state no file, process, or network site: {offenders:?}"
);
}
fn assert_states_no_trait_object() {
let spellings = ["Box", "Arc", "Rc"]
.into_iter()
.map(|owner| format!("{owner}<{}", "dyn"))
.chain(std::iter::once(format!("&{}", "dyn")))
.collect::<Vec<String>>();
let borrowed: Vec<&str> = spellings.iter().map(String::as_str).collect();
let offenders = naming(PRODUCTION_SOURCES, &borrowed, "the trait object");
assert!(
offenders.is_empty(),
"graph production sources state no trait object: {offenders:?}"
);
}