Skip to content

test(scenarios): S2-S6, S8 and S17 as expected failures naming their issues - #371

Merged
jsam merged 3 commits into
mainfrom
fm/test-t03
Oct 5, 2026
Merged

jsam merged 3 commits into
mainfrom
fm/test-t03

Conversation

@jsam

@jsam jsam commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Intent

please leave this query batching functionliaty just refactor things so its clear and optimized for this ... auto materialize needs to be default mode of operation where rules get deployed as views and everything else is a query .. make the docs true with the correct systems design ... this is not accceptable state for production readiness (Context: implement #337 exactly as written.)

Issue #337 "Testing: Scenarios as expected failures (T-03)", as written: Part of the test strategy (captain, 2026-10-05: scenarios that test the changes together; cleaner, faster suites; TESTING.md). Epic #305.
Scope. S2 (counter part), S3 (counter part), S4, S5 ("one pass" part), S6, S8 (drop refusal part), S17 (views_at part) written against the target contract and registered as KnownDefect { plan_item: "#315" ... } etc. with Reproduction::Deterministic; the parts that hold today (rows, key isolation, diff on replacement) are required passes in the same scenario.
Acceptance. Each XFAIL names its issue (V1 #308, V9 #315, V13 #316, V11 #318, V7 #314, V14 #320, V10 #317); the suite prints the XFAIL list at the end; an XPASS fails the job (the mechanism exists in testkit/src/known_defect.rs); the issue bodies of V9, V11, V13, V14 gain a line "flips scenario Sn to required".

The scenarios it names, from the test strategy's catalogue (shop pack: orders, order_item, stock, blocked, link, claim; deployed rules eligible, related (recursive), offer (negation over recursion), n_eligible):

  • S2 one-row view read is a lookup: ?eligible("o-42", I, W) 50 times and ?related("i1", X); rule_evaluations delta = 0 and view_reads = reads (V1 counters, V9); rows part required.
  • S3 ad-hoc query joins facts with views: ?stock(I, Q), eligible("o-42", I, _), Q > 5 and a session rule joined with offer; rows equal the recompute answer at the same revision (required); rule_evaluations for eligible = 0, only the query's own operators run (V9).
  • S4 subscription and query consistent at a stated revision: subscribe at s; writer commits n changes; after each delta the agent queries with at: delta.revision; at the end a read at: s; query reply revision = at; rows at r_n = snapshot + deltas 1..n; read at s equals the snapshot; a read at a compacted revision fails revision_compacted and never returns rows (V9, V13); the delta half runs today.
  • S5 many agents, one view, each gets its key: 200 keyed agents on eligible plus 10 unkeyed; one write touches 3 keys, one touches none; exactly those keyed agents and the unkeyed ones receive a delta, the others are quiet (required); one maintenance pass per commit (V1 counter, V10).
  • S6 arbitrary-query subscription refused: .subscribe of a join and of a view with a comparison refused with invalid_request and deploy a rule first; the same bodies as ? queries work; a valid subscribe afterwards works (V11).
  • S8 rule replaced while subscribed: replacing offer with a stricter body in one program with facts gives one atomic old-vs-new delta at its revision, no mixed generations in a concurrent reader (required); dropping link while related depends on it is refused with conflict naming the dependents (V7).
  • S17 write burst with read-your-writes: writes from 4 writers, each read back on the same and another connection, a rule replacement during the burst, no missed or stray deltas (required); during the rebuild the ack carries views_at (V14).

What Changed

Risk Assessment

✅ Low: The change only touches tests, the testkit and the Makefile/docs. Both fixes from round 1 are correct. record() skips the file append only when the testkit itself is built under cfg(test), so the scenario binary still logs its XFAILs. S4 now combines its four reads into one result in read order and judges it once, so after V9 alone the read at s still gives an AT_IGNORED XFAIL. Removing the unit-stage log export from ci-test-all leaves e2e-reactive as the only writer, and the final summary prints that list.

Testing

I ran the seven new catalogue scenarios in debug against real engine processes, pointing the XFAIL log at the evidence directory. All seven passed their required parts and recorded XFAILs naming #308, #314, #315, #316, #318 and #320. #317 (V10) and #308 are both on S5's counter check, which reports only the first open defect in line, #308; #317 will show once #308 lands. make xfail-list printed the list at the end. A temporary edit that made S17's views_at contract hold failed the run with XPASS [#320], and I reverted the edit. The testkit self-tests left the XFAIL log empty, which confirms the review fix. The worktree is clean.

  • Live validation: ✅ go - 10 of 10 scenarios driven live against the product
Scenario Result Live Evidence
S2: one-row view reads return the right rows (required); the counter part is an XFAIL naming #308 ✅ pass live scenarios-new.log: reads::s2_one_row_view_read_is_a_lookup ok, XFAIL [#308]
S3: an ad-hoc join of facts and views matches the recompute answer (required); the counter part is an XFAIL ✅ pass live scenarios-new.log: reads::s3_ad_hoc_query_joins_facts_and_views ok, XFAIL [#308]
S4: the subscription's deltas run today; the query revision gap is XFAIL #315 and the compacted read is XFAIL #316 ✅ pass live scenarios-new.log: consistency::s4 ok, XFAIL [#315] and XFAIL [#316]
S5: of 200 keyed and 10 unkeyed agents, exactly the touched keys and the unkeyed agents get deltas (required); the one-pass counter is an XFAIL ✅ pass live scenarios-new.log: fanout::s5_many_agents_each_hear_only_their_key ok, XFAIL [#308]
S6: subscribing to a join or to a view with a comparison is accepted today, recorded as XFAIL #318; the same bodies work as queries ✅ pass live scenarios-new.log: subscribe_rules::s6 ok, two XFAIL [#318] lines
S8: replacing a rule gives one atomic delta (required); dropping link while related depends on it is accepted, recorded as XFAIL #314 ✅ pass live scenarios-new.log: generations::s8_rule_replaced_while_subscribed ok, XFAIL [#314]
S17: a 4-writer burst with read-your-writes and a mid-burst rule replacement (required); missing views_at is XFAIL #320 ✅ pass live scenarios-new.log: burst::s17_write_burst_reads_its_writes ok, XFAIL [#320]
The suite prints the XFAIL list at the end of the run ✅ pass live xfail-list.txt: 'Expected failures still open (7):' followed by the issue-named lines
Adversarial: an XPASS fails the run once a defect's contract holds ✅ pass live xpass-simulated.log: XPASS [#320] panic, test FAILED, exit 101
The testkit's self-tests no longer append fake X00/X01 entries to the XFAIL log ✅ pass live testkit-selftest.txt; selftest-xfail.log is 0 bytes
Evidence: Scenario run transcript (S2-S6, S8, S17)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.77s
     Running tests/scenarios/main.rs (target/debug/deps/scenarios-e36d7e30c71358d5)

running 7 tests
XFAIL [#318] a .subscribe whose body is not one deployed-rule atom is accepted: transport: expected a invalid_request refusal naming "deploy a rule first", the request succeeded: [Array [String("i1"), Number(7)], Array [String("i5"), Number(9)]]
XFAIL [#318] a .subscribe whose body is not one deployed-rule atom is accepted: transport: expected a invalid_request refusal naming "deploy a rule first", the request succeeded: [Array [String("o-42"), String("i5"), String("in_stock")]]
test subscribe_rules::s6_subscribe_to_a_query_is_refused ... ok
XFAIL [#308] rule_evaluations / view_reads / view_maintenance_us are not exported: counter rule_evaluations is not exported
test reads::s3_ad_hoc_query_joins_facts_and_views ... ok
XFAIL [#315] query replies carry no revision: transport: query reply names no revision (read at 7)
XFAIL [#316] a read at a compacted revision is answered instead of refused revision_compacted: transport: expected a revision_compacted refusal naming "compacted", the request succeeded: [Array [String("i1"), Number(7), String("in_stock")], Array [String("i13"), Number(0), String("in_stock")], Array [String("i13"), Number(4), String("in_stock")], Array [String("i5"), Number(9), String("in_stock")]]
test consistency::s4_subscription_and_query_agree_at_a_revision ... ok
S8: 12 concurrent reads saw one generation each
XFAIL [#314] dropping a relation a deployed view depends on is accepted and empties the view: transport: expected a conflict refusal naming "related", the request succeeded: [Array [String("Relation 'link' dropped.")]]
test generations::s8_rule_replaced_while_subscribed ... ok
XFAIL [#308] rule_evaluations / view_reads / view_maintenance_us are not exported: counter rule_evaluations is not exported
test reads::s2_one_row_view_read_is_a_lookup ... ok
XFAIL [#320] a write acknowledged during a view rebuild does not carry views_at: transport: the rebuild's acknowledgement names no views_at (revision 214)
test burst::s17_write_burst_reads_its_writes ... ok
XFAIL [#308] rule_evaluations / view_reads / view_maintenance_us are not exported: counter rule_evaluations is not exported
test fanout::s5_many_agents_each_hear_only_their_key ... ok

test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 27 filtered out; finished in 4.61s
Evidence: End-of-run XFAIL list printed by make xfail-list
Expected failures still open (7):
XFAIL [#308] rule_evaluations / view_reads / view_maintenance_us are not exported: counter rule_evaluations is not exported
XFAIL [#314] dropping a relation a deployed view depends on is accepted and empties the view: transport: expected a conflict refusal naming "related", the request succeeded: [Array [String("Relation 'link' dropped.")]]
XFAIL [#315] query replies carry no revision: transport: query reply names no revision (read at 7)
XFAIL [#316] a read at a compacted revision is answered instead of refused revision_compacted: transport: expected a revision_compacted refusal naming "compacted", the request succeeded: [Array [String("i1"), Number(7), String("in_stock")], Array [String("i13"), Number(0), String("in_stock")], Array [String("i13"), Number(4), String("in_stock")], Array [String("i5"), Number(9), String("in_stock")]]
XFAIL [#318] a .subscribe whose body is not one deployed-rule atom is accepted: transport: expected a invalid_request refusal naming "deploy a rule first", the request succeeded: [Array [String("i1"), Number(7)], Array [String("i5"), Number(9)]]
XFAIL [#318] a .subscribe whose body is not one deployed-rule atom is accepted: transport: expected a invalid_request refusal naming "deploy a rule first", the request succeeded: [Array [String("o-42"), String("i5"), String("in_stock")]]
XFAIL [#320] a write acknowledged during a view rebuild does not carry views_at: transport: the rebuild's acknowledgement names no views_at (revision 214)
Evidence: Simulated XPASS fails the run

panicked at testkit/src/known_defect.rs:64:23: XPASS [#320] a write acknowledged during a view rebuild does not carry views_at: the contract now holds. Remove this known-defect marker so the scenario becomes a required pass. test burst::s17_write_burst_reads_its_writes ... FAILED

   Compiling inputlayer v0.1.0 (~/.no-mistakes/worktrees/9eea230c3aae/01M46YDZPAPSYK35NQXT4ECJ7D)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 3.31s
     Running tests/scenarios/main.rs (target/debug/deps/scenarios-e36d7e30c71358d5)

running 1 test

thread 'burst::s17_write_burst_reads_its_writes' (2353630) panicked at testkit/src/known_defect.rs:64:23:
XPASS [#320] a write acknowledged during a view rebuild does not carry views_at: the contract now holds. Remove this known-defect marker so the scenario becomes a required pass.
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
test burst::s17_write_burst_reads_its_writes ... FAILED

failures:

failures:
    burst::s17_write_burst_reads_its_writes

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 33 filtered out; finished in 5.21s

error: test failed, to rerun pass `--test scenarios`
Evidence: Testkit self-tests do not write to the XFAIL log
XFAIL [X00] test defect: timed out waiting for delta
XFAIL [X01] the defect behind the first one: unexpected work: x
XPASS [X01] the defect behind the first one: the contract now holds. Remove this known-defect marker so the scenario becomes a required pass.
XFAIL [X00] test defect: timed out waiting for delta
XPASS [X00] test defect: the contract now holds. Remove this known-defect marker so the scenario becomes a required pass.
test known_defect::tests::test_first_defect_in_front_is_expected_failure ... ok
test known_defect::tests::test_defect_behind_shows_once_the_first_is_fixed ... ok
test known_defect::tests::test_matching_violation_is_expected_failure ... ok
test known_defect::tests::test_holding_contract_is_unexpected_pass_of_the_last_defect - should panic ... ok
test known_defect::tests::test_other_violation_is_real_failure - should panic ... ok
test known_defect::tests::test_holding_contract_is_unexpected_pass - should panic ... ok
test known_defect::tests::test_racy_defect_not_reproduced_passes ... ok
test known_defect::tests::test_violation_of_no_defect_is_real_failure - should panic ... ok
test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 12 filtered out; finished in 0.00s

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

🔧 **Rebase** - 7 issues found → auto-fixed ✅
  • ⚠️ Makefile - merge conflict rebasing onto origin/main
  • ⚠️ TESTING.md - merge conflict rebasing onto origin/main
  • ⚠️ testkit/src/client.rs - merge conflict rebasing onto origin/main
  • ⚠️ testkit/src/counters.rs - merge conflict rebasing onto origin/main
  • ⚠️ testkit/src/fixture.rs - merge conflict rebasing onto origin/main
  • ⚠️ tests/scenarios/harness.rs - merge conflict rebasing onto origin/main
  • ⚠️ tests/scenarios/main.rs - merge conflict rebasing onto origin/main

🔧 Fix applied.
✅ Re-checked - no issues remain.

🔧 **Review** - 2 issues found → auto-fixed ✅
  • ⚠️ testkit/src/known_defect.rs:96 - The XFAIL list includes fake entries from the testkit's own unit tests. record() appends to the INPUTLAYER_XFAIL_LOG file whenever that variable is set. make unit-test sets it and then runs cargo test --workspace, which includes the testkit self-tests (test_matching_violation_is_expected_failure, test_first_defect_in_front_is_expected_failure, test_defect_behind_shows_once_the_first_is_fixed, test_racy_defect_not_reproduced_passes). So the PR gate (ci.yml:249 runs make unit-test) prints entries like XFAIL [X00] test defect and XFAIL [X01] ... / NOT REPRODUCED [X00] in 'Expected failures still open'. That breaks the acceptance item 'the suite prints the XFAIL list at the end', because the list is meant to show only real open issues. Fix: skip the file append under cfg!(test) in record() (keep the println), or have the self-tests clear the env var. Related site: Makefile:215-217, where ci-test-all's unit stage empties the log and exports the variable but excludes the scenarios binary. The only lines it can collect are this self-test noise, and make e2e-reactive empties the log again before the scenarios run. That truncate/export in the unit stage can be dropped. The list is also printed twice in ci-test-all: once by e2e-reactive and again at Makefile:300.
  • ⚠️ tests/scenarios/consistency.rs:124 - S4 judges each revision_aligned outcome on its own with judge_first(&amp;[NO_REVISION, AT_IGNORED]). Once V9 Queries read deployed views from arrangements; revision on query replies (V9) #315 lands but V13 at: <revision> reads with a retention window (V13) #316 has not, this fails the job with an XPASS naming at: <revision> reads with a retention window (V13) #316, which is still open. Here is why. Each of the three in-loop reads at: delta.revision runs right after that delta, with no other writer, so the latest revision is delta.revision. An engine that ignores at but now returns revision answers at exactly that revision with the right rows, so the outcome is Ok. judge_first sends Ok to the last defect (AT_IGNORED), which panics XPASS [#316] on the first write, before the read at: s (the one that would really show at: <revision> reads with a retention window (V13) #316) is judged. This contradicts TESTING.md's stated design that 'each stage is an XFAIL of its own issue', and Queries read deployed views from arrangements; revision on query replies (V9) #315's body, which says it flips only S4's revision part. Fix: fold the four outcomes into one result, keeping the first Err (for example aligned.into_iter().collect::&lt;Checked&lt;Vec&lt;()&gt;&gt;&gt;().map(drop)), and call judge_first once.

🔧 Fix applied.
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 10 of 10 scenarios driven live against the product
Scenario Result Live Evidence
S2: one-row view reads return the right rows (required); the counter part is an XFAIL naming #308 ✅ pass live scenarios-new.log: reads::s2_one_row_view_read_is_a_lookup ok, XFAIL [#308]
S3: an ad-hoc join of facts and views matches the recompute answer (required); the counter part is an XFAIL ✅ pass live scenarios-new.log: reads::s3_ad_hoc_query_joins_facts_and_views ok, XFAIL [#308]
S4: the subscription's deltas run today; the query revision gap is XFAIL #315 and the compacted read is XFAIL #316 ✅ pass live scenarios-new.log: consistency::s4 ok, XFAIL [#315] and XFAIL [#316]
S5: of 200 keyed and 10 unkeyed agents, exactly the touched keys and the unkeyed agents get deltas (required); the one-pass counter is an XFAIL ✅ pass live scenarios-new.log: fanout::s5_many_agents_each_hear_only_their_key ok, XFAIL [#308]
S6: subscribing to a join or to a view with a comparison is accepted today, recorded as XFAIL #318; the same bodies work as queries ✅ pass live scenarios-new.log: subscribe_rules::s6 ok, two XFAIL [#318] lines
S8: replacing a rule gives one atomic delta (required); dropping link while related depends on it is accepted, recorded as XFAIL #314 ✅ pass live scenarios-new.log: generations::s8_rule_replaced_while_subscribed ok, XFAIL [#314]
S17: a 4-writer burst with read-your-writes and a mid-burst rule replacement (required); missing views_at is XFAIL #320 ✅ pass live scenarios-new.log: burst::s17_write_burst_reads_its_writes ok, XFAIL [#320]
The suite prints the XFAIL list at the end of the run ✅ pass live xfail-list.txt: 'Expected failures still open (7):' followed by the issue-named lines
Adversarial: an XPASS fails the run once a defect's contract holds ✅ pass live xpass-simulated.log: XPASS [#320] panic, test FAILED, exit 101
The testkit's self-tests no longer append fake X00/X01 entries to the XFAIL log ✅ pass live testkit-selftest.txt; selftest-xfail.log is 0 bytes
  • cargo build --tests --test scenarios -p inputlayer
  • INPUTLAYER_XFAIL_LOG=$E/xfail.log cargo test --test scenarios -- --nocapture reads:: consistency:: fanout:: subscribe_rules:: generations:: burst:: (7 passed, each with XFAILs naming their issues)
  • make xfail-list XFAIL_LOG=$E/xfail.log (prints the end-of-run XFAIL list)
  • Adversarial: temporarily replaced NO_VIEWS_AT.judge(views_at) with judge(Ok(())) in tests/scenarios/burst.rs and ran cargo test --test scenarios burst::. The run exited 101 with XPASS [#320]; the edit was reverted with git checkout
  • INPUTLAYER_XFAIL_LOG=$E/selftest-xfail.log cargo test -p inputlayer-testkit known_defect (self-tests print XFAIL/XPASS but the log file stays 0 bytes)
  • Read-only gh issue view for #315, #316, #318, #320 to confirm the 'flips scenario Sn to required' lines
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

jsam added 3 commits October 5, 2026 21:13
…issues (#337)

The milestone 9 scenarios on the shop pack, each running the part that
holds today as a required pass and asserting the rest of the target
contract as a deterministic expected failure that names the issue making
it hold: S2 and S3 (reads evaluate no rule: V1 #308 counters, then V9
V13 #316), S5 (key isolation for 200 keyed and 10 unkeyed agents; one
maintenance pass V1 #308, then V10 #317), S6 (`.subscribe` of a query
refused, V11 #318), S8 (exact old-vs-new delta on a rule replacement;
drop refusal V7 #314) and S17 (read-your-writes through a rebuild;
`views_at` V14 #320).

The testkit gains `Violation::UnexpectedWork`, `KnownDefect::judge_first`
for checks that run into one issue after another, `try_execute_at`,
`QueryResult::views_at`, and an XFAIL log (`INPUTLAYER_XFAIL_LOG`) that
`make unit-test`, `make ci-test-all` and `make e2e-reactive` print as the
open expected-failure list when the run ends.
@jsam jsam changed the title test(scenarios): S2-S6, S8 and S17 as expected failures naming their issues (#337) test(scenarios): S2-S6, S8 and S17 as expected failures naming their issues Oct 5, 2026
@jsam
jsam marked this pull request as ready for review October 5, 2026 21:40
@jsam
jsam merged commit ea0438d into main Oct 5, 2026
22 checks passed
@jsam
jsam deleted the fm/test-t03 branch October 5, 2026 21:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant