use crate::e2e::fixture::Assertion;
use super::{SkipVerdict, peek_skip_records};
const COMMENT_OPENERS: &[&str] = &["//", "#", "/*"];
pub(crate) fn has_executable_line(body: &str) -> bool {
body.lines().any(|line| {
let trimmed = line.trim();
!trimmed.is_empty() && !COMMENT_OPENERS.iter().any(|opener| trimmed.starts_with(opener))
})
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum InertCause {
UnresolvedFieldPath,
AwaitedOrLimited,
RenderedNothing,
}
#[derive(Debug, Clone)]
pub(crate) struct InertExample {
pub(crate) language: String,
pub(crate) fixture_id: String,
pub(crate) markers: usize,
pub(crate) cause: InertCause,
}
impl InertExample {
pub(crate) fn reason(&self) -> String {
match self.cause {
InertCause::UnresolvedFieldPath => format!(
"alef resolved no assertion for fixture `{}`: {} assertion(s) name a field path \
the availability oracle rejected",
self.fixture_id, self.markers,
),
InertCause::AwaitedOrLimited => format!(
"alef rendered no runnable expectation for fixture `{}`: all {} declared \
assertion(s) were skipped (see the markers above)",
self.fixture_id, self.markers,
),
InertCause::RenderedNothing => format!(
"alef rendered no runnable expectation for fixture `{}`: its declared assertions \
produced no check and no skip marker",
self.fixture_id,
),
}
}
}
thread_local! {
static INERT_LEDGER: std::cell::RefCell<Vec<InertExample>> = const { std::cell::RefCell::new(Vec::new()) };
}
pub(crate) fn take_inert_examples() -> Vec<InertExample> {
INERT_LEDGER.with(|ledger| std::mem::take(&mut *ledger.borrow_mut()))
}
pub(crate) fn inert_summary(records: &[InertExample]) -> Option<String> {
if records.is_empty() {
return None;
}
let count = |cause: InertCause| records.iter().filter(|record| record.cause == cause).count();
let languages: std::collections::BTreeSet<&str> = records.iter().map(|record| record.language.as_str()).collect();
Some(format!(
"{} generated example(s) across {} language(s) had no runnable expectation and were \
refused rather than published as passing tests: {} with an unresolved field path, {} \
awaiting alef support or blocked by a language limit, {} that rendered nothing at all",
records.len(),
languages.len(),
count(InertCause::UnresolvedFieldPath),
count(InertCause::AwaitedOrLimited),
count(InertCause::RenderedNothing),
))
}
pub(crate) fn record_refusal(refusal: &InertExample) {
INERT_LEDGER.with(|ledger| ledger.borrow_mut().push(refusal.clone()));
}
pub(crate) fn refusal_body(markers: &str, statement: &str) -> String {
let mut out = String::new();
for line in markers.lines() {
if line.trim().is_empty() {
continue;
}
out.push_str(line.trim_end());
out.push('\n');
}
out.push_str(statement);
if !out.ends_with('\n') {
out.push('\n');
}
out
}
pub(crate) fn inert_verdict(
assertions_body: &str,
language: &str,
fixture_id: &str,
assertions: &[Assertion],
) -> Option<InertExample> {
if assertions.is_empty() || has_executable_line(assertions_body) {
return None;
}
let records = peek_skip_records(language, fixture_id);
let cause = if records
.iter()
.any(|record| record.verdict == SkipVerdict::UnacknowledgedGap)
{
InertCause::UnresolvedFieldPath
} else if records.is_empty() {
InertCause::RenderedNothing
} else {
InertCause::AwaitedOrLimited
};
Some(InertExample {
language: language.to_string(),
fixture_id: fixture_id.to_string(),
markers: records.len(),
cause,
})
}
#[cfg(test)]
mod tests {
use super::{
InertCause, has_executable_line, inert_summary, inert_verdict, record_refusal, refusal_body,
take_inert_examples,
};
use crate::e2e::codegen::field_skip::FieldSkip;
use crate::e2e::fixture::Assertion;
fn assertion(field: &str) -> Assertion {
Assertion {
assertion_type: "equals".to_string(),
field: Some(field.to_string()),
value: Some(serde_json::json!("x")),
..Default::default()
}
}
#[test]
fn a_body_with_one_real_expectation_is_not_refused() {
let _ = take_inert_examples();
let body = format!(
" # skipped: {}\n expect(result.title).to eq('x')\n",
FieldSkip::NotAvailableOnResultType.message("metadata.title")
);
assert!(has_executable_line(&body), "control: the rendered check must be seen");
assert!(
inert_verdict(&body, "ruby", "control_fixture", &[assertion("metadata.title")]).is_none(),
"an example with a real expectation must be published unchanged"
);
assert!(
take_inert_examples().is_empty(),
"nothing may be recorded for a live example"
);
}
#[test]
fn a_body_of_only_skip_markers_is_refused() {
let _ = take_inert_examples();
let body = format!(
" # skipped: {}\n # skipped: {}\n",
FieldSkip::StreamingAssertionOnUnsupportedField.message("stream.has_page_event"),
FieldSkip::StreamingAssertionOnUnsupportedField.message("stream_complete"),
);
assert!(!has_executable_line(&body), "a comment-only body executes nothing");
let refusal = inert_verdict(&body, "ruby", "stream_fixture", &[assertion("stream.has_page_event")])
.expect("an all-markers example must be refused");
assert_eq!(refusal.fixture_id, "stream_fixture");
record_refusal(&refusal);
assert_eq!(take_inert_examples().len(), 1, "the refusal must be recorded once");
}
#[test]
fn an_empty_body_with_declared_assertions_is_refused_as_rendered_nothing() {
let _ = take_inert_examples();
let refusal =
inert_verdict("", "ruby", "silent_fixture", &[assertion("metadata.title")]).expect("must be refused");
assert_eq!(refusal.cause, InertCause::RenderedNothing);
assert_eq!(refusal.markers, 0);
let _ = take_inert_examples();
}
#[test]
fn a_fixture_that_declares_no_assertions_is_never_refused() {
let _ = take_inert_examples();
assert!(inert_verdict("", "ruby", "smoke_fixture", &[]).is_none());
assert!(take_inert_examples().is_empty());
}
#[test]
fn comment_openers_do_not_swallow_real_statements() {
assert!(has_executable_line(" expect(x).to eq(1)\n"));
assert!(has_executable_line(" assert result is not None\n"));
assert!(has_executable_line("\t\tAssert.Equal(1, x);\n"));
assert!(!has_executable_line(" // skipped: nothing here\n\n"));
assert!(!has_executable_line(" /* skipped: nothing here */\n"));
}
#[test]
fn a_refusal_body_carries_every_marker_line_before_the_statement() {
let body = refusal_body(
" // skipped: first\n\n // skipped: second \n",
" skip 'nothing left to assert'",
);
assert_eq!(
body, " // skipped: first\n // skipped: second\n skip 'nothing left to assert'\n",
"blank lines are dropped, trailing space trimmed, and the statement lands last"
);
}
#[test]
fn the_summary_counts_each_cause_separately() {
let _ = take_inert_examples();
record_refusal(&inert_verdict("", "ruby", "one", &[assertion("a")]).expect("refused"));
record_refusal(&inert_verdict("", "python", "two", &[assertion("b")]).expect("refused"));
let records = take_inert_examples();
let summary = inert_summary(&records).expect("two refusals must summarise");
assert!(summary.starts_with("2 generated example(s)"), "got: {summary}");
assert!(inert_summary(&[]).is_none());
}
#[test]
fn a_body_with_only_an_assertion_type_skip_marker_is_awaited_or_limited_not_rendered_nothing() {
let _ = crate::e2e::codegen::take_skip_records();
let _ = take_inert_examples();
let body = " // skipped: assertion type 'equals' has no accessor for error field \
error.status_code in this backend\n";
let declared = [assertion("error.status_code")];
crate::e2e::codegen::fail_on_unavailable_field_markers(body, "go", "type_skip_fixture", &declared);
crate::e2e::codegen::fail_on_unsupported_assertion_type_markers(body, "go", "type_skip_fixture");
let refusal =
inert_verdict(body, "go", "type_skip_fixture", &declared).expect("an all-markers body must be refused");
assert_eq!(
refusal.cause,
InertCause::AwaitedOrLimited,
"the assertion-type marker must be on the ledger, not silently dropped"
);
assert_eq!(
refusal.markers, 1,
"the field funnel must not also count the type-skip wording"
);
let _ = crate::e2e::codegen::take_skip_records();
let _ = take_inert_examples();
}
#[test]
fn without_the_type_funnel_the_same_body_is_misclassified_as_rendered_nothing() {
let _ = crate::e2e::codegen::take_skip_records();
let _ = take_inert_examples();
let body = " // skipped: assertion type 'equals' has no accessor for error field \
error.status_code in this backend\n";
let declared = [assertion("error.status_code")];
crate::e2e::codegen::fail_on_unavailable_field_markers(body, "go", "unpaired_fixture", &declared);
let refusal =
inert_verdict(body, "go", "unpaired_fixture", &declared).expect("an all-markers body must be refused");
assert_eq!(refusal.cause, InertCause::RenderedNothing);
assert_eq!(refusal.markers, 0);
let _ = crate::e2e::codegen::take_skip_records();
let _ = take_inert_examples();
}
}