use super::{
SkipVerdict, fail_on_unavailable_field_markers, is_falsy_flag, skip_summary, strict_assertion_failure,
take_skip_records,
};
use crate::e2e::fixture::{Assertion, AssertionSkip, AssertionSkipDirective, AssertionSkipKind};
fn verdicts_for(body: &str, language: &str, assertions: &[Assertion]) -> Vec<SkipVerdict> {
let _ = take_skip_records();
fail_on_unavailable_field_markers(body, language, "smoke", assertions);
take_skip_records().into_iter().map(|r| r.verdict).collect()
}
fn strict_error_for(body: &str, language: &str, fixture_id: &str, assertions: &[Assertion]) -> Option<String> {
let _ = take_skip_records();
fail_on_unavailable_field_markers(body, language, fixture_id, assertions);
strict_assertion_failure(&take_skip_records(), true).map(|error| format!("{error:#}"))
}
fn assertion_on(field: &str, skip: Option<AssertionSkip>) -> Assertion {
Assertion {
field: Some(field.to_string()),
skip,
..Assertion::default()
}
}
#[test]
fn non_strict_is_a_noop_even_on_a_marker_body() {
let _ = take_skip_records();
fail_on_unavailable_field_markers(
" # skipped: field 'chunks' not available on result type\n",
"python",
"widget_smoke",
&[],
);
assert!(strict_assertion_failure(&take_skip_records(), false).is_none());
}
#[test]
fn strict_fails_loudly_naming_fixture_and_field() {
let error = strict_error_for(
" # skipped: field 'chunks' not available on result type\n",
"python",
"widget_smoke",
&[],
)
.expect("an unresolved field must fail under strict");
assert!(
error.contains("[python] fixture `widget_smoke`: field `chunks`"),
"got: {error}"
);
}
#[test]
fn an_unmappable_field_is_fatal_by_default() {
let _ = take_skip_records();
let body = " // skipped: field 'strategy.crawl_order' not available on result type\n";
fail_on_unavailable_field_markers(
body,
"go",
"traversal_order",
&[assertion_on("strategy.crawl_order", None)],
);
let error = strict_assertion_failure(&take_skip_records(), super::strict_assertions_enabled())
.expect("an unmappable field must fail generation by default");
assert!(
format!("{error:#}").contains("field `strategy.crawl_order`"),
"got: {error:#}"
);
}
#[test]
fn strict_error_lists_every_offender() {
let _ = take_skip_records();
fail_on_unavailable_field_markers(
" // skipped: field 'alpha' not available on result type\n\
\x20 // skipped: field 'beta' not available on result type\n",
"go",
"smoke",
&[],
);
let error = strict_assertion_failure(&take_skip_records(), true).expect("two gaps must fail");
let rendered = format!("{error:#}");
assert!(rendered.contains("field `alpha`"), "got: {rendered}");
assert!(rendered.contains("field `beta`"), "got: {rendered}");
assert!(rendered.starts_with("2 e2e assertion(s)"), "got: {rendered}");
}
#[test]
fn an_explicitly_opted_out_field_skips_and_is_counted() {
let _ = take_skip_records();
let body = " // skipped: field 'strategy.crawl_order' not available on result type\n";
let assertions = [assertion_on(
"strategy.crawl_order",
Some(AssertionSkip::Scoped(AssertionSkipDirective {
languages: vec!["go".to_string()],
kind: AssertionSkipKind::LanguageLimitation,
reason: Some("traversal order is not exposed on the Go result".to_string()),
})),
)];
fail_on_unavailable_field_markers(body, "go", "traversal_order", &assertions);
let records = take_skip_records();
assert!(
strict_assertion_failure(&records, true).is_none(),
"an acknowledged skip must not fail generation"
);
assert_eq!(records.len(), 1, "the acknowledged skip must still be recorded");
assert_eq!(
records[0].verdict,
SkipVerdict::Acknowledged(AssertionSkipKind::LanguageLimitation)
);
assert_eq!(records[0].field, "strategy.crawl_order");
let summary = skip_summary(&records).expect("an acknowledged skip must still produce a summary");
assert_eq!(
summary,
"1 assertion(s) skipped across 1 fixture(s): 0 awaiting alef support, \
1 language/ABI limitation(s), 0 unresolved field path(s)"
);
}
#[test]
fn a_not_representable_opt_out_is_attributed_to_alef() {
let _ = take_skip_records();
let body = " // skipped: field 'is_error' not available on result type\n";
let assertions = [assertion_on(
"is_error",
Some(AssertionSkip::Scoped(AssertionSkipDirective {
languages: Vec::new(),
kind: AssertionSkipKind::NotRepresentable,
reason: Some("`is_error` is an assertion kind, not a field path".to_string()),
})),
)];
fail_on_unavailable_field_markers(body, "go", "error_smoke", &assertions);
let records = take_skip_records();
assert!(strict_assertion_failure(&records, true).is_none());
let summary = skip_summary(&records).expect("summary");
assert!(summary.contains("1 awaiting alef support"), "got: {summary}");
assert!(summary.contains("0 language/ABI limitation(s)"), "got: {summary}");
}
#[test]
fn a_bare_true_skip_covers_every_language() {
let body = " // skipped: field 'chunks' not available on result type\n";
let assertions = [assertion_on("chunks", Some(AssertionSkip::All(true)))];
let expected = [SkipVerdict::Acknowledged(AssertionSkipKind::NotRepresentable)];
assert_eq!(verdicts_for(body, "dart", &assertions), expected);
assert_eq!(verdicts_for(body, "ruby", &assertions), expected);
}
#[test]
fn a_scoped_skip_does_not_cover_other_languages() {
let body = " // skipped: field 'chunks' not available on result type\n";
let assertions = [assertion_on(
"chunks",
Some(AssertionSkip::Scoped(AssertionSkipDirective {
languages: vec!["dart".to_string()],
kind: AssertionSkipKind::LanguageLimitation,
reason: None,
})),
)];
assert_eq!(
verdicts_for(body, "dart", &assertions),
vec![SkipVerdict::Acknowledged(AssertionSkipKind::LanguageLimitation)]
);
assert_eq!(
verdicts_for(body, "go", &assertions),
vec![SkipVerdict::UnacknowledgedGap],
"an opt-out scoped to dart must leave go fatal"
);
}
#[test]
fn a_false_skip_does_not_opt_out() {
let body = " // skipped: field 'chunks' not available on result type\n";
let assertions = [assertion_on("chunks", Some(AssertionSkip::All(false)))];
assert_eq!(
verdicts_for(body, "go", &assertions),
vec![SkipVerdict::UnacknowledgedGap]
);
}
#[test]
fn a_skip_on_another_field_does_not_opt_this_one_out() {
let body = " // skipped: field 'chunks' not available on result type\n";
let assertions = [assertion_on("usage", Some(AssertionSkip::All(true)))];
assert_eq!(
verdicts_for(body, "go", &assertions),
vec![SkipVerdict::UnacknowledgedGap]
);
}
#[test]
fn a_body_with_no_marker_records_nothing() {
assert!(verdicts_for(" assert result.count == 1\n", "python", &[]).is_empty());
}
#[test]
fn unsupported_assertion_type_comments_are_not_recorded() {
assert!(
verdicts_for(
" // skipped: unsupported assertion type on synthetic field 'embeddings'\n",
"go",
&[]
)
.is_empty()
);
}
#[test]
fn language_suffixed_not_available_comments_stay_fatal() {
let error = strict_error_for(
"\t// skipped: field 'keywords' not available on Go ProcessingResult\n",
"go",
"smoke",
&[],
)
.expect("a binding-type resolution miss is a gap");
assert!(error.contains("field `keywords`"), "got: {error}");
}
#[test]
fn streaming_field_assertions_await_alef_support_rather_than_failing() {
let body = " // streaming assertion on unsupported field 'has_page_event'\n";
assert_eq!(
verdicts_for(body, "csharp", &[]),
vec![SkipVerdict::AwaitingGeneratorSupport]
);
assert!(
strict_error_for(body, "csharp", "stream_smoke", &[]).is_none(),
"a missing generator feature must not fail a consumer's build"
);
}
#[test]
fn every_streaming_wording_awaits_alef_support() {
for (body, language) in [
(
" # skipped: streaming field 'stream.items': no python accessor\n",
"python",
),
(
" // skipped: field 'stream.items' not available on streaming result type\n",
"go",
),
] {
assert_eq!(
verdicts_for(body, language, &[]),
vec![SkipVerdict::AwaitingGeneratorSupport],
"{language} streaming wording must be alef's debt, not the consumer's"
);
}
}
#[test]
fn summary_separates_alef_backlog_from_binding_limits() {
let _ = take_skip_records();
fail_on_unavailable_field_markers(
" // streaming assertion on unsupported field 'has_page_event'\n",
"csharp",
"stream_smoke",
&[],
);
fail_on_unavailable_field_markers(
" // skipped: field 'usage.tokens' references a field or type excluded from \
the Swift binding\n",
"swift",
"excluded_smoke",
&[],
);
let summary = skip_summary(&take_skip_records()).expect("summary");
assert_eq!(
summary,
"2 assertion(s) skipped across 2 fixture(s): 1 awaiting alef support, \
1 language/ABI limitation(s), 0 unresolved field path(s)"
);
}
#[test]
fn tagged_union_boundary_wordings_are_counted_not_fatal() {
let dart = " // skipped: field 'payload.tags' crosses a tagged-union variant boundary \
(not expressible in Dart)\n";
assert_eq!(verdicts_for(dart, "dart", &[]), vec![SkipVerdict::Limitation]);
let swift = " // skipped: field 'payload.tags' crosses a tagged-union variant boundary \
(not expressible in Swift)\n";
assert_eq!(verdicts_for(swift, "swift", &[]), vec![SkipVerdict::Limitation]);
}
#[test]
fn the_swift_json_bridged_count_wording_is_counted_not_fatal() {
let body = format!(
" // skipped: {}\n",
super::field_skip::FieldSkip::CountOnJsonBridgedLeafInSwift.message("metadata.headings.length")
);
assert_eq!(verdicts_for(&body, "swift", &[]), vec![SkipVerdict::Limitation]);
assert!(
strict_error_for(&body, "swift", "metadata_headings", &[]).is_none(),
"a resolvable field refused for an ABI reason must not fail a consumer's build"
);
}
#[test]
fn ruby_serialized_enum_accessor_wording_is_counted_not_fatal() {
let body = " # skipped: enum variant accessor 'metadata.format.excel' not available on Ruby \
(serialized to Hash)\n";
assert_eq!(verdicts_for(body, "ruby", &[]), vec![SkipVerdict::Limitation]);
}
#[test]
fn result_is_simple_template_wording_is_counted_not_fatal() {
let body = " // skipped: result_is_simple, field 'metadata.title' not on simple result type\n";
assert_eq!(verdicts_for(body, "php", &[]), vec![SkipVerdict::Limitation]);
}
#[test]
fn not_applicable_for_simple_result_wording_is_counted_not_fatal() {
let body = " # skipped: field 'structure.headings' not applicable for simple result type\n";
assert_eq!(verdicts_for(body, "python", &[]), vec![SkipVerdict::Limitation]);
}
#[test]
fn swift_binding_exclusion_wording_is_counted_not_fatal() {
let body = " // skipped: field 'usage.tokens' references a field or type excluded from \
the Swift binding\n";
assert_eq!(verdicts_for(body, "swift", &[]), vec![SkipVerdict::Limitation]);
}
#[test]
fn the_result_is_simple_resolver_wording_stays_a_gap() {
let body = " # skipped: result_is_simple for field 'metadata' not available on result type\n";
assert_eq!(verdicts_for(body, "ruby", &[]), vec![SkipVerdict::UnacknowledgedGap]);
}
#[test]
fn coarse_oracle_backends_downgrade_gaps_to_limitations() {
let body = " // skipped: field 'chunks' not available on result type\n";
assert_eq!(verdicts_for(body, "gleam", &[]), vec![SkipVerdict::Limitation]);
assert_eq!(verdicts_for(body, "brew", &[]), vec![SkipVerdict::Limitation]);
assert_eq!(
verdicts_for(body, "go", &[]),
vec![SkipVerdict::UnacknowledgedGap],
"the same wording must stay fatal on an IR-wired backend"
);
}
#[test]
fn summary_is_none_when_nothing_was_skipped() {
assert_eq!(skip_summary(&[]), None);
}
#[test]
fn summary_counts_distinct_fixtures_not_markers() {
let _ = take_skip_records();
let body = " // skipped: field 'usage.tokens' references a field or type excluded from \
the Swift binding\n";
fail_on_unavailable_field_markers(body, "swift", "alpha", &[]);
fail_on_unavailable_field_markers(body, "swift", "alpha", &[]);
fail_on_unavailable_field_markers(body, "swift", "beta", &[]);
let summary = skip_summary(&take_skip_records()).expect("three markers must summarise");
assert!(
summary.starts_with("3 assertion(s) skipped across 2 fixture(s):"),
"got: {summary}"
);
}
#[test]
fn is_falsy_flag_accepts_zero_and_case_insensitive_false_only() {
assert!(is_falsy_flag("0"));
assert!(is_falsy_flag("false"));
assert!(is_falsy_flag("FALSE"));
assert!(!is_falsy_flag("1"));
assert!(!is_falsy_flag("true"));
assert!(!is_falsy_flag(""));
assert!(!is_falsy_flag("no"));
}
#[test]
fn diagnostic_names_language_fixture_field_and_the_opt_in() {
let message = strict_error_for(
" # skipped: field 'usage' not available on result type\n",
"ruby",
"batch_smoke",
&[],
)
.expect("an unresolved field must fail under strict");
assert!(message.contains("[ruby]"), "got: {message}");
assert!(message.contains("`batch_smoke`"), "got: {message}");
assert!(message.contains("`usage`"), "got: {message}");
assert!(message.contains("\"skip\""), "must name the opt-in: {message}");
assert!(
message.contains(super::STRICT_ASSERTIONS_ENV),
"must name the escape hatch: {message}"
);
}