use super::facts::CallFact;
use super::rust_index::{
self, FunctionSummary, OracleFact, RustIndex, TestSummary, extract_identifier_tokens,
};
use super::seams::{ExpectedSink, RepoSeam, SeamId, SeamKind};
use crate::domain::{
Confidence, MissingDiscriminatorFact, OracleKind, OracleStrength, StageEvidence, StageState,
ValueContext, ValueFact,
};
use serde::{Deserialize, Serialize};
use std::cell::{OnceCell, RefCell};
use std::cmp::Reverse;
use std::collections::{BTreeMap, BTreeSet};
use std::path::{Path, PathBuf};
use std::time::{Duration, Instant};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) struct TestGripEvidence {
pub(crate) seam_id: SeamId,
pub(crate) related_tests: Vec<RelatedTestGrip>,
pub(crate) reach: StageEvidence,
pub(crate) activate: StageEvidence,
pub(crate) propagate: StageEvidence,
pub(crate) observe: StageEvidence,
pub(crate) discriminate: StageEvidence,
pub(crate) observed_values: Vec<ValueFact>,
pub(crate) missing_discriminators: Vec<MissingDiscriminatorFact>,
}
const COMPACT_RELATED_TEST_LIMIT: usize = 12;
const LATENCY_TRACE_ENV: &str = "RIPR_REPO_EXPOSURE_LATENCY_TRACE";
const EVIDENCE_PROGRESS_CHUNK: usize = 500;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) struct RelatedTestGrip {
pub(crate) test_name: String,
pub(crate) file: PathBuf,
pub(crate) line: usize,
pub(crate) oracle_kind: OracleKind,
pub(crate) oracle_strength: OracleStrength,
pub(crate) evidence_summary: String,
pub(crate) relation_reason: RelationReason,
pub(crate) relation_confidence: RelationConfidence,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct OracleSemantics {
pub(crate) observes: String,
pub(crate) missing: String,
pub(crate) upgrade_suggestion: Option<String>,
}
pub(crate) struct CompactGripContext<'a> {
index: &'a RustIndex,
tests: Vec<CompactTest<'a>>,
tests_by_call_name: BTreeMap<String, Vec<usize>>,
tests_by_assertion_token: BTreeMap<String, Vec<usize>>,
tests_by_file_stem: BTreeMap<String, Vec<usize>>,
tests_by_import_token: BTreeMap<String, Vec<usize>>,
owner_named_cache: RefCell<BTreeMap<String, Vec<usize>>>,
same_module_cache: RefCell<BTreeMap<String, Vec<usize>>>,
}
struct CompactTest<'a> {
test: &'a TestSummary,
path_normalized: String,
module_path: Option<String>,
name_lower: String,
call_names: BTreeSet<String>,
code_lines: Vec<String>,
value_facts: OnceCell<super::value_resolution::ValueEnvFacts>,
}
impl<'a> CompactGripContext<'a> {
pub(crate) fn new(index: &'a RustIndex) -> Self {
let mut tests_by_call_name: BTreeMap<String, Vec<usize>> = BTreeMap::new();
let mut tests_by_assertion_token: BTreeMap<String, Vec<usize>> = BTreeMap::new();
let mut tests_by_file_stem: BTreeMap<String, Vec<usize>> = BTreeMap::new();
let mut tests_by_import_token: BTreeMap<String, Vec<usize>> = BTreeMap::new();
let tests = index
.tests
.iter()
.enumerate()
.map(|(test_index, test)| {
let call_names = test
.calls
.iter()
.map(|call| call.name.clone())
.collect::<BTreeSet<_>>();
let mut assertion_tokens = BTreeSet::new();
for assertion in &test.assertions {
for token in extract_identifier_tokens(&assertion.text) {
assertion_tokens.insert(token);
}
}
let code_lines = test
.body
.lines()
.map(strip_comments_and_strings)
.collect::<Vec<_>>();
for call_name in &call_names {
tests_by_call_name
.entry(call_name.clone())
.or_default()
.push(test_index);
}
for token in &assertion_tokens {
tests_by_assertion_token
.entry(token.clone())
.or_default()
.push(test_index);
}
if let Some(stem) = test.file.file_stem().and_then(|stem| stem.to_str()) {
tests_by_file_stem
.entry(stem.to_string())
.or_default()
.push(test_index);
}
for token in import_affinity_tokens(&code_lines) {
tests_by_import_token
.entry(token)
.or_default()
.push(test_index);
}
CompactTest {
test,
path_normalized: normalize_path(&test.file),
module_path: module_path_for(&test.file),
name_lower: test.name.to_ascii_lowercase(),
call_names,
code_lines,
value_facts: OnceCell::new(),
}
})
.collect();
Self {
index,
tests,
tests_by_call_name,
tests_by_assertion_token,
tests_by_file_stem,
tests_by_import_token,
owner_named_cache: RefCell::new(BTreeMap::new()),
same_module_cache: RefCell::new(BTreeMap::new()),
}
}
fn owner_named_indices(&self, owner_name_lower: &str) -> Vec<usize> {
if owner_name_lower.is_empty() {
return Vec::new();
}
if let Some(indices) = self.owner_named_cache.borrow().get(owner_name_lower) {
return indices.clone();
}
let indices = self
.tests
.iter()
.enumerate()
.filter_map(|(index, test)| test.name_lower.contains(owner_name_lower).then_some(index))
.collect::<Vec<_>>();
self.owner_named_cache
.borrow_mut()
.insert(owner_name_lower.to_string(), indices.clone());
indices
}
fn same_module_indices(&self, owner_module: &str) -> Vec<usize> {
if owner_module.is_empty() {
return Vec::new();
}
if let Some(indices) = self.same_module_cache.borrow().get(owner_module) {
return indices.clone();
}
let indices = self
.tests
.iter()
.enumerate()
.filter_map(|(index, test)| {
test.module_path
.as_deref()
.is_some_and(|test_module| same_module(owner_module, test_module))
.then_some(index)
})
.collect::<Vec<_>>();
self.same_module_cache
.borrow_mut()
.insert(owner_module.to_string(), indices.clone());
indices
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub(crate) enum RelationReason {
DirectOwnerCall,
AssertionTargetAffinity,
SameTestFile,
SameModule,
OwnerNamedTest,
ImportPathAffinity,
FixtureOwnerAffinity,
}
impl RelationReason {
pub(crate) fn as_str(self) -> &'static str {
match self {
Self::DirectOwnerCall => "direct_owner_call",
Self::AssertionTargetAffinity => "assertion_target_affinity",
Self::SameTestFile => "same_test_file",
Self::SameModule => "same_module",
Self::OwnerNamedTest => "owner_named_test",
Self::ImportPathAffinity => "import_path_affinity",
Self::FixtureOwnerAffinity => "fixture_owner_affinity",
}
}
fn priority(self) -> u8 {
match self {
Self::DirectOwnerCall => 0,
Self::AssertionTargetAffinity => 1,
Self::SameTestFile => 2,
Self::SameModule => 3,
Self::OwnerNamedTest => 4,
Self::ImportPathAffinity => 5,
Self::FixtureOwnerAffinity => 6,
}
}
fn confidence(self) -> RelationConfidence {
match self {
Self::DirectOwnerCall | Self::AssertionTargetAffinity => RelationConfidence::High,
Self::SameTestFile
| Self::SameModule
| Self::OwnerNamedTest
| Self::ImportPathAffinity => RelationConfidence::Medium,
Self::FixtureOwnerAffinity => RelationConfidence::Low,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub(crate) enum RelationConfidence {
High,
Medium,
Low,
Opaque,
}
impl RelationConfidence {
pub(crate) fn as_str(self) -> &'static str {
match self {
Self::High => "high",
Self::Medium => "medium",
Self::Low => "low",
Self::Opaque => "opaque",
}
}
fn rank(self) -> u8 {
match self {
Self::High => 0,
Self::Medium => 1,
Self::Low => 2,
Self::Opaque => 3,
}
}
}
pub(crate) fn evidence_for_seams(seams: &[RepoSeam], index: &RustIndex) -> Vec<TestGripEvidence> {
let context_started = Instant::now();
trace_latency_phase(
"evidence_context",
&format!("start_seams_{}", seams.len()),
Duration::ZERO,
);
let context = CompactGripContext::new(index);
trace_latency_phase(
"evidence_context",
&format!("tests_{}_seams_{}", context.tests.len(), seams.len()),
context_started.elapsed(),
);
let evidence_started = Instant::now();
let mut out: Vec<TestGripEvidence> = Vec::with_capacity(seams.len());
for (index, seam) in seams.iter().enumerate() {
out.push(evidence_for_seam_with_context(seam, &context));
let processed = index + 1;
if processed % EVIDENCE_PROGRESS_CHUNK == 0 || processed == seams.len() {
trace_latency_phase(
"evidence_for_seams_progress",
&format!("processed_{processed}_of_{}", seams.len()),
evidence_started.elapsed(),
);
}
}
out.sort_by(|a, b| a.seam_id.as_str().cmp(b.seam_id.as_str()));
out
}
#[cfg(test)]
pub(crate) fn evidence_for_seam(seam: &RepoSeam, index: &RustIndex) -> TestGripEvidence {
let context = CompactGripContext::new(index);
evidence_for_seam_with_context(seam, &context)
}
fn evidence_for_seam_with_context(
seam: &RepoSeam,
context: &CompactGripContext<'_>,
) -> TestGripEvidence {
let mut related_with_reason = find_related_tests_with_context(seam, context);
sort_related_tests_for_seam(seam, context, &mut related_with_reason);
let related_indexed: Vec<&CompactTest<'_>> = related_with_reason
.iter()
.map(|(indexed, _reason)| *indexed)
.collect();
let owner_fn = find_owner_function(seam, context.index);
let related: Vec<&TestSummary> = related_indexed.iter().map(|indexed| indexed.test).collect();
let reach = reach_evidence(seam, &related);
let (activate, observed_values, missing_discriminators) =
activate_evidence(seam, &related_indexed, context.index, owner_fn);
let propagate = propagate_evidence(seam, &related);
let observe = observe_evidence(&related);
let discriminate = discriminate_evidence(seam, &related);
let related_tests: Vec<RelatedTestGrip> = related_with_reason
.iter()
.map(|(indexed, reason)| related_test_grip(seam, indexed.test, *reason))
.collect();
TestGripEvidence {
seam_id: seam.id().clone(),
related_tests,
reach,
activate,
propagate,
observe,
discriminate,
observed_values,
missing_discriminators,
}
}
fn trace_latency_phase(phase: &str, status: &str, duration: Duration) {
if std::env::var_os(LATENCY_TRACE_ENV).is_some() {
eprintln!("{}", latency_trace_line(phase, status, duration));
}
}
fn latency_trace_line(phase: &str, status: &str, duration: Duration) -> String {
format!(
"ripr_repo_exposure_latency phase={phase} status={status} duration_ms={}",
duration.as_millis()
)
}
pub(crate) fn compact_evidence_for_seam(
seam: &RepoSeam,
context: &CompactGripContext<'_>,
) -> TestGripEvidence {
let related_indexed = find_related_tests_compact(seam, context);
let related: Vec<&TestSummary> = related_indexed.iter().map(|indexed| indexed.test).collect();
let owner_fn = find_owner_function(seam, context.index);
let reach = reach_evidence(seam, &related);
let (activate, missing_discriminators) =
compact_activate_evidence(seam, &related_indexed, context.index, owner_fn);
let propagate = propagate_evidence(seam, &related);
let observe = observe_evidence(&related);
let discriminate = discriminate_evidence(seam, &related);
TestGripEvidence {
seam_id: seam.id().clone(),
related_tests: Vec::new(),
reach,
activate,
propagate,
observe,
discriminate,
observed_values: Vec::new(),
missing_discriminators,
}
}
fn find_related_tests_with_context<'context, 'index>(
seam: &RepoSeam,
context: &'context CompactGripContext<'index>,
) -> Vec<(&'context CompactTest<'index>, RelationReason)> {
let owner = OwnerContext::resolve(seam, context);
let target_tokens = assertion_target_tokens(seam);
let prefix = owner.prefix.as_deref();
let mut candidates: BTreeMap<usize, RelationReason> = BTreeMap::new();
match_direct_owner_call(&mut candidates, context, prefix, &owner);
match_assertion_target_affinity(&mut candidates, context, prefix, &target_tokens);
match_same_test_file(&mut candidates, context, prefix, &owner);
match_same_module(&mut candidates, context, prefix, &owner);
match_owner_named_test(&mut candidates, context, prefix, &owner);
match_import_path_affinity(&mut candidates, context, prefix, &owner);
match_fixture_owner_affinity(&mut candidates, context, prefix, &owner);
dedupe_related_candidates(candidates, context)
}
struct OwnerContext {
name: String,
name_lower: String,
file_stem: String,
module_path: Option<String>,
prefix: Option<String>,
fixture_names: BTreeSet<String>,
}
impl OwnerContext {
fn resolve(seam: &RepoSeam, context: &CompactGripContext<'_>) -> Self {
let owner_fn = find_owner_function(seam, context.index);
let name = owner_fn.map(|f| f.name.as_str()).unwrap_or("").to_string();
let name_lower = name.to_ascii_lowercase();
let owner_file = owner_fn.map(|f| f.file.as_path());
let file_stem = owner_file
.and_then(|p| p.file_stem())
.and_then(|s| s.to_str())
.unwrap_or("")
.to_string();
let module_path = owner_file.and_then(module_path_for);
let prefix = owner_fn.and_then(|f| package_prefix(&f.file));
let fixture_names = owner_file
.and_then(|file| context.index.files.get(file))
.map(fixture_names_for_owner_file)
.unwrap_or_default();
Self {
name,
name_lower,
file_stem,
module_path,
prefix,
fixture_names,
}
}
}
fn assertion_target_tokens(seam: &RepoSeam) -> BTreeSet<String> {
let discriminator_tokens = required_discriminator_tokens(seam);
let sink_tokens = extract_identifier_tokens(seam.expected_sink().as_str());
discriminator_tokens
.into_iter()
.chain(sink_tokens)
.collect()
}
fn match_direct_owner_call(
candidates: &mut BTreeMap<usize, RelationReason>,
context: &CompactGripContext<'_>,
prefix: Option<&str>,
owner: &OwnerContext,
) {
if owner.name.is_empty() {
return;
}
let Some(indices) = context.tests_by_call_name.get(&owner.name) else {
return;
};
for test_index in indices {
insert_related_candidate(
candidates,
context,
prefix,
*test_index,
RelationReason::DirectOwnerCall,
);
}
}
fn match_assertion_target_affinity(
candidates: &mut BTreeMap<usize, RelationReason>,
context: &CompactGripContext<'_>,
prefix: Option<&str>,
target_tokens: &BTreeSet<String>,
) {
for token in target_tokens {
if let Some(indices) = context.tests_by_assertion_token.get(token) {
for test_index in indices {
insert_related_candidate(
candidates,
context,
prefix,
*test_index,
RelationReason::AssertionTargetAffinity,
);
}
}
}
}
fn match_same_test_file(
candidates: &mut BTreeMap<usize, RelationReason>,
context: &CompactGripContext<'_>,
prefix: Option<&str>,
owner: &OwnerContext,
) {
if owner.file_stem.is_empty() {
return;
}
let stems = [
owner.file_stem.clone(),
format!("{}_test", owner.file_stem),
format!("{}_tests", owner.file_stem),
];
for stem in stems {
if let Some(indices) = context.tests_by_file_stem.get(&stem) {
for test_index in indices {
insert_related_candidate(
candidates,
context,
prefix,
*test_index,
RelationReason::SameTestFile,
);
}
}
}
}
fn match_same_module(
candidates: &mut BTreeMap<usize, RelationReason>,
context: &CompactGripContext<'_>,
prefix: Option<&str>,
owner: &OwnerContext,
) {
let Some(module_path) = owner.module_path.as_deref() else {
return;
};
for test_index in context.same_module_indices(module_path) {
insert_related_candidate(
candidates,
context,
prefix,
test_index,
RelationReason::SameModule,
);
}
}
fn match_owner_named_test(
candidates: &mut BTreeMap<usize, RelationReason>,
context: &CompactGripContext<'_>,
prefix: Option<&str>,
owner: &OwnerContext,
) {
for test_index in context.owner_named_indices(&owner.name_lower) {
insert_related_candidate(
candidates,
context,
prefix,
test_index,
RelationReason::OwnerNamedTest,
);
}
}
fn match_import_path_affinity(
candidates: &mut BTreeMap<usize, RelationReason>,
context: &CompactGripContext<'_>,
prefix: Option<&str>,
owner: &OwnerContext,
) {
if owner.name.is_empty() {
return;
}
let Some(indices) = context.tests_by_import_token.get(&owner.name) else {
return;
};
for test_index in indices {
if !context
.tests
.get(*test_index)
.is_some_and(|indexed| test_imports_owner_compact(indexed, &owner.name))
{
continue;
}
insert_related_candidate(
candidates,
context,
prefix,
*test_index,
RelationReason::ImportPathAffinity,
);
}
}
fn match_fixture_owner_affinity(
candidates: &mut BTreeMap<usize, RelationReason>,
context: &CompactGripContext<'_>,
prefix: Option<&str>,
owner: &OwnerContext,
) {
for fixture_name in &owner.fixture_names {
if let Some(indices) = context.tests_by_call_name.get(fixture_name) {
for test_index in indices {
insert_related_candidate(
candidates,
context,
prefix,
*test_index,
RelationReason::FixtureOwnerAffinity,
);
}
}
}
}
fn dedupe_related_candidates<'context, 'index>(
candidates: BTreeMap<usize, RelationReason>,
context: &'context CompactGripContext<'index>,
) -> Vec<(&'context CompactTest<'index>, RelationReason)> {
let mut related: Vec<(&'context CompactTest<'index>, RelationReason)> = Vec::new();
let mut seen: std::collections::HashSet<(String, PathBuf, usize)> =
std::collections::HashSet::new();
for (test_index, reason) in candidates {
let Some(indexed) = context.tests.get(test_index) else {
continue;
};
let key = (
indexed.test.name.clone(),
indexed.test.file.clone(),
indexed.test.start_line,
);
if seen.insert(key) {
related.push((indexed, reason));
}
}
related
}
fn insert_related_candidate(
candidate_reasons: &mut BTreeMap<usize, RelationReason>,
context: &CompactGripContext<'_>,
prefix: Option<&str>,
test_index: usize,
reason: RelationReason,
) {
if candidate_reasons.contains_key(&test_index) {
return;
}
let Some(indexed) = context.tests.get(test_index) else {
return;
};
if let Some(prefix) = prefix
&& !indexed.path_normalized.starts_with(prefix)
{
return;
}
candidate_reasons.insert(test_index, reason);
}
fn find_related_tests_compact<'a>(
seam: &RepoSeam,
context: &'a CompactGripContext<'_>,
) -> Vec<&'a CompactTest<'a>> {
let mut related = find_related_tests_with_context(seam, context);
sort_related_tests_for_seam(seam, context, &mut related);
related
.into_iter()
.take(COMPACT_RELATED_TEST_LIMIT)
.map(|(indexed, _reason)| indexed)
.collect()
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd)]
struct RelatedTestRankKey {
relation_confidence: u8,
relation_reason: u8,
oracle_strength: Reverse<u8>,
activation_overlap: Reverse<usize>,
file: PathBuf,
test_name: String,
line: usize,
}
fn sort_related_tests_for_seam(
seam: &RepoSeam,
context: &CompactGripContext<'_>,
related: &mut [(&CompactTest<'_>, RelationReason)],
) {
related.sort_by_cached_key(|entry| {
let (indexed, reason) = *entry;
related_test_rank_key(seam, context, indexed, reason)
});
}
fn related_test_rank_key(
seam: &RepoSeam,
context: &CompactGripContext<'_>,
indexed: &CompactTest<'_>,
reason: RelationReason,
) -> RelatedTestRankKey {
let (_oracle_kind, oracle_strength) = best_oracle(indexed.test, seam);
RelatedTestRankKey {
relation_confidence: reason.confidence().rank(),
relation_reason: reason.priority(),
oracle_strength: Reverse(oracle_strength.rank()),
activation_overlap: Reverse(activation_overlap_score(seam, context, indexed)),
file: indexed.test.file.clone(),
test_name: indexed.test.name.clone(),
line: indexed.test.start_line,
}
}
fn fixture_names_for_owner_file(facts: &rust_index::FileFacts) -> BTreeSet<String> {
facts
.functions
.iter()
.filter(|f| !f.is_test && (is_fixture_named(&f.name) || f.body.contains("#[fixture]")))
.map(|f| f.name.clone())
.collect()
}
fn required_discriminator_tokens(seam: &RepoSeam) -> Vec<String> {
extract_identifier_tokens(required_discriminator_text(seam))
}
fn required_discriminator_text(seam: &RepoSeam) -> &str {
use super::seams::RequiredDiscriminator;
match seam.required_discriminator() {
RequiredDiscriminator::BoundaryValue { description }
| RequiredDiscriminator::ReturnValue { description } => description.as_str(),
RequiredDiscriminator::ErrorVariant { variant } => variant.as_str(),
RequiredDiscriminator::FieldValue { field } => field.as_str(),
RequiredDiscriminator::Effect { sink } => sink.as_str(),
RequiredDiscriminator::MatchArmTaken { arm } => arm.as_str(),
RequiredDiscriminator::CallSite { target } => target.as_str(),
}
}
#[cfg(test)]
fn assertion_targets_seam(test: &TestSummary, tokens: &[String]) -> bool {
if tokens.is_empty() {
return false;
}
for assertion in &test.assertions {
let assertion_tokens = extract_identifier_tokens(&assertion.text);
if assertion_tokens
.iter()
.any(|at| tokens.iter().any(|t| at == t))
{
return true;
}
}
false
}
#[cfg(test)]
fn same_test_file(test_file: &Path, owner_stem: &str) -> bool {
let stem = match test_file.file_stem().and_then(|s| s.to_str()) {
Some(s) => s,
None => return false,
};
if stem == owner_stem {
return true;
}
if let Some(prefix) = stem.strip_suffix("_test")
&& prefix == owner_stem
{
return true;
}
if let Some(prefix) = stem.strip_suffix("_tests")
&& prefix == owner_stem
{
return true;
}
false
}
fn module_path_for(file: &Path) -> Option<String> {
let normalized = normalize_path(file);
let body = normalized
.rfind("/src/")
.map(|idx| &normalized[idx + "/src/".len()..])
.or_else(|| {
normalized
.rfind("/tests/")
.map(|idx| &normalized[idx + "/tests/".len()..])
})
.or_else(|| normalized.strip_prefix("src/"))
.or_else(|| normalized.strip_prefix("tests/"))?;
let trimmed = body.strip_suffix(".rs").unwrap_or(body);
if trimmed.is_empty() {
None
} else {
Some(trimmed.to_string())
}
}
fn same_module(owner_module: &str, test_module: &str) -> bool {
let parent = match owner_module.rsplit_once('/') {
Some((parent, _leaf)) => parent,
None => return false,
};
if parent.is_empty() {
return false;
}
test_module == parent
|| test_module.starts_with(&format!("{parent}/"))
|| test_module.starts_with(&format!("{}/", parent.replace('/', "_")))
}
fn test_imports_owner_compact(test: &CompactTest<'_>, owner_name: &str) -> bool {
if owner_name.is_empty() {
return false;
}
let qualified = format!("::{owner_name}");
for code in &test.code_lines {
if code.contains(&qualified) {
return true;
}
if code.trim_start().starts_with("use ")
&& extract_identifier_tokens(code)
.iter()
.any(|token| token == owner_name)
{
return true;
}
}
false
}
fn import_affinity_tokens(code_lines: &[String]) -> BTreeSet<String> {
let mut tokens = BTreeSet::new();
for code in code_lines {
let trimmed = code.trim_start();
if code.contains("::") || trimmed.starts_with("use ") {
tokens.extend(extract_identifier_tokens(code));
}
}
tokens
}
fn strip_comments_and_strings(line: &str) -> String {
let without_comment = match line.find("//") {
Some(idx) => &line[..idx],
None => line,
};
let mut out = String::with_capacity(without_comment.len());
let mut in_string = false;
let mut escaped = false;
for ch in without_comment.chars() {
if in_string {
if escaped {
escaped = false;
continue;
}
match ch {
'\\' => escaped = true,
'"' => in_string = false,
_ => {}
}
continue;
}
if ch == '"' {
in_string = true;
continue;
}
out.push(ch);
}
out
}
fn is_fixture_named(name: &str) -> bool {
let prefixes = ["fixture_", "setup_", "make_", "build_", "new_", "mock_"];
let suffixes = ["_fixture", "_factory"];
prefixes.iter().any(|p| name.starts_with(p)) || suffixes.iter().any(|s| name.ends_with(s))
}
fn find_owner_function<'a>(seam: &RepoSeam, index: &'a RustIndex) -> Option<&'a FunctionSummary> {
rust_index::find_owner_function(index, seam.file(), seam.display_line())
}
fn normalize_path(path: &Path) -> String {
path.to_string_lossy()
.replace('\\', "/")
.trim_start_matches("./")
.to_string()
}
fn package_prefix(path: &Path) -> Option<String> {
let normalized = normalize_path(path);
if let Some(rest) = normalized.strip_prefix("crates/")
&& let Some((crate_name, crate_relative)) = rest.split_once('/')
&& (crate_relative.starts_with("src/") || crate_relative.starts_with("tests/"))
{
return Some(format!("crates/{crate_name}/"));
}
for marker in ["/src/", "/tests/"] {
if let Some(idx) = normalized.rfind(marker) {
let prefix = &normalized[..idx];
if prefix.is_empty() {
return None;
}
return Some(format!("{prefix}/"));
}
}
None
}
fn reach_evidence(seam: &RepoSeam, related: &[&TestSummary]) -> StageEvidence {
if related.is_empty() {
return StageEvidence::new(
StageState::No,
Confidence::Medium,
format!(
"No static test path found for seam owner `{}`",
seam.owner()
),
);
}
let names: Vec<&str> = related.iter().take(3).map(|t| t.name.as_str()).collect();
StageEvidence::new(
StageState::Yes,
Confidence::Medium,
format!(
"Related tests appear to reach `{}`: {}",
seam.owner(),
names.join(", ")
),
)
}
fn activate_evidence(
seam: &RepoSeam,
related: &[&CompactTest<'_>],
index: &RustIndex,
owner_fn: Option<&FunctionSummary>,
) -> (StageEvidence, Vec<ValueFact>, Vec<MissingDiscriminatorFact>) {
let owner_name = owner_fn.map(|f| f.name.as_str()).unwrap_or("");
let mut observed: Vec<ValueFact> = Vec::new();
if !owner_name.is_empty() {
for indexed in related {
observed.extend(observed_value_facts_for_test(
seam, indexed, index, owner_name,
));
}
}
sort_value_facts(&mut observed);
let missing = missing_discriminators_for(seam, &observed);
let direct_value_insensitive_owner_call = !owner_name.is_empty()
&& !requires_concrete_activation_values(seam)
&& related
.iter()
.any(|indexed| has_direct_owner_call(indexed, owner_name));
let state = if related.is_empty() {
StageState::No
} else if !observed.is_empty() || direct_value_insensitive_owner_call {
StageState::Yes
} else {
StageState::Unknown
};
let stage = StageEvidence::new(
state,
if !observed.is_empty() || direct_value_insensitive_owner_call {
Confidence::Medium
} else {
Confidence::Low
},
if !observed.is_empty() {
format!(
"Observed {} concrete activation value(s) for seam `{}`",
observed.len(),
seam.expression()
.lines()
.next()
.unwrap_or(seam.expression())
)
} else if direct_value_insensitive_owner_call {
format!(
"Observed direct owner call for value-insensitive seam `{}`",
seam.expression()
.lines()
.next()
.unwrap_or(seam.expression())
)
} else if requires_concrete_activation_values(seam) {
format!(
"No concrete activation values observed for seam `{}`",
seam.expression()
.lines()
.next()
.unwrap_or(seam.expression())
)
} else {
format!(
"No direct owner call observed for value-insensitive seam `{}`",
seam.expression()
.lines()
.next()
.unwrap_or(seam.expression())
)
},
);
(stage, observed, missing)
}
fn requires_concrete_activation_values(seam: &RepoSeam) -> bool {
matches!(seam.kind(), SeamKind::PredicateBoundary)
}
fn observed_value_facts_for_test(
seam: &RepoSeam,
indexed: &CompactTest<'_>,
index: &RustIndex,
owner_name: &str,
) -> Vec<ValueFact> {
let mut observed: Vec<ValueFact> = Vec::new();
let value_facts = indexed
.value_facts
.get_or_init(|| super::value_resolution::ValueEnvFacts::build(indexed.test, index));
let env = super::value_resolution::ValueEnv::new(seam, value_facts);
let observed_argument_indices = observed_argument_indices(seam, index, owner_name);
for call in &indexed.test.calls {
if call.name != owner_name {
continue;
}
let Some(args) = call_arguments(&call.text, owner_name) else {
continue;
};
for (arg_index, arg) in args.into_iter().enumerate() {
if let Some(indices) = &observed_argument_indices
&& !indices.contains(&arg_index)
{
continue;
}
let mut emitted = false;
for value in scalar_values(&arg) {
observed.push(ValueFact {
line: call.line,
text: call.text.clone(),
value,
context: ValueContext::FunctionArgument,
});
emitted = true;
}
if emitted {
continue;
}
for (value, context) in env.resolve_at_call(&arg, call.line, &call.name, &call.text) {
observed.push(ValueFact {
line: call.line,
text: call.text.clone(),
value,
context,
});
}
}
}
observed.extend(env.builder_facts());
observed
}
fn has_direct_owner_call(indexed: &CompactTest<'_>, owner_name: &str) -> bool {
indexed
.test
.calls
.iter()
.any(|call| call.name == owner_name && call_arguments(&call.text, owner_name).is_some())
}
fn observed_argument_indices(
seam: &RepoSeam,
index: &RustIndex,
owner_name: &str,
) -> Option<Vec<usize>> {
if seam.kind() != SeamKind::PredicateBoundary {
return None;
}
let owner_fn = find_owner_function(seam, index)?;
if owner_fn.name != owner_name {
return None;
}
let (left, right) = comparison_operands(seam.expression())?;
let parameters = function_parameters(owner_fn);
if let Some(left_index) = parameters.iter().position(|param| param == &left) {
return Some(vec![left_index]);
}
parameters
.iter()
.position(|param| param == &right)
.map(|right_index| vec![right_index])
}
fn activation_overlap_score(
seam: &RepoSeam,
context: &CompactGripContext<'_>,
indexed: &CompactTest<'_>,
) -> usize {
let Some(owner_fn) = find_owner_function(seam, context.index) else {
return 0;
};
let owner_name = owner_fn.name.as_str();
if owner_name.is_empty() {
return 0;
}
let mut score = boundary_equality_overlap_score(seam, indexed, context.index, owner_fn);
let required_text = required_discriminator_text(seam);
score += observed_value_facts_for_test(seam, indexed, context.index, owner_name)
.iter()
.filter(|fact| observed_value_matches_required_discriminator(&fact.value, required_text))
.count();
score
}
fn observed_value_matches_required_discriminator(value: &str, required_text: &str) -> bool {
let value = value.trim();
let required_text = required_text.trim();
!value.is_empty()
&& !required_text.is_empty()
&& (value == required_text
|| value.contains(required_text)
|| required_text.contains(value))
}
fn boundary_equality_overlap_score(
seam: &RepoSeam,
indexed: &CompactTest<'_>,
index: &RustIndex,
owner_fn: &FunctionSummary,
) -> usize {
if seam.kind() != SeamKind::PredicateBoundary {
return 0;
}
let Some((left, right)) = comparison_operands(seam.expression()) else {
return 0;
};
let parameters = function_parameters(owner_fn);
let Some(left_index) = parameters.iter().position(|param| param == &left) else {
return 0;
};
let Some(right_index) = parameters.iter().position(|param| param == &right) else {
return 0;
};
let mut score = 0;
for call in &indexed.test.calls {
if call.name != owner_fn.name {
continue;
}
let Some(args) = call_arguments(&call.text, &owner_fn.name) else {
continue;
};
let Some(left_arg) = args.get(left_index) else {
continue;
};
let Some(right_arg) = args.get(right_index) else {
continue;
};
if arguments_overlap_at_boundary(seam, indexed, index, left_arg, right_arg, call) {
score += 1;
}
}
score
}
fn arguments_overlap_at_boundary(
seam: &RepoSeam,
indexed: &CompactTest<'_>,
index: &RustIndex,
left_arg: &str,
right_arg: &str,
call: &CallFact,
) -> bool {
if left_arg.trim() == right_arg.trim() && !left_arg.trim().is_empty() {
return true;
}
let left_values = resolved_argument_values(seam, indexed, index, left_arg, call);
let right_values = resolved_argument_values(seam, indexed, index, right_arg, call);
left_values.iter().any(|left| {
let left = comparable_value(left);
right_values
.iter()
.any(|right| left == comparable_value(right))
})
}
fn resolved_argument_values(
seam: &RepoSeam,
indexed: &CompactTest<'_>,
index: &RustIndex,
arg: &str,
call: &CallFact,
) -> Vec<String> {
let values = scalar_values(arg);
if !values.is_empty() {
return values;
}
let value_facts = indexed
.value_facts
.get_or_init(|| super::value_resolution::ValueEnvFacts::build(indexed.test, index));
let env = super::value_resolution::ValueEnv::new(seam, value_facts);
env.resolve_at_call(arg, call.line, &call.name, &call.text)
.into_iter()
.map(|(value, _context)| value)
.collect()
}
fn compact_activate_evidence(
seam: &RepoSeam,
related: &[&CompactTest<'_>],
index: &RustIndex,
owner_fn: Option<&FunctionSummary>,
) -> (StageEvidence, Vec<MissingDiscriminatorFact>) {
if seam.kind() == SeamKind::PredicateBoundary {
let (stage, _observed, missing) = activate_evidence(seam, related, index, owner_fn);
return (stage, missing);
}
let owner_name = owner_fn.map(|f| f.name.as_str()).unwrap_or("");
let direct_owner_call = !owner_name.is_empty()
&& related
.iter()
.any(|indexed| indexed.call_names.contains(owner_name));
let state = if related.is_empty() {
StageState::No
} else if direct_owner_call {
StageState::Yes
} else {
StageState::Unknown
};
let stage = StageEvidence::new(
state.clone(),
if direct_owner_call {
Confidence::Medium
} else {
Confidence::Low
},
format!(
"Compact activation evidence for seam `{}` is `{}`",
seam.expression()
.lines()
.next()
.unwrap_or(seam.expression()),
state.as_str()
),
);
(stage, Vec::new())
}
fn missing_discriminators_for(
seam: &RepoSeam,
observed: &[ValueFact],
) -> Vec<MissingDiscriminatorFact> {
match seam.kind() {
SeamKind::PredicateBoundary => {
let expression = seam.expression();
if !boundary_predicate_uses_equal_op(expression) {
return Vec::new();
}
let boundary_token = boundary_rhs_token(expression);
if boundary_token.is_empty() {
return Vec::new();
}
let any_observed = !observed.is_empty();
if !any_observed {
return vec![MissingDiscriminatorFact {
value: format!("{boundary_token} (boundary value)"),
reason: "no observed activation values for boundary predicate".to_string(),
flow_sink: None,
}];
}
let equality_seen = observed
.iter()
.any(|v| v.value.as_str() == boundary_token.as_str());
if equality_seen {
Vec::new()
} else {
vec![MissingDiscriminatorFact {
value: format!("{boundary_token} (equality boundary)"),
reason:
"observed values do not include the equality-boundary case for this predicate"
.to_string(),
flow_sink: None,
}]
}
}
SeamKind::ErrorVariant => Vec::new(),
SeamKind::ReturnValue
| SeamKind::FieldConstruction
| SeamKind::SideEffect
| SeamKind::MatchArm
| SeamKind::CallPresence => Vec::new(),
}
}
fn boundary_predicate_uses_equal_op(expression: &str) -> bool {
expression.contains(" >= ")
|| expression.contains(" <= ")
|| expression.contains(" == ")
|| expression.contains(" != ")
}
fn boundary_rhs_token(expression: &str) -> String {
for op in [" >= ", " <= ", " == ", " != ", " > ", " < "] {
if let Some(idx) = expression.find(op) {
let rhs = expression[idx + op.len()..].trim();
let token: String = rhs
.chars()
.take_while(|c| c.is_alphanumeric() || *c == '_')
.collect();
if !token.is_empty() {
return token;
}
}
}
String::new()
}
fn function_parameters(function: &FunctionSummary) -> Vec<String> {
let signature = function
.body
.lines()
.next()
.unwrap_or(function.body.as_str());
let Some(open) = signature.find('(') else {
return Vec::new();
};
let after_open = &signature[open + 1..];
let Some(close) = after_open.find(')') else {
return Vec::new();
};
split_top_level_commas(&after_open[..close])
.into_iter()
.filter_map(|argument| {
argument
.split_once(':')
.map(|(name, _type)| name.trim().to_string())
})
.filter(|name| !name.is_empty() && name != "self" && name != "&self" && name != "mut self")
.collect()
}
fn comparison_operands(expression: &str) -> Option<(String, String)> {
for operator in [">=", "<=", "==", "!=", ">", "<"] {
if let Some((left, right)) = expression.split_once(operator) {
let left = clean_operand(left);
let right = clean_operand(right);
if !left.is_empty() && !right.is_empty() {
return Some((left, right));
}
}
}
None
}
fn clean_operand(operand: &str) -> String {
let cleaned = operand
.trim()
.trim_start_matches("if ")
.trim_end_matches('{')
.trim_end_matches(';')
.trim();
cleaned
.split_once('{')
.map(|(before, _after)| before.trim())
.unwrap_or(cleaned)
.to_string()
}
fn comparable_value(value: &str) -> String {
value
.trim()
.trim_matches('"')
.chars()
.filter(|ch| *ch != '_')
.collect()
}
fn propagate_evidence(seam: &RepoSeam, related: &[&TestSummary]) -> StageEvidence {
if related.is_empty() {
return StageEvidence::new(
StageState::No,
Confidence::Medium,
"No related tests; cannot infer propagation",
);
}
let any_oracle = related.iter().any(|t| !t.assertions.is_empty());
let any_matching_sink = related
.iter()
.any(|t| oracles_match_sink(&t.assertions, seam.expected_sink()));
let state = match (any_oracle, any_matching_sink) {
(true, true) => StageState::Yes,
(true, false) => StageState::Unknown,
(false, _) => StageState::Unknown,
};
let summary = format!(
"Static propagation to `{}` sink is {}",
seam.expected_sink().as_str(),
state.as_str()
);
StageEvidence::new(state, Confidence::Low, summary)
}
fn oracles_match_sink(oracles: &[OracleFact], sink: ExpectedSink) -> bool {
oracles.iter().any(|oracle| match sink {
ExpectedSink::ReturnValue | ExpectedSink::OutputField => matches!(
oracle.kind,
OracleKind::ExactValue
| OracleKind::WholeObjectEquality
| OracleKind::Snapshot
| OracleKind::RelationalCheck
),
ExpectedSink::ErrorChannel => matches!(
oracle.kind,
OracleKind::ExactErrorVariant | OracleKind::BroadError
),
ExpectedSink::SideEffect => matches!(oracle.kind, OracleKind::MockExpectation),
})
}
fn observe_evidence(related: &[&TestSummary]) -> StageEvidence {
if related.is_empty() {
return StageEvidence::new(
StageState::No,
Confidence::Medium,
"No related tests; nothing observes the seam",
);
}
let any_oracle = related.iter().any(|t| !t.assertions.is_empty());
let any_smoke_only = related.iter().all(|t| {
!t.assertions.is_empty() && t.assertions.iter().all(|o| o.kind == OracleKind::SmokeOnly)
});
let state = if !any_oracle {
StageState::No
} else if any_smoke_only {
StageState::Weak
} else {
StageState::Yes
};
let summary = format!("Observation evidence is `{}`", state.as_str());
StageEvidence::new(state, Confidence::Medium, summary)
}
fn discriminate_evidence(seam: &RepoSeam, related: &[&TestSummary]) -> StageEvidence {
if related.is_empty() {
return StageEvidence::new(
StageState::No,
Confidence::Medium,
"No related tests; oracle cannot discriminate",
);
}
let mut best = OracleStrength::None;
let mut best_kind_matches_seam = false;
for test in related {
for oracle in &test.assertions {
if oracle.strength.rank() > best.rank() {
best = oracle.strength.clone();
}
if oracle_kind_matches_seam(seam, &oracle.kind) {
best_kind_matches_seam = true;
}
}
}
let state = match (best_kind_matches_seam, &best) {
(_, OracleStrength::None) => StageState::No,
(_, OracleStrength::Unknown) => StageState::Unknown,
(_, OracleStrength::Weak | OracleStrength::Smoke) => StageState::Weak,
(true, OracleStrength::Strong | OracleStrength::Medium) => StageState::Yes,
(false, OracleStrength::Strong | OracleStrength::Medium) => StageState::Weak,
};
let summary = format!(
"Strongest oracle for seam kind `{}` is `{}` (kind-match {})",
seam.kind().as_str(),
best.as_str(),
best_kind_matches_seam
);
StageEvidence::new(state, Confidence::Medium, summary)
}
fn oracle_kind_matches_seam(seam: &RepoSeam, oracle: &OracleKind) -> bool {
match seam.kind() {
SeamKind::PredicateBoundary
| SeamKind::ReturnValue
| SeamKind::MatchArm
| SeamKind::FieldConstruction => matches!(
oracle,
OracleKind::ExactValue
| OracleKind::WholeObjectEquality
| OracleKind::Snapshot
| OracleKind::RelationalCheck
),
SeamKind::ErrorVariant => matches!(oracle, OracleKind::ExactErrorVariant),
SeamKind::SideEffect | SeamKind::CallPresence => {
matches!(oracle, OracleKind::MockExpectation)
}
}
}
pub(crate) fn oracle_semantics_for(
kind: &OracleKind,
strength: &OracleStrength,
seam_kind: SeamKind,
) -> OracleSemantics {
if matches!(strength, OracleStrength::None) {
return OracleSemantics {
observes: "no recognized test oracle".to_string(),
missing: "an observable discriminator for this seam".to_string(),
upgrade_suggestion: Some(upgrade_suggestion_for_seam(seam_kind).to_string()),
};
}
match kind {
OracleKind::ExactValue => OracleSemantics {
observes: "the exact value or value pattern asserted by the test".to_string(),
missing: "no obvious value-shape discriminator gap under static scope".to_string(),
upgrade_suggestion: None,
},
OracleKind::ExactErrorVariant => OracleSemantics {
observes: "the exact error variant".to_string(),
missing: "error payload details if the changed behavior depends on payload".to_string(),
upgrade_suggestion: Some(
"assert the payload inside the matched error variant when payload behavior changed"
.to_string(),
),
},
OracleKind::WholeObjectEquality => OracleSemantics {
observes: "whole output object equality".to_string(),
missing:
"field-specific intent only if the whole-object assertion is too broad to review"
.to_string(),
upgrade_suggestion: None,
},
OracleKind::Snapshot => OracleSemantics {
observes: "a snapshot of rendered or debug output".to_string(),
missing: "a small explicit discriminator if the snapshot is too broad to review"
.to_string(),
upgrade_suggestion: Some(
"add an exact assertion for the changed field or value when the snapshot is broad"
.to_string(),
),
},
OracleKind::RelationalCheck => OracleSemantics {
observes: "a partial relationship or broad predicate about the result".to_string(),
missing: "the exact changed value or boundary discriminator".to_string(),
upgrade_suggestion: Some(upgrade_suggestion_for_seam(seam_kind).to_string()),
},
OracleKind::BroadError => OracleSemantics {
observes: "some error occurred".to_string(),
missing:
"the exact error variant or payload that would discriminate the changed behavior"
.to_string(),
upgrade_suggestion: Some(upgrade_suggestion_for_seam(seam_kind).to_string()),
},
OracleKind::SmokeOnly => OracleSemantics {
observes: "the call completed or returned a broad ok/some/none shape".to_string(),
missing: "the output value, error variant, field, effect, or call discriminator"
.to_string(),
upgrade_suggestion: Some(upgrade_suggestion_for_seam(seam_kind).to_string()),
},
OracleKind::MockExpectation => OracleSemantics {
observes: "an expected call, event, state write, or persistence effect".to_string(),
missing:
"effect payload, count, order, or state details if those discriminate the behavior"
.to_string(),
upgrade_suggestion: None,
},
OracleKind::Unknown => OracleSemantics {
observes: "no recognized concrete oracle shape".to_string(),
missing: "a discriminator assertion for the seam's observable behavior".to_string(),
upgrade_suggestion: Some(upgrade_suggestion_for_seam(seam_kind).to_string()),
},
}
}
fn upgrade_suggestion_for_seam(seam_kind: SeamKind) -> &'static str {
match seam_kind {
SeamKind::PredicateBoundary => {
"add an exact returned-value assertion at the missing boundary value"
}
SeamKind::ErrorVariant => "assert the exact error variant with matches! or assert_matches!",
SeamKind::ReturnValue => "add an exact returned-value assertion for the changed output",
SeamKind::FieldConstruction => {
"assert the specific output field that carries the changed behavior"
}
SeamKind::SideEffect => {
"assert the event, state write, persistence effect, or mock expectation payload"
}
SeamKind::MatchArm => "assert the exact enum or value produced by the changed match arm",
SeamKind::CallPresence => "assert the expected call happened with the relevant arguments",
}
}
fn related_test_grip(
seam: &RepoSeam,
test: &TestSummary,
reason: RelationReason,
) -> RelatedTestGrip {
let (kind, strength) = best_oracle(test, seam);
let summary = if matches!(strength, OracleStrength::None) {
"no oracle in test body".to_string()
} else {
match kind {
OracleKind::ExactValue => "exact value assertion".to_string(),
OracleKind::ExactErrorVariant => "exact error-variant assertion".to_string(),
OracleKind::WholeObjectEquality => "whole-object equality".to_string(),
OracleKind::Snapshot => "snapshot oracle".to_string(),
OracleKind::RelationalCheck => "relational check".to_string(),
OracleKind::BroadError => "is_err / broad-error assertion".to_string(),
OracleKind::SmokeOnly => "smoke-only assertion".to_string(),
OracleKind::MockExpectation => "mock expectation".to_string(),
OracleKind::Unknown => "no recognised oracle".to_string(),
}
};
let confidence = reason.confidence();
RelatedTestGrip {
test_name: test.name.clone(),
file: test.file.clone(),
line: test.start_line,
oracle_kind: kind,
oracle_strength: strength,
evidence_summary: summary,
relation_reason: reason,
relation_confidence: confidence,
}
}
fn best_oracle(test: &TestSummary, seam: &RepoSeam) -> (OracleKind, OracleStrength) {
let mut best_kind = OracleKind::Unknown;
let mut best_strength = OracleStrength::None;
for oracle in &test.assertions {
if oracle.strength.rank() > best_strength.rank() {
best_strength = oracle.strength.clone();
best_kind = oracle.kind.clone();
} else if oracle.strength.rank() == best_strength.rank()
&& oracle_kind_matches_seam(seam, &oracle.kind)
{
best_kind = oracle.kind.clone();
}
}
(best_kind, best_strength)
}
fn call_arguments(text: &str, callee: &str) -> Option<Vec<String>> {
let needle = format!("{callee}(");
let start = text.find(&needle)? + callee.len();
let inside = delimited_contents_at(text, start)?;
Some(split_top_level_commas(&inside))
}
fn delimited_contents_at(text: &str, start: usize) -> Option<String> {
let bytes = text.as_bytes();
let open = *bytes.get(start)?;
let close = match open {
b'(' => b')',
b'[' => b']',
b'{' => b'}',
_ => return None,
};
let open = char::from(open);
let close = char::from(close);
let mut depth = 0i32;
let mut in_string = false;
let mut escaped = false;
let mut content_start = None;
for (offset, ch) in text[start..].char_indices() {
let idx = start + offset;
if in_string {
if escaped {
escaped = false;
} else if ch == '\\' {
escaped = true;
} else if ch == '"' {
in_string = false;
}
continue;
}
match ch {
'"' => in_string = true,
c if c == open => {
depth += 1;
if depth == 1 {
content_start = Some(idx + ch.len_utf8());
}
}
c if c == close => {
depth -= 1;
if depth == 0 {
let content_start = content_start?;
return text.get(content_start..idx).map(str::to_string);
}
}
_ => {}
}
}
None
}
fn split_top_level_commas(input: &str) -> Vec<String> {
let mut out = Vec::new();
let mut depth = 0i32;
let mut current = String::new();
for ch in input.chars() {
match ch {
'(' | '[' | '{' => {
depth += 1;
current.push(ch);
}
')' | ']' | '}' => {
depth -= 1;
current.push(ch);
}
',' if depth == 0 => {
out.push(current.trim().to_string());
current.clear();
}
_ => current.push(ch),
}
}
let trailing = current.trim().to_string();
if !trailing.is_empty() {
out.push(trailing);
}
out
}
fn scalar_values(arg: &str) -> Vec<String> {
let trimmed = arg.trim().trim_end_matches([',', ';']);
if trimmed.is_empty() {
return Vec::new();
}
if trimmed.starts_with('"') || trimmed.starts_with('\'') {
return vec![trimmed.to_string()];
}
let numeric_body = trimmed.strip_prefix('-').unwrap_or(trimmed);
if !numeric_body.is_empty()
&& numeric_body
.chars()
.next()
.is_some_and(|c| c.is_ascii_digit())
&& numeric_body
.chars()
.all(|c| c.is_ascii_digit() || c == '_' || c == '.')
{
return vec![trimmed.to_string()];
}
if trimmed.contains("::")
&& trimmed
.chars()
.all(|c| c.is_alphanumeric() || c == '_' || c == ':')
{
return vec![trimmed.to_string()];
}
Vec::new()
}
fn sort_value_facts(values: &mut Vec<ValueFact>) {
values.sort_by(|a, b| {
a.line
.cmp(&b.line)
.then(a.value.cmp(&b.value))
.then(a.text.cmp(&b.text))
});
values.dedup_by(|a, b| a.line == b.line && a.value == b.value && a.text == b.text);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::analysis::rust_index::{RaRustSyntaxAdapter, RustSyntaxAdapter};
use crate::analysis::seam_inventory::inventory_seams_from_index;
fn index_from_files(files: &[(PathBuf, &str)]) -> Result<RustIndex, String> {
let adapter = RaRustSyntaxAdapter;
let mut index = RustIndex::default();
for (path, source) in files {
let facts = adapter.summarize_file(path, source)?;
index.tests.extend(facts.tests.iter().cloned());
index.functions.extend(facts.functions.iter().cloned());
index.files.insert(path.clone(), facts);
}
Ok(index)
}
#[test]
fn latency_trace_line_uses_repo_exposure_trace_shape() {
let line = latency_trace_line(
"evidence_for_seams_progress",
"processed_500_of_12337",
Duration::from_millis(42),
);
assert_eq!(
line,
"ripr_repo_exposure_latency phase=evidence_for_seams_progress status=processed_500_of_12337 duration_ms=42"
);
}
#[test]
fn latency_trace_line_can_report_evidence_context_start() {
let line = latency_trace_line("evidence_context", "start_seams_12337", Duration::ZERO);
assert_eq!(
line,
"ripr_repo_exposure_latency phase=evidence_context status=start_seams_12337 duration_ms=0"
);
}
#[test]
fn oracle_semantics_explains_broad_error_gap_and_upgrade() {
let semantics = oracle_semantics_for(
&OracleKind::BroadError,
&OracleStrength::Weak,
SeamKind::ErrorVariant,
);
assert_eq!(semantics.observes, "some error occurred");
assert_eq!(
semantics.missing,
"the exact error variant or payload that would discriminate the changed behavior"
);
assert_eq!(
semantics.upgrade_suggestion.as_deref(),
Some("assert the exact error variant with matches! or assert_matches!")
);
}
#[test]
fn oracle_semantics_explains_smoke_only_boundary_gap() {
let semantics = oracle_semantics_for(
&OracleKind::SmokeOnly,
&OracleStrength::Smoke,
SeamKind::PredicateBoundary,
);
assert_eq!(
semantics.observes,
"the call completed or returned a broad ok/some/none shape"
);
assert_eq!(
semantics.missing,
"the output value, error variant, field, effect, or call discriminator"
);
assert_eq!(
semantics.upgrade_suggestion.as_deref(),
Some("add an exact returned-value assertion at the missing boundary value")
);
}
#[test]
fn oracle_semantics_keeps_exact_value_without_extra_upgrade() {
let semantics = oracle_semantics_for(
&OracleKind::ExactValue,
&OracleStrength::Strong,
SeamKind::ReturnValue,
);
assert_eq!(
semantics.observes,
"the exact value or value pattern asserted by the test"
);
assert_eq!(
semantics.missing,
"no obvious value-shape discriminator gap under static scope"
);
assert!(semantics.upgrade_suggestion.is_none());
}
#[test]
fn oracle_semantics_covers_supported_oracle_families() {
let cases = [
(
OracleKind::ExactErrorVariant,
OracleStrength::Strong,
SeamKind::ErrorVariant,
"the exact error variant",
Some(
"assert the payload inside the matched error variant when payload behavior changed",
),
),
(
OracleKind::WholeObjectEquality,
OracleStrength::Strong,
SeamKind::ReturnValue,
"whole output object equality",
None,
),
(
OracleKind::Snapshot,
OracleStrength::Medium,
SeamKind::ReturnValue,
"a snapshot of rendered or debug output",
Some(
"add an exact assertion for the changed field or value when the snapshot is broad",
),
),
(
OracleKind::RelationalCheck,
OracleStrength::Weak,
SeamKind::MatchArm,
"a partial relationship or broad predicate about the result",
Some("assert the exact enum or value produced by the changed match arm"),
),
(
OracleKind::MockExpectation,
OracleStrength::Medium,
SeamKind::SideEffect,
"an expected call, event, state write, or persistence effect",
None,
),
(
OracleKind::Unknown,
OracleStrength::Unknown,
SeamKind::CallPresence,
"no recognized concrete oracle shape",
Some("assert the expected call happened with the relevant arguments"),
),
(
OracleKind::Unknown,
OracleStrength::None,
SeamKind::FieldConstruction,
"no recognized test oracle",
Some("assert the specific output field that carries the changed behavior"),
),
];
for (kind, strength, seam_kind, observes, upgrade) in cases {
let semantics = oracle_semantics_for(&kind, &strength, seam_kind);
assert_eq!(semantics.observes, observes);
assert_eq!(semantics.upgrade_suggestion.as_deref(), upgrade);
}
}
#[test]
fn opaque_custom_assertion_helper_stays_unknown_oracle() -> Result<(), String> {
let files: Vec<(PathBuf, &str)> = vec![
(
PathBuf::from("src/pricing.rs"),
"pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n",
),
(
PathBuf::from("tests/pricing_tests.rs"),
"#[test]\n\
fn opaque_helper() {\n\
let total = discounted_total(100, 100);\n\
assert_discount_is_valid(&total);\n\
}\n",
),
];
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|seam| seam.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
let first = evidence
.related_tests
.first()
.ok_or_else(|| "related test present".to_string())?;
assert_eq!(first.oracle_kind, OracleKind::Unknown);
assert_eq!(first.oracle_strength, OracleStrength::Unknown);
assert_eq!(evidence.discriminate.state, StageState::Unknown);
let semantics =
oracle_semantics_for(&first.oracle_kind, &first.oracle_strength, predicate.kind());
assert_eq!(semantics.observes, "no recognized concrete oracle shape");
assert_eq!(
semantics.upgrade_suggestion.as_deref(),
Some("add an exact returned-value assertion at the missing boundary value")
);
Ok(())
}
#[test]
fn duplicative_equality_assertion_stays_weak_oracle() -> Result<(), String> {
let files: Vec<(PathBuf, &str)> = vec![
(
PathBuf::from("src/pricing.rs"),
"pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n",
),
(
PathBuf::from("tests/pricing_tests.rs"),
"#[test]\n\
fn duplicated_equality() {\n\
let total = discounted_total(100, 100);\n\
assert_eq!(total, total);\n\
}\n",
),
];
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|seam| seam.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
let first = evidence
.related_tests
.first()
.ok_or_else(|| "related test present".to_string())?;
assert_eq!(first.oracle_kind, OracleKind::RelationalCheck);
assert_eq!(first.oracle_strength, OracleStrength::Weak);
assert_eq!(evidence.discriminate.state, StageState::Weak);
let semantics =
oracle_semantics_for(&first.oracle_kind, &first.oracle_strength, predicate.kind());
assert_eq!(
semantics.missing,
"the exact changed value or boundary discriminator"
);
Ok(())
}
#[test]
fn given_boundary_seam_when_tests_skip_equal_value_then_evidence_reports_missing_boundary_discriminator()
-> Result<(), String> {
let prod = PathBuf::from("src/pricing.rs");
let prod_src = r#"
pub fn discounted_total(amount: i32, threshold: i32) -> i32 {
if amount >= threshold { amount - 10 } else { amount }
}
"#;
let tests = PathBuf::from("tests/pricing_tests.rs");
let tests_src = r#"
#[test]
fn below_threshold_has_no_discount() {
assert_eq!(discounted_total(50, 100), 50);
}
#[test]
fn far_above_threshold_discounts() {
assert_eq!(discounted_total(10000, 100), 9990);
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "expected predicate seam".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
if evidence.related_tests.is_empty() {
return Err("expected reach evidence to find related tests".to_string());
}
if evidence.missing_discriminators.is_empty() {
return Err(format!(
"expected at least one missing-discriminator hypothesis for boundary seam `{}`",
predicate.expression()
));
}
let mentions_threshold = evidence
.missing_discriminators
.iter()
.any(|fact| fact.value.contains("threshold"));
if !mentions_threshold {
return Err(format!(
"missing-discriminator hypothesis should name the boundary identifier; got {:?}",
evidence
.missing_discriminators
.iter()
.map(|f| f.value.clone())
.collect::<Vec<_>>()
));
}
Ok(())
}
#[test]
fn given_boundary_seam_when_test_uses_equal_value_and_exact_assertion_then_discriminate_evidence_is_yes()
-> Result<(), String> {
let prod = PathBuf::from("src/pricing.rs");
let prod_src = r#"
pub fn discounted_total(amount: i32, threshold: i32) -> i32 {
if amount >= threshold { amount - 10 } else { amount }
}
"#;
let tests = PathBuf::from("tests/pricing_tests.rs");
let tests_src = r#"
#[test]
fn equality_boundary_returns_discount() {
assert_eq!(discounted_total(100, 100), 90);
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "expected predicate seam".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
if evidence.discriminate.state != StageState::Yes {
return Err(format!(
"expected discriminate=Yes, got {} ({})",
evidence.discriminate.state.as_str(),
evidence.discriminate.summary
));
}
Ok(())
}
#[test]
fn given_error_variant_seam_when_test_only_asserts_is_err_then_discriminate_evidence_is_weak()
-> Result<(), String> {
let prod = PathBuf::from("src/parse.rs");
let prod_src = r#"
pub enum AuthError { RevokedToken, Expired }
pub fn parse(value: &str) -> Result<i32, AuthError> {
if value.is_empty() {
return Err(AuthError::RevokedToken);
}
Ok(0)
}
"#;
let tests = PathBuf::from("tests/parse_tests.rs");
let tests_src = r#"
#[test]
fn parse_rejects_empty() {
assert!(parse("").is_err());
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/parse.rs")], &index);
let error_seam = seams
.iter()
.find(|s| s.kind() == SeamKind::ErrorVariant)
.ok_or_else(|| "expected error_variant seam".to_string())?;
let evidence = evidence_for_seam(error_seam, &index);
if evidence.discriminate.state != StageState::Weak
&& evidence.discriminate.state != StageState::Unknown
{
return Err(format!(
"expected discriminate=Weak|Unknown for is_err-only oracle, got {}",
evidence.discriminate.state.as_str()
));
}
Ok(())
}
#[test]
fn given_error_variant_seam_when_test_asserts_exact_variant_then_discriminate_evidence_is_yes()
-> Result<(), String> {
let prod = PathBuf::from("src/parse.rs");
let prod_src = r#"
pub enum AuthError { RevokedToken, Expired }
pub fn parse(value: &str) -> Result<i32, AuthError> {
if value.is_empty() {
return Err(AuthError::RevokedToken);
}
Ok(0)
}
"#;
let tests = PathBuf::from("tests/parse_tests.rs");
let tests_src = r#"
#[test]
fn parse_returns_revoked_token_on_empty() {
assert!(matches!(parse(""), Err(AuthError::RevokedToken)));
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/parse.rs")], &index);
let error_seam = seams
.iter()
.find(|s| s.kind() == SeamKind::ErrorVariant)
.ok_or_else(|| "expected error_variant seam".to_string())?;
let evidence = evidence_for_seam(error_seam, &index);
if evidence.discriminate.state != StageState::Yes {
return Err(format!(
"expected discriminate=Yes for matches!(...AuthError::RevokedToken), got {} ({})",
evidence.discriminate.state.as_str(),
evidence.discriminate.summary
));
}
Ok(())
}
#[test]
fn given_side_effect_seam_when_no_effect_observer_exists_then_observe_evidence_is_weak_or_unknown()
-> Result<(), String> {
let prod = PathBuf::from("src/publish.rs");
let prod_src = r#"
pub struct Service;
pub struct Event;
impl Service {
pub fn publish(&mut self, _event: Event) {}
}
pub fn publish_message(service: &mut Service, event: Event) {
service.publish(event);
}
"#;
let tests = PathBuf::from("tests/publish_tests.rs");
let tests_src = r#"
#[test]
fn publish_runs_without_panic() {
let mut service = Service;
publish_message(&mut service, Event);
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/publish.rs")], &index);
let side_effect = seams
.iter()
.find(|s| s.kind() == SeamKind::SideEffect)
.ok_or_else(|| {
format!(
"expected side_effect seam, got kinds: {:?}",
seams.iter().map(|s| s.kind().as_str()).collect::<Vec<_>>()
)
})?;
let evidence = evidence_for_seam(side_effect, &index);
match evidence.observe.state {
StageState::No | StageState::Weak | StageState::Unknown => Ok(()),
other => Err(format!(
"expected observe in {{No, Weak, Unknown}} for side-effect with no observer, got {}",
other.as_str()
)),
}
}
#[test]
fn given_side_effect_seam_when_event_assertion_exists_then_oracle_observes_effect()
-> Result<(), String> {
let prod = PathBuf::from("src/publish.rs");
let prod_src = r#"
pub struct Service;
pub struct Event;
impl Service {
pub fn publish(&mut self, _event: Event) {}
}
pub fn publish_message(service: &mut Service, event: Event) {
service.publish(event);
}
"#;
let tests = PathBuf::from("tests/publish_tests.rs");
let tests_src = r#"
#[test]
fn publish_records_event() {
let mut service = Service;
publish_message(&mut service, Event);
assert!(service.published_events().contains(&"message"));
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/publish.rs")], &index);
let side_effect = seams
.iter()
.find(|s| s.kind() == SeamKind::SideEffect)
.ok_or_else(|| "expected side_effect seam".to_string())?;
let evidence = evidence_for_seam(side_effect, &index);
assert_eq!(evidence.observe.state, StageState::Yes);
assert_eq!(evidence.propagate.state, StageState::Yes);
assert_eq!(evidence.discriminate.state, StageState::Yes);
assert!(
evidence
.related_tests
.iter()
.any(|test| test.oracle_kind == OracleKind::MockExpectation)
);
Ok(())
}
#[test]
fn given_opaque_helper_when_values_cannot_be_seen_then_evidence_records_static_limitation()
-> Result<(), String> {
let prod = PathBuf::from("src/pricing.rs");
let prod_src = r#"
pub fn discounted_total(amount: i32, threshold: i32) -> i32 {
if amount >= threshold { amount - 10 } else { amount }
}
"#;
let tests = PathBuf::from("tests/pricing_tests.rs");
let tests_src = r#"
fn make_input() -> (i32, i32) { (50, 100) }
#[test]
fn helper_path_runs() {
let (a, t) = make_input();
let _ = discounted_total(a, t);
assert!(true);
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "expected predicate seam".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
if evidence.activate.state == StageState::Yes {
return Err(format!(
"expected activate != Yes for helper-supplied values, got {} ({})",
evidence.activate.state.as_str(),
evidence.activate.summary
));
}
Ok(())
}
#[test]
fn evidence_for_seams_is_deterministic_across_input_order() -> Result<(), String> {
let prod = PathBuf::from("src/pricing.rs");
let prod_src = r#"
pub fn discounted_total(amount: i32, threshold: i32) -> i32 {
if amount >= threshold { amount - 10 } else { amount }
}
"#;
let tests = PathBuf::from("tests/pricing_tests.rs");
let tests_src = r#"
#[test]
fn boundary_case() {
assert_eq!(discounted_total(100, 100), 90);
}
#[test]
fn below_case() {
assert_eq!(discounted_total(50, 100), 50);
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let mut seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let forward_ids: Vec<String> = evidence_for_seams(&seams, &index)
.iter()
.map(|e| e.seam_id.as_str().to_string())
.collect();
seams.reverse();
let reversed_ids: Vec<String> = evidence_for_seams(&seams, &index)
.iter()
.map(|e| e.seam_id.as_str().to_string())
.collect();
if forward_ids != reversed_ids {
return Err(format!(
"evidence order is not stable:\n forward: {forward_ids:?}\n reversed: {reversed_ids:?}"
));
}
Ok(())
}
#[test]
fn evidence_for_seams_matches_single_seam_evidence_while_reusing_context() -> Result<(), String>
{
let prod = PathBuf::from("src/pricing.rs");
let prod_src = r#"
pub fn discounted_total(amount: i32, threshold: i32) -> i32 {
if amount >= threshold { amount - 10 } else { amount }
}
"#;
let tests = PathBuf::from("tests/pricing_tests.rs");
let tests_src = r#"
#[test]
fn equality_boundary_returns_discount() {
assert_eq!(discounted_total(100, 100), 90);
}
#[test]
fn import_only_mentions_owner() {
use crate::pricing::discounted_total;
assert_eq!(1, 1);
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let batch = evidence_for_seams(&seams, &index);
for seam in &seams {
let single = evidence_for_seam(seam, &index);
let Some(from_batch) = batch.iter().find(|entry| entry.seam_id == *seam.id()) else {
return Err(format!(
"batch evidence missing seam {}",
seam.id().as_str()
));
};
let single_json =
serde_json::to_string(&single).map_err(|err| format!("encode single: {err}"))?;
let batch_json =
serde_json::to_string(from_batch).map_err(|err| format!("encode batch: {err}"))?;
assert_eq!(single_json, batch_json);
}
Ok(())
}
#[test]
fn given_compact_evidence_when_direct_owner_call_reaches_error_seam_then_activation_is_yes()
-> Result<(), String> {
let prod = PathBuf::from("src/parse.rs");
let prod_src = r#"
pub enum AuthError { RevokedToken, Expired }
pub fn parse(value: &str) -> Result<i32, AuthError> {
if value.is_empty() {
return Err(AuthError::RevokedToken);
}
Ok(0)
}
"#;
let tests = PathBuf::from("tests/parse_tests.rs");
let tests_src = r#"
#[test]
fn parse_rejects_empty() {
assert!(parse("").is_err());
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/parse.rs")], &index);
let error_seam = seams
.iter()
.find(|s| s.kind() == SeamKind::ErrorVariant)
.ok_or_else(|| "expected error_variant seam".to_string())?;
let context = CompactGripContext::new(&index);
let evidence = compact_evidence_for_seam(error_seam, &context);
assert_eq!(evidence.reach.state, StageState::Yes);
assert_eq!(evidence.activate.state, StageState::Yes);
assert_eq!(evidence.related_tests.len(), 0);
assert_eq!(evidence.observed_values.len(), 0);
assert_eq!(evidence.missing_discriminators.len(), 0);
Ok(())
}
#[test]
fn given_full_evidence_when_no_arg_owner_call_reaches_return_seam_then_activation_is_yes()
-> Result<(), String> {
let prod = PathBuf::from("src/labels.rs");
let prod_src = r#"
pub fn device_labels() -> Vec<&'static str> {
Vec::new()
}
"#;
let tests = PathBuf::from("tests/labels_tests.rs");
let tests_src = r#"
#[test]
fn device_labels_start_empty() {
assert!(device_labels().is_empty());
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/labels.rs")], &index);
let return_seam = seams
.iter()
.find(|s| s.kind() == SeamKind::ReturnValue && s.expression().contains("Vec::new()"))
.ok_or_else(|| "expected Vec::new return_value seam".to_string())?;
let evidence = evidence_for_seam(return_seam, &index);
assert_eq!(evidence.reach.state, StageState::Yes);
assert_eq!(evidence.activate.state, StageState::Yes);
assert!(
evidence.observed_values.is_empty(),
"no-arg activation should not invent observed values: {:?}",
evidence.observed_values
);
assert!(
evidence
.activate
.summary
.contains("direct owner call for value-insensitive seam"),
"activation summary should explain the value-insensitive owner-call route: {}",
evidence.activate.summary
);
assert!(
evidence.missing_discriminators.is_empty(),
"return-value no-arg activation must not create boundary debt"
);
Ok(())
}
#[test]
fn given_value_insensitive_seam_when_only_affinity_related_then_activation_names_owner_call_limitation()
-> Result<(), String> {
let prod = PathBuf::from("src/labels.rs");
let prod_src = r#"
pub fn device_labels() -> Vec<&'static str> {
Vec::new()
}
"#;
let tests = PathBuf::from("tests/contract_tests.rs");
let tests_src = r#"
#[test]
fn return_value_contract_mentions_empty_output() {
let return_value = Vec::<&str>::new();
assert!(return_value.is_empty());
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/labels.rs")], &index);
let return_seam = seams
.iter()
.find(|s| s.kind() == SeamKind::ReturnValue && s.expression().contains("Vec::new()"))
.ok_or_else(|| "expected Vec::new return_value seam".to_string())?;
let evidence = evidence_for_seam(return_seam, &index);
assert_eq!(evidence.reach.state, StageState::Yes);
assert!(
evidence
.related_tests
.iter()
.any(|test| test.relation_reason == RelationReason::AssertionTargetAffinity),
"expected assertion-target affinity related test, got {:?}",
evidence.related_tests
);
assert_eq!(evidence.activate.state, StageState::Unknown);
assert!(
evidence
.activate
.summary
.contains("No direct owner call observed for value-insensitive seam"),
"activation summary should name the owner-call limitation, got {}",
evidence.activate.summary
);
assert!(
evidence.observed_values.is_empty(),
"affinity-only activation must not invent observed values: {:?}",
evidence.observed_values
);
Ok(())
}
#[test]
fn given_full_evidence_when_owner_call_with_opaque_args_reaches_return_seam_then_activation_is_yes()
-> Result<(), String> {
let prod = PathBuf::from("src/labels.rs");
let prod_src = r#"
pub fn render_label(input: &str) -> String {
input.to_string()
}
"#;
let tests = PathBuf::from("tests/labels_tests.rs");
let tests_src = r#"
fn fixture_label() -> String { "alpha".to_string() }
#[test]
fn render_label_matches_fixture() {
let label = fixture_label();
assert_eq!(render_label(&label), "alpha");
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/labels.rs")], &index);
let return_seam = seams
.iter()
.find(|s| s.kind() == SeamKind::ReturnValue && s.expression().contains("to_string"))
.ok_or_else(|| "expected to_string return_value seam".to_string())?;
let evidence = evidence_for_seam(return_seam, &index);
assert_eq!(evidence.reach.state, StageState::Yes);
assert_eq!(evidence.activate.state, StageState::Yes);
assert!(
evidence.observed_values.is_empty(),
"opaque direct-call arguments must not become observed values: {:?}",
evidence.observed_values
);
assert!(
evidence
.activate
.summary
.contains("direct owner call for value-insensitive seam"),
"activation summary should explain the value-insensitive owner-call route: {}",
evidence.activate.summary
);
assert!(
evidence.missing_discriminators.is_empty(),
"value-insensitive direct owner calls must not create boundary debt"
);
Ok(())
}
#[test]
fn given_compact_evidence_when_import_affinity_has_no_owner_call_then_activation_is_unknown()
-> Result<(), String> {
let prod = PathBuf::from("src/parse.rs");
let prod_src = r#"
pub enum AuthError { RevokedToken, Expired }
pub fn parse(value: &str) -> Result<i32, AuthError> {
if value.is_empty() {
return Err(AuthError::RevokedToken);
}
Ok(0)
}
"#;
let tests = PathBuf::from("tests/wrapper_tests.rs");
let tests_src = r#"
fn helper() -> Result<i32, AuthError> { Err(AuthError::RevokedToken) }
#[test]
fn wrapper_rejects_empty() {
use crate::parse;
assert!(helper().is_err());
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/parse.rs")], &index);
let error_seam = seams
.iter()
.find(|s| s.kind() == SeamKind::ErrorVariant)
.ok_or_else(|| "expected error_variant seam".to_string())?;
let context = CompactGripContext::new(&index);
let related = find_related_tests_compact(error_seam, &context);
assert_eq!(related.len(), 1);
assert_eq!(related[0].test.name, "wrapper_rejects_empty");
let evidence = compact_evidence_for_seam(error_seam, &context);
assert_eq!(evidence.reach.state, StageState::Yes);
assert_eq!(evidence.activate.state, StageState::Unknown);
Ok(())
}
#[test]
fn given_compact_related_tests_when_more_than_limit_match_then_results_are_capped()
-> Result<(), String> {
let prod = PathBuf::from("src/pricing.rs");
let prod_src = r#"
pub fn discounted_total(amount: i32, threshold: i32) -> i32 {
if amount >= threshold { amount - 10 } else { amount }
}
"#;
let mut tests_src = String::new();
for idx in 0..14 {
tests_src.push_str(&format!(
"#[test]\nfn direct_{idx:02}() {{ assert_eq!(discounted_total(100, 100), 90); }}\n"
));
}
let tests = PathBuf::from("tests/pricing_tests.rs");
let index = index_from_files(&[(prod, prod_src), (tests, tests_src.as_str())])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "expected predicate seam".to_string())?;
let context = CompactGripContext::new(&index);
let related = find_related_tests_compact(predicate, &context);
assert_eq!(related.len(), COMPACT_RELATED_TEST_LIMIT);
assert_eq!(related[0].test.name, "direct_00");
assert_eq!(
related[COMPACT_RELATED_TEST_LIMIT - 1].test.name,
"direct_11"
);
Ok(())
}
#[test]
fn given_compact_import_affinity_when_owner_only_in_comment_or_string_then_no_relation_is_found()
-> Result<(), String> {
let prod = PathBuf::from("src/parse.rs");
let prod_src = r#"
pub enum AuthError { RevokedToken, Expired }
pub fn parse(value: &str) -> Result<i32, AuthError> {
if value.is_empty() {
return Err(AuthError::RevokedToken);
}
Ok(0)
}
"#;
let tests = PathBuf::from("tests/noise_tests.rs");
let tests_src = r#"
#[test]
fn wrapper_mentions_owner_only_in_non_code() {
// use crate::parse;
let _path = "crate::parse";
assert!(helper().is_err());
}
"#;
let index = index_from_files(&[(prod, prod_src), (tests, tests_src)])?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/parse.rs")], &index);
let error_seam = seams
.iter()
.find(|s| s.kind() == SeamKind::ErrorVariant)
.ok_or_else(|| "expected error_variant seam".to_string())?;
let context = CompactGripContext::new(&index);
let related = find_related_tests_compact(error_seam, &context);
assert_eq!(related.len(), 0);
Ok(())
}
fn first_grip_for(
seam_file: &str,
prod_src: &str,
tests: &[(&str, &str)],
) -> Result<RelatedTestGrip, String> {
let mut files: Vec<(PathBuf, &str)> = vec![(PathBuf::from(seam_file), prod_src)];
for (path, src) in tests {
files.push((PathBuf::from(*path), *src));
}
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from(seam_file)], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
evidence
.related_tests
.into_iter()
.next()
.ok_or_else(|| "at least one related test".to_string())
}
#[test]
fn given_direct_owner_call_and_same_file_match_when_related_tests_are_ranked_then_direct_call_is_first()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let same_file_only = (
"tests/pricing_tests.rs",
"#[test] fn pricing_smoke() { assert_eq!(1, 1); }\n",
);
let direct = (
"tests/unrelated.rs",
"#[test] fn calls_owner() { assert_eq!(discounted_total(100, 100), 90); }\n",
);
let files: Vec<(PathBuf, &str)> = vec![
(PathBuf::from("src/pricing.rs"), prod_src),
(PathBuf::from(same_file_only.0), same_file_only.1),
(PathBuf::from(direct.0), direct.1),
];
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
let first = evidence
.related_tests
.first()
.ok_or_else(|| "at least one related test".to_string())?;
let labels: Vec<_> = evidence
.related_tests
.iter()
.map(|g| (g.test_name.clone(), g.relation_reason))
.collect();
assert_eq!(
first.relation_reason,
RelationReason::DirectOwnerCall,
"direct owner call must outrank same-file affinity; got grips {labels:?}"
);
assert_eq!(first.relation_confidence, RelationConfidence::High);
Ok(())
}
#[test]
fn given_owner_named_test_without_call_when_related_tests_are_ranked_then_confidence_is_medium()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/billing.rs",
"#[test] fn discounted_total_smoke() { assert_eq!(1, 1); }\n",
);
let grip = first_grip_for("src/pricing.rs", prod_src, &[test])?;
assert_eq!(grip.relation_reason, RelationReason::OwnerNamedTest);
assert_eq!(grip.relation_confidence, RelationConfidence::Medium);
Ok(())
}
#[test]
fn given_fixture_only_affinity_when_related_tests_are_ranked_then_confidence_is_low()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n\
pub fn make_quote() -> i32 { 100 }\n";
let test = (
"tests/integration.rs",
"#[test] fn quote_smoke() { let _ = make_quote(); assert!(true); }\n",
);
let grip = first_grip_for("src/pricing.rs", prod_src, &[test])?;
assert_eq!(grip.relation_reason, RelationReason::FixtureOwnerAffinity);
assert_eq!(grip.relation_confidence, RelationConfidence::Low);
Ok(())
}
#[test]
fn given_assertion_target_affinity_uses_token_aware_match_not_substring() -> Result<(), String>
{
let prod_src = "pub fn discounted_total(amount: i32, discount_threshold: i32) -> i32 \
{ if amount >= discount_threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/billing.rs",
"fn other() -> i32 { 0 }\n\
#[test] fn smoke() { let discount_threshold_factor = 5; assert_eq!(other(), 0); let _ = discount_threshold_factor; }\n",
);
let files: Vec<(PathBuf, &str)> = vec![
(PathBuf::from("src/pricing.rs"), prod_src),
(PathBuf::from(test.0), test.1),
];
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
for grip in &evidence.related_tests {
assert_ne!(
grip.relation_reason,
RelationReason::AssertionTargetAffinity,
"substring hit (`discount_threshold_factor`) must not match \
assertion_target_affinity; got {grip:?}"
);
}
Ok(())
}
#[test]
fn given_related_tests_with_same_confidence_when_sorted_then_order_is_stable_by_file_name_line()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test_a = (
"tests/zeta.rs",
"#[test] fn discounted_total_one() { assert_eq!(1, 1); }\n",
);
let test_b = (
"tests/alpha.rs",
"#[test] fn discounted_total_two() { assert_eq!(1, 1); }\n",
);
let files: Vec<(PathBuf, &str)> = vec![
(PathBuf::from("src/pricing.rs"), prod_src),
(PathBuf::from(test_a.0), test_a.1),
(PathBuf::from(test_b.0), test_b.1),
];
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
assert!(
evidence.related_tests.len() >= 2,
"expected at least 2 related tests, got {}",
evidence.related_tests.len()
);
assert_eq!(evidence.related_tests[0].file, Path::new("tests/alpha.rs"));
assert_eq!(evidence.related_tests[1].file, Path::new("tests/zeta.rs"));
Ok(())
}
#[test]
fn given_higher_confidence_related_test_when_sorted_then_it_comes_before_lower_confidence()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n\
pub fn make_quote() -> i32 { 100 }\n";
let fixture_user = (
"tests/a_first.rs",
"#[test] fn fx() { let _ = make_quote(); assert!(true); }\n",
);
let direct_caller = (
"tests/z_last.rs",
"#[test] fn caller() { assert_eq!(discounted_total(100, 100), 90); }\n",
);
let files: Vec<(PathBuf, &str)> = vec![
(PathBuf::from("src/pricing.rs"), prod_src),
(PathBuf::from(fixture_user.0), fixture_user.1),
(PathBuf::from(direct_caller.0), direct_caller.1),
];
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
let first = evidence
.related_tests
.first()
.ok_or_else(|| "at least one related test".to_string())?;
assert_eq!(first.relation_reason, RelationReason::DirectOwnerCall);
assert_eq!(first.relation_confidence, RelationConfidence::High);
Ok(())
}
#[test]
fn given_related_tests_with_same_relation_when_ranked_then_strong_oracle_precedes_smoke_oracle()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> Result<i32, ()> \
{ if amount >= threshold { Ok(amount - 10) } else { Ok(amount) } }\n";
let smoke = (
"tests/a_smoke.rs",
"#[test] fn smoke_owner_call() { assert!(discounted_total(100, 100).is_ok()); }\n",
);
let strong = (
"tests/z_exact.rs",
"#[test] fn exact_owner_call() { assert_eq!(discounted_total(100, 100).unwrap(), 90); }\n",
);
let files: Vec<(PathBuf, &str)> = vec![
(PathBuf::from("src/pricing.rs"), prod_src),
(PathBuf::from(smoke.0), smoke.1),
(PathBuf::from(strong.0), strong.1),
];
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
let first = evidence
.related_tests
.first()
.ok_or_else(|| "at least one related test".to_string())?;
assert_eq!(first.test_name, "exact_owner_call");
assert_eq!(first.relation_reason, RelationReason::DirectOwnerCall);
assert_eq!(first.oracle_strength, OracleStrength::Strong);
Ok(())
}
#[test]
fn given_related_tests_with_same_relation_and_oracle_when_ranked_then_activation_overlap_precedes_file_order()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let above = (
"tests/a_above.rs",
"#[test] fn above_boundary() { let actual = discounted_total(101, 100); assert_eq!(actual, 91); }\n",
);
let equality = (
"tests/z_equal.rs",
"#[test] fn equality_boundary() { let actual = discounted_total(100, 100); assert_eq!(actual, 90); }\n",
);
let files: Vec<(PathBuf, &str)> = vec![
(PathBuf::from("src/pricing.rs"), prod_src),
(PathBuf::from(above.0), above.1),
(PathBuf::from(equality.0), equality.1),
];
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
let first = evidence
.related_tests
.first()
.ok_or_else(|| "at least one related test".to_string())?;
assert_eq!(first.test_name, "equality_boundary");
assert_eq!(first.relation_reason, RelationReason::DirectOwnerCall);
assert_eq!(first.oracle_strength, OracleStrength::Strong);
Ok(())
}
#[test]
fn given_import_path_affinity_without_direct_call_when_related_tests_are_ranked_then_confidence_is_medium()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/integration_smoke.rs",
"#[test] fn smoke() { let _f = crate::pricing::discounted_total; assert_eq!(1, 1); }\n",
);
let grip = first_grip_for("src/pricing.rs", prod_src, &[test])?;
assert_eq!(grip.relation_reason, RelationReason::ImportPathAffinity);
assert_eq!(grip.relation_confidence, RelationConfidence::Medium);
Ok(())
}
#[test]
fn given_qualified_owner_path_only_in_comment_or_string_when_related_tests_are_ranked_then_import_path_affinity_does_not_fire()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let comment_only = (
"tests/integration_a.rs",
"#[test] fn smoke_a() { \
// see crate::pricing::discounted_total for background \n\
assert_eq!(1, 1); \
}\n",
);
let string_only = (
"tests/integration_b.rs",
"#[test] fn smoke_b() { \
let _doc = \"crate::pricing::discounted_total\"; \
let _ = _doc; assert_eq!(1, 1); \
}\n",
);
for (path, src) in [comment_only, string_only] {
let files: Vec<(PathBuf, &str)> = vec![
(PathBuf::from("src/pricing.rs"), prod_src),
(PathBuf::from(path), src),
];
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
for grip in &evidence.related_tests {
assert_ne!(
grip.relation_reason,
RelationReason::ImportPathAffinity,
"qualified path inside comment/string in {path} must not match \
ImportPathAffinity; got {grip:?}"
);
}
}
Ok(())
}
#[test]
fn given_owner_and_module_tokens_without_import_path_when_related_tests_are_ranked_then_import_path_affinity_does_not_fire()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/billing.rs",
"#[test] fn discounted_total_token_smoke() { \
let pricing = \"pricing\"; let discounted_total = 5; \
let _ = (pricing, discounted_total); assert_eq!(1, 1); \
}\n",
);
let files: Vec<(PathBuf, &str)> = vec![
(PathBuf::from("src/pricing.rs"), prod_src),
(PathBuf::from(test.0), test.1),
];
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
for grip in &evidence.related_tests {
assert_ne!(
grip.relation_reason,
RelationReason::ImportPathAffinity,
"token co-occurrence (`pricing` + `discounted_total` in body without \
`::` path syntax) must not match ImportPathAffinity; got {grip:?}"
);
}
Ok(())
}
#[test]
fn given_same_module_test_without_direct_call_when_related_tests_are_ranked_then_confidence_is_medium()
-> Result<(), String> {
let prod_src = "pub fn apply_discount(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing/integration.rs",
"#[test] fn module_neighbour() { assert_eq!(1, 1); }\n",
);
let files: Vec<(PathBuf, &str)> = vec![
(PathBuf::from("src/pricing/discount.rs"), prod_src),
(PathBuf::from(test.0), test.1),
];
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing/discount.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
let grip = evidence.related_tests.first().ok_or_else(|| {
"expected at least one related test for same-module pairing".to_string()
})?;
assert_eq!(grip.relation_reason, RelationReason::SameModule);
assert_eq!(grip.relation_confidence, RelationConfidence::Medium);
Ok(())
}
#[test]
fn relation_reason_as_str_priority_and_confidence_are_pinned_per_variant() {
let table = [
(
RelationReason::DirectOwnerCall,
"direct_owner_call",
0u8,
RelationConfidence::High,
),
(
RelationReason::AssertionTargetAffinity,
"assertion_target_affinity",
1,
RelationConfidence::High,
),
(
RelationReason::SameTestFile,
"same_test_file",
2,
RelationConfidence::Medium,
),
(
RelationReason::SameModule,
"same_module",
3,
RelationConfidence::Medium,
),
(
RelationReason::OwnerNamedTest,
"owner_named_test",
4,
RelationConfidence::Medium,
),
(
RelationReason::ImportPathAffinity,
"import_path_affinity",
5,
RelationConfidence::Medium,
),
(
RelationReason::FixtureOwnerAffinity,
"fixture_owner_affinity",
6,
RelationConfidence::Low,
),
];
for (reason, name, prio, conf) in table {
assert_eq!(reason.as_str(), name, "{reason:?}.as_str()");
assert_eq!(reason.priority(), prio, "{reason:?}.priority()");
assert_eq!(reason.confidence(), conf, "{reason:?}.confidence()");
}
}
#[test]
fn relation_confidence_as_str_and_rank_are_pinned_per_variant() {
let table = [
(RelationConfidence::High, "high", 0u8),
(RelationConfidence::Medium, "medium", 1),
(RelationConfidence::Low, "low", 2),
(RelationConfidence::Opaque, "opaque", 3),
];
for (conf, name, rank) in table {
assert_eq!(conf.as_str(), name, "{conf:?}.as_str()");
assert_eq!(conf.rank(), rank, "{conf:?}.rank()");
}
}
#[test]
fn required_discriminator_tokens_extracts_text_from_every_variant() {
use crate::analysis::seams::{ExpectedSink, RepoSeam, RequiredDiscriminator};
let make = |rd: RequiredDiscriminator| {
RepoSeam::new(
"src/x.rs",
"x::owner",
SeamKind::PredicateBoundary,
0,
1,
"irrelevant",
rd,
ExpectedSink::ReturnValue,
)
};
let cases: Vec<(RequiredDiscriminator, &str)> = vec![
(
RequiredDiscriminator::BoundaryValue {
description: "boundary_token".to_string(),
},
"boundary_token",
),
(
RequiredDiscriminator::ReturnValue {
description: "returnval_token".to_string(),
},
"returnval_token",
),
(
RequiredDiscriminator::ErrorVariant {
variant: "errvar_token".to_string(),
},
"errvar_token",
),
(
RequiredDiscriminator::FieldValue {
field: "fieldval_token".to_string(),
},
"fieldval_token",
),
(
RequiredDiscriminator::Effect {
sink: "effect_token".to_string(),
},
"effect_token",
),
(
RequiredDiscriminator::MatchArmTaken {
arm: "matcharm_token".to_string(),
},
"matcharm_token",
),
(
RequiredDiscriminator::CallSite {
target: "callsite_token".to_string(),
},
"callsite_token",
),
];
for (rd, expected_token) in cases {
let seam = make(rd.clone());
let tokens = required_discriminator_tokens(&seam);
assert!(
tokens.iter().any(|t| t == expected_token),
"{rd:?} -> tokens {tokens:?} must contain {expected_token}"
);
}
}
#[test]
fn same_test_file_accepts_stem_match_and_test_suffixes() {
assert!(same_test_file(Path::new("tests/foo.rs"), "foo"));
assert!(same_test_file(Path::new("tests/foo_test.rs"), "foo"));
assert!(same_test_file(Path::new("tests/foo_tests.rs"), "foo"));
assert!(!same_test_file(Path::new("tests/bar.rs"), "foo"));
assert!(!same_test_file(Path::new(""), "foo"));
}
#[test]
fn module_path_for_handles_every_root_shape() {
let cases: Vec<(&str, Option<&str>)> = vec![
("src/foo.rs", Some("foo")),
("tests/cli_smoke.rs", Some("cli_smoke")),
("crates/ripr/src/auth/login.rs", Some("auth/login")),
("crates/ripr/tests/integration.rs", Some("integration")),
("docs/note.rs", None),
("src/.rs", None),
];
for (input, expected) in cases {
let got = module_path_for(Path::new(input));
let want = expected.map(str::to_string);
assert_eq!(got, want, "module_path_for({input})");
}
}
#[test]
fn same_module_matches_parent_prefix_and_underscore_form() {
assert!(same_module("pricing/discount", "pricing/integration"));
assert!(same_module("a/b/c", "a_b/d"));
assert!(!same_module("flat", "anything"));
assert!(!same_module("pricing/discount", "billing/integration"));
}
#[test]
fn is_fixture_named_recognises_each_prefix_and_suffix() {
let positives = [
"fixture_quote",
"setup_db",
"make_quote",
"build_request",
"new_user",
"mock_clock",
"quote_fixture",
"quote_factory",
];
for name in positives {
assert!(is_fixture_named(name), "{name} should be fixture-named");
}
for name in ["compute_total", "discount", "verify"] {
assert!(
!is_fixture_named(name),
"{name} should NOT be fixture-named"
);
}
}
#[test]
fn given_assertion_target_token_in_test_assertion_when_related_tests_are_ranked_then_assertion_target_affinity_fires()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, discount_threshold: i32) -> i32 \
{ if amount >= discount_threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/billing.rs",
"fn other() -> i32 { 0 }\n\
#[test] fn smoke() { let discount_threshold = 5; assert_eq!(discount_threshold, 5); }\n",
);
let grip = first_grip_for("src/pricing.rs", prod_src, &[test])?;
assert_eq!(
grip.relation_reason,
RelationReason::AssertionTargetAffinity
);
assert_eq!(grip.relation_confidence, RelationConfidence::High);
Ok(())
}
#[test]
fn assertion_targets_seam_returns_false_for_empty_token_list() {
use crate::analysis::rust_index::TestFact;
let test = TestFact {
name: "synth".to_string(),
file: PathBuf::from("tests/x.rs"),
start_line: 1,
end_line: 5,
body: "assert_eq!(1, 1);".to_string(),
calls: Vec::new(),
assertions: Vec::new(),
literals: Vec::new(),
attrs: Vec::new(),
};
assert!(!assertion_targets_seam(&test, &[]));
}
#[test]
fn package_prefix_resolves_crates_and_nested_src_tests_layouts() {
assert_eq!(
package_prefix(Path::new("crates/ripr/src/auth/login.rs")).as_deref(),
Some("crates/ripr/")
);
assert_eq!(
package_prefix(Path::new("crates/ripr/tests/integration.rs")).as_deref(),
Some("crates/ripr/")
);
assert_eq!(
package_prefix(Path::new("workspaces/foo/src/auth/login.rs")).as_deref(),
Some("workspaces/foo/")
);
assert_eq!(package_prefix(Path::new("src/foo.rs")), None);
assert_eq!(package_prefix(Path::new("docs/note.rs")), None);
}
#[test]
fn given_owner_in_workspace_crate_when_test_is_in_other_crate_then_it_is_filtered_out()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let other_pkg_test = (
"crates/ripr_other/tests/x.rs",
"#[test] fn discounted_total_other_pkg() { assert_eq!(1, 1); }\n",
);
let files: Vec<(PathBuf, &str)> = vec![
(
PathBuf::from("crates/ripr_pricing/src/discount.rs"),
prod_src,
),
(PathBuf::from(other_pkg_test.0), other_pkg_test.1),
];
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(
&[PathBuf::from("crates/ripr_pricing/src/discount.rs")],
&index,
);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
for grip in &evidence.related_tests {
assert_ne!(
grip.file,
Path::new("crates/ripr_other/tests/x.rs"),
"test in unrelated package should be filtered by package_prefix; \
got {grip:?}"
);
}
Ok(())
}
#[test]
fn given_test_calls_helper_with_fixture_attribute_then_fixture_owner_affinity_fires()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n\
pub fn provide_quote() -> i32 {\n // #[fixture]\n 100\n}\n";
let test = (
"tests/integration.rs",
"#[test] fn quote_smoke() { let _ = provide_quote(); assert!(true); }\n",
);
let grip = first_grip_for("src/pricing.rs", prod_src, &[test])?;
assert_eq!(grip.relation_reason, RelationReason::FixtureOwnerAffinity);
Ok(())
}
fn observed_values_for(prod_src: &str, tests: &[(&str, &str)]) -> Result<Vec<String>, String> {
let mut files: Vec<(PathBuf, &str)> = vec![(PathBuf::from("src/pricing.rs"), prod_src)];
for (path, src) in tests {
files.push((PathBuf::from(*path), *src));
}
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
Ok(evidence
.observed_values
.into_iter()
.map(|v| v.value)
.collect())
}
#[test]
fn given_let_binding_values_when_owner_call_uses_identifiers_then_observed_values_are_resolved()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn at_threshold() { let amount = 100; let threshold = 100; \
assert_eq!(discounted_total(amount, threshold), 90); }\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.iter().any(|v| v == "100"),
"let-resolved 100 must appear in observed values; got {values:?}"
);
Ok(())
}
#[test]
fn given_boundary_owner_call_when_threshold_is_parameter_then_observed_values_stay_on_input_operand()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, discount_threshold: i32) -> i32 \
{ if amount >= discount_threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn below_threshold() { \
assert_eq!(discounted_total(50, 100), 50); \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert_eq!(
values,
vec!["50".to_string()],
"observed values should describe the tested input operand, not the boundary parameter"
);
Ok(())
}
#[test]
fn given_same_file_const_when_owner_call_uses_identifier_then_observed_value_is_resolved()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"const THRESHOLD: i32 = 100;\n\
#[test] fn at_threshold() { \
assert_eq!(discounted_total(THRESHOLD, THRESHOLD), 90); \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.iter().any(|v| v == "100"),
"const-resolved 100 must appear; got {values:?}"
);
Ok(())
}
#[test]
fn given_table_driven_cases_when_owner_call_uses_row_values_then_each_case_value_is_recorded()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn table() { \
for (amount, threshold, expected) in [(50, 100, 50), (100, 100, 90)] { \
assert_eq!(discounted_total(amount, threshold), expected); \
} \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.iter().any(|v| v == "50"),
"table row value 50 must appear; got {values:?}"
);
assert!(
values.iter().any(|v| v == "100"),
"table row value 100 must appear; got {values:?}"
);
Ok(())
}
#[test]
fn given_option_result_constructor_when_owner_call_uses_shape_then_inner_value_is_recorded()
-> Result<(), String> {
let prod_src = "pub fn process(value: Option<i32>, threshold: i32) -> i32 \
{ match value { Some(v) if v >= threshold => v - 10, _ => 0 } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn at_boundary() { \
assert_eq!(process(Some(100), 100), 90); \
}\n",
);
let mut files: Vec<(PathBuf, &str)> = vec![(PathBuf::from("src/pricing.rs"), prod_src)];
files.push((PathBuf::from(test.0), test.1));
let index = index_from_files(&files)?;
let seams = inventory_seams_from_index(&[PathBuf::from("src/pricing.rs")], &index);
let predicate = seams
.iter()
.find(|s| s.kind() == SeamKind::PredicateBoundary)
.ok_or_else(|| "predicate seam present".to_string())?;
let evidence = evidence_for_seam(predicate, &index);
let values: Vec<String> = evidence
.observed_values
.iter()
.map(|v| v.value.clone())
.collect();
assert!(
values.iter().any(|v| v == "100"),
"Some(100) must unwrap and contribute 100; got {values:?}"
);
Ok(())
}
#[test]
fn given_builder_methods_matching_parameter_tokens_then_observed_values_are_recorded()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, discount_threshold: i32) -> i32 \
{ if amount >= discount_threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn via_builder() { \
let q = Quote::new().amount(100).discount_threshold(100).build(); \
assert_eq!(discounted_total(q.amount, q.discount_threshold), 90); \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.iter().filter(|v| v.as_str() == "100").count() >= 1,
"builder method 100 must be recorded; got {values:?}"
);
Ok(())
}
#[test]
fn given_fixture_factory_override_methods_matching_seam_tokens_then_values_are_recorded()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn via_fixture_override() { \
let q = QuoteFixture::default().with_amount(100).with_threshold(100).build(); \
assert_eq!(discounted_total(q.amount, q.threshold), 90); \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.iter().filter(|v| v.as_str() == "100").count() >= 1,
"fixture override 100 must be recorded; got {values:?}"
);
Ok(())
}
#[test]
fn given_same_test_struct_literal_fields_when_owner_call_uses_projection_then_values_are_recorded()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn via_struct_literal() { \
let case = DiscountCase { amount: 100, threshold: 100 }; \
assert_eq!(discounted_total(case.amount, case.threshold), 90); \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.iter().any(|v| v == "100"),
"same-test struct literal field value 100 must be recorded; got {values:?}"
);
Ok(())
}
#[test]
fn given_same_line_struct_literal_after_owner_call_then_projection_values_stay_unresolved()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn via_same_line_late_literal() { \
assert_eq!(discounted_total(case.amount, case.threshold), 90); \
let case = DiscountCase { amount: 100, threshold: 100 }; \
let _ = case; \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.is_empty(),
"same-line literals introduced after the owner call must not produce fake values; got {values:?}"
);
Ok(())
}
#[test]
fn given_struct_literal_shadowed_after_owner_call_then_values_are_recorded()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test]\nfn via_later_shadowed_fixture() {\n \
let case = DiscountCase { amount: 100, threshold: 100 };\n \
assert_eq!(discounted_total(case.amount, case.threshold), 90);\n \
let case = make_discount_case();\n \
let _ = case;\n\
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.iter().any(|v| v == "100"),
"later-shadowed struct literal field value 100 must still be recorded for the earlier owner call; got {values:?}"
);
Ok(())
}
#[test]
fn given_struct_literal_after_owner_call_then_projection_values_stay_unresolved()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test]\nfn via_late_literal_fixture() {\n \
assert_eq!(discounted_total(case.amount, case.threshold), 90);\n \
let case = DiscountCase { amount: 100, threshold: 100 };\n \
let _ = case;\n\
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.is_empty(),
"literal struct fields introduced after the owner call must not produce fake values; got {values:?}"
);
Ok(())
}
#[test]
fn given_struct_literal_field_mutated_before_owner_call_then_values_stay_unresolved()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test]\nfn via_mutated_fixture() {\n \
let case = DiscountCase { amount: 100, threshold: 100 };\n \
case.amount = make_amount();\n \
assert_eq!(discounted_total(case.amount, case.threshold), 90);\n\
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.is_empty(),
"mutated struct literal fields must not reuse stale literal values; got {values:?}"
);
Ok(())
}
#[test]
fn given_struct_literal_field_mutated_after_owner_call_then_values_are_recorded()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test]\nfn via_later_mutated_fixture() {\n \
let case = DiscountCase { amount: 100, threshold: 100 };\n \
assert_eq!(discounted_total(case.amount, case.threshold), 90);\n \
case.amount = make_amount();\n\
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.iter().any(|v| v == "100"),
"later-mutated struct literal field value 100 must still be recorded for the earlier owner call; got {values:?}"
);
Ok(())
}
#[test]
fn given_helper_built_struct_when_owner_call_uses_projection_then_values_stay_unresolved()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn via_helper_fixture() { \
let case = make_discount_case(); \
assert_eq!(discounted_total(case.amount, case.threshold), 90); \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.is_empty(),
"helper-built struct projections must not produce fake values; got {values:?}"
);
Ok(())
}
#[test]
fn given_shadowed_struct_literal_when_owner_call_uses_projection_then_values_stay_unresolved()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn via_shadowed_fixture() { \
let case = DiscountCase { amount: 100, threshold: 100 }; \
let case = make_discount_case(); \
assert_eq!(discounted_total(case.amount, case.threshold), 90); \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.is_empty(),
"shadowed struct projections must not reuse stale literal fields; got {values:?}"
);
Ok(())
}
#[test]
fn given_fixture_parameter_and_later_same_name_struct_literal_then_values_stay_unresolved()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[rstest] fn via_fixture_param(case: DiscountCase) { \
assert_eq!(discounted_total(case.amount, case.threshold), 90); \
let case = DiscountCase { amount: 100, threshold: 100 }; \
let _ = case; \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.is_empty(),
"fixture parameter projections must not resolve from later literals; got {values:?}"
);
Ok(())
}
#[test]
fn given_for_loop_shadowing_struct_literal_then_values_stay_unresolved() -> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn via_shadowing_loop() { \
let case = DiscountCase { amount: 100, threshold: 100 }; \
for case in helper_cases() { \
assert_eq!(discounted_total(case.amount, case.threshold), 90); \
} \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.is_empty(),
"loop-shadowed struct projections must not reuse stale literal fields; got {values:?}"
);
Ok(())
}
#[test]
fn given_let_pattern_shadowing_struct_literal_then_values_stay_unresolved() -> Result<(), String>
{
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn via_shadowing_let_pattern() { \
let case = DiscountCase { amount: 100, threshold: 100 }; \
let Some(case) = make_discount_case() else { return; }; \
assert_eq!(discounted_total(case.amount, case.threshold), 90); \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.is_empty(),
"let-pattern-shadowed projections must not reuse stale literal fields; got {values:?}"
);
Ok(())
}
#[test]
fn given_builder_method_with_unrelated_name_then_value_is_not_counted_for_seam_activation()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn via_unrelated_builder() { \
let _q = Foo::new().with_seed(42).build(); \
assert_eq!(discounted_total(50, 100), 50); \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
!values.iter().any(|v| v == "42"),
"unrelated builder literal 42 must NOT count; got {values:?}"
);
Ok(())
}
#[test]
fn given_unrelated_string_literal_mentions_value_when_extracting_values_then_no_observed_discriminator_is_recorded()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn string_only() { \
let _doc = \"threshold = 100\"; \
let unresolved = make_amount(); \
assert_eq!(discounted_total(unresolved, unresolved), 0); \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
!values.iter().any(|v| v == "100"),
"string literal 100 must NOT be observed; got {values:?}"
);
Ok(())
}
#[test]
fn given_shared_fixture_module_constant_when_extracting_v2_values_then_no_cross_file_value_is_resolved()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let common = (
"tests/common/mod.rs",
"pub const SHARED_THRESHOLD: i32 = 100;\n",
);
let test = (
"tests/pricing_tests.rs",
"#[test] fn cross_file() { \
assert_eq!(discounted_total(SHARED_THRESHOLD, SHARED_THRESHOLD), 90); \
}\n",
);
let values = observed_values_for(prod_src, &[test, common])?;
assert!(
!values.iter().any(|v| v == "100"),
"cross-file SHARED_THRESHOLD = 100 must NOT resolve in v2; got {values:?}"
);
Ok(())
}
#[test]
fn given_let_binding_shadowed_by_comment_when_extracting_then_real_binding_wins()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn at_threshold() { \
// let amount = 999; let threshold = 999;\n\
let amount = 100; let threshold = 100; \
assert_eq!(discounted_total(amount, threshold), 90); \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.iter().any(|v| v == "100"),
"real let binding 100 must be observed; got {values:?}"
);
assert!(
!values.iter().any(|v| v == "999"),
"commented-out let binding 999 must NOT be observed; got {values:?}"
);
Ok(())
}
#[test]
fn given_unresolved_identifier_arg_when_extracting_values_then_no_observed_value_is_recorded()
-> Result<(), String> {
let prod_src = "pub fn discounted_total(amount: i32, threshold: i32) -> i32 \
{ if amount >= threshold { amount - 10 } else { amount } }\n";
let test = (
"tests/pricing_tests.rs",
"#[test] fn opaque() { \
let amount = make_amount(); \
let threshold = make_threshold(); \
assert_eq!(discounted_total(amount, threshold), 0); \
}\n",
);
let values = observed_values_for(prod_src, &[test])?;
assert!(
values.is_empty()
|| values
.iter()
.all(|v| !matches!(v.as_str(), "100" | "0" | "make_amount")),
"opaque args must not produce a fake observed value; got {values:?}"
);
Ok(())
}
}