Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
181 commits
Select commit Hold shift + click to select a range
0881339
Weaken the restriction in concretely about not testing reactor/proact…
iancooper Jul 18, 2026
e9ab3a4
docs: add ADRs 0066/0067 for conformance-test provider interface, gat…
iancooper Jul 18, 2026
f91656c
docs: address design-review findings on ADRs 0066/0067
iancooper Jul 18, 2026
b1d24e6
docs: withdraw FR-3 mechanism assertion; fold into a mechanism-agnost…
iancooper Jul 18, 2026
2745b20
docs: correct native-delay claim and complete the FR-3 withdrawal sweep
iancooper Jul 18, 2026
6be86e9
docs: rewrite spec 0036 requirements; all twelve gateway transports i…
iancooper Jul 19, 2026
3d14ef3
docs: reverse the gating lifecycle; remediate requirements r7 and des…
iancooper Jul 19, 2026
8b507ed
docs: requirements round 8 and design round 6, both remediated
iancooper Jul 19, 2026
fcb5ad1
docs: requirements rounds 9-10; approve requirements; FR-2 lower-boun…
iancooper Jul 20, 2026
76b2e8f
docs: design rounds 7-8; correct RocketMQ FR-2 attribution; approve d…
iancooper Jul 20, 2026
3b2070b
docs: generate, review, and approve ralph-tasks for spec 0036
iancooper Jul 21, 2026
61ff79d
feat: seed the conformance ledger (23×11 matrix, five known FR-2 gaps)
iancooper Jul 21, 2026
2136578
feat: narrow SkipTest to a closed legacy-template list (ADR 0066 step A)
iancooper Jul 21, 2026
79bf720
feat: extend FR-1 provider interface templates and drop positional DL…
iancooper Jul 21, 2026
c0ec205
feat: emit Shared/RejectionMetadataKeys once per gateway configuration
iancooper Jul 21, 2026
6384065
feat: migrate Kafka providers to FR-1 surface and regenerate Kafka
iancooper Jul 21, 2026
8832ac3
feat: migrate AWS (V3) providers to FR-1 surface and regenerate AWS
iancooper Jul 21, 2026
0fc413d
feat: migrate AWS.V4 providers to FR-1 surface and regenerate AWS.V4
iancooper Jul 21, 2026
3be27c9
feat: migrate GCP providers to FR-1 surface and regenerate GCP
iancooper Jul 21, 2026
f5b8a3d
feat: migrate MSSQL provider to FR-1 surface and regenerate MSSQL
iancooper Jul 21, 2026
98db1e6
feat: migrate PostgresSQL provider to FR-1 surface and regenerate Pos…
iancooper Jul 21, 2026
3a43b14
feat: migrate Redis provider to FR-1 surface and regenerate Redis
iancooper Jul 21, 2026
333f5f1
feat: migrate RMQ.Async providers to FR-1 surface and regenerate RMQ.…
iancooper Jul 21, 2026
f6f2e08
feat: migrate RocketMQ provider to FR-1 surface and regenerate RocketMQ
iancooper Jul 21, 2026
824dde5
docs: capture Phase 0 rollout learnings; fix regen framework flag and…
iancooper Jul 22, 2026
ef208fc
feat: wire generator to emit ledger-driven Deferred Skip for canonica…
iancooper Jul 22, 2026
1f1d912
feat: add canonical plain-requeue templates (FR-22) with bounded rede…
iancooper Jul 22, 2026
dc06594
feat: add canonical requeue-with-delay templates (FR-2, before-D/afte…
iancooper Jul 22, 2026
f572ebe
feat: add canonical zero-delay requeue templates (FR-15)
iancooper Jul 22, 2026
ec7adfe
feat: add canonical delivery-error reject-to-DLQ templates (FR-4)
iancooper Jul 22, 2026
cdcfc4e
feat: add canonical unacceptable-reject invalid-channel templates (FR-5)
iancooper Jul 22, 2026
c9af3f8
feat: add canonical unacceptable DLQ-only fallback templates (FR-6)
iancooper Jul 22, 2026
b373fa7
feat: add canonical no-channels acknowledge-and-continue templates (F…
iancooper Jul 22, 2026
473b547
feat: add canonical None-reason reject DLQ-default templates (FR-17)
iancooper Jul 22, 2026
14339f5
feat: add canonical rejection-metadata stamping templates (FR-8)
iancooper Jul 22, 2026
d38c0c7
feat: add canonical delayed-send templates (FR-9)
iancooper Jul 22, 2026
5546a82
feat: add canonical Nack-redelivery templates (FR-16)
iancooper Jul 22, 2026
6177b54
feat: add Kafka reference-surface reconciliation checkpoint
iancooper Jul 22, 2026
dd948ba
feat: generate the canonical suite into every wired project (generate…
iancooper Jul 22, 2026
747db6a
docs: correct Skip-attribute convention in ralph-tasks and record Pha…
iancooper Jul 22, 2026
97c9be7
feat: prove Kafka reference suite; defer both rows to #4240 (infra bl…
iancooper Jul 22, 2026
66d152e
docs: strengthen deferral governance and split broker-heavy conforman…
iancooper Jul 22, 2026
0ac311e
feat: prove Kafka requeue/redeliver class (FR-22, FR-15, FR-16) — Pas…
iancooper Jul 22, 2026
7ac2796
feat: prove Kafka no-channel acknowledge-and-log (FR-7) — Pass, both …
iancooper Jul 22, 2026
37f0930
feat: prove Kafka reject→DLQ/invalid + metadata (FR-4/5/6/8/17) — Pas…
iancooper Jul 22, 2026
cb3ddd2
test: make the canonical-Skip generator gates ledger-aware (green as …
iancooper Jul 23, 2026
06f65fd
feat: prove Kafka delay class (FR-2, FR-9) — Pass, both configs
iancooper Jul 23, 2026
936d7ae
feat: prove AWS (V3) / SqsStandard conformance — Pass, all 11 columns
iancooper Jul 23, 2026
04ed383
feat: prove AWS (V3) / SqsFifo conformance — 10 Pass, FR-9 Deferred
iancooper Jul 23, 2026
45841cf
feat: prove AWS (V3) / SnsStandard conformance — 10 Pass + FR-9 Fixed
iancooper Jul 23, 2026
b58abee
feat: prove AWS (V3) / SnsFifo conformance — 10 Pass + FR-9 Fixed
iancooper Jul 23, 2026
5978bce
feat: prove AWS.V4 / SqsStandard conformance — Pass, all 11 columns
iancooper Jul 23, 2026
b2b821e
feat: prove AWS.V4 / SqsFifo conformance — 10 Pass, FR-9 Deferred
iancooper Jul 27, 2026
5bb5660
feat: prove AWS.V4 / SnsStandard conformance — 10 Pass + FR-9 Fixed (…
iancooper Jul 27, 2026
ce005b7
feat: prove AWS.V4 / SnsFifo conformance — 10 Pass + FR-9 Fixed (#4240)
iancooper Jul 27, 2026
bb45949
feat: prove Redis conformance — 10 Pass + FR-16 Deferred (#4240)
iancooper Jul 28, 2026
62aebe1
feat: prove MSSQL conformance — 10 Pass + FR-16 Deferred (#4240)
iancooper Jul 28, 2026
252b264
feat: prove PostgresSQL conformance — 11 Pass (FR-16 Pass, native vis…
iancooper Jul 29, 2026
868f37e
feat: prove RMQ.Async / Classic conformance — 6 Pass + FR-4/5/6/8/17 …
iancooper Jul 29, 2026
0e46e85
feat: relax FR-8 for native-dead-letter transports — RMQ.Async / Clas…
iancooper Jul 29, 2026
ea2a230
feat: prove RMQ.Async / Quorum conformance — 10 Pass + FR-5 Deferred …
iancooper Jul 29, 2026
edf2b4f
wip: RocketMQ conformance groundwork — producer + harness fixes (row …
iancooper Jul 30, 2026
4458a84
feat: prove RocketMQ conformance — 9 Fixed + FR-2/FR-15 Deferred (#4240)
iancooper Jul 30, 2026
d94e9b8
feat: prove GCP / Pull conformance — 4 Pass + FR-9 Fixed + FR-2/4/5/6…
iancooper Jul 30, 2026
67fc5bb
feat: prove GCP / PullOrdering conformance — 4 Pass + FR-9 Fixed + FR…
iancooper Jul 30, 2026
7ec65b4
feat: defer GCP / Stream + StreamOrdering conformance — all cells Def…
iancooper Jul 30, 2026
5682db8
feat: onboard MQTT for conformance — config + both gateway providers …
iancooper Sep 1, 2026
b1a5027
feat: prove MQTT conformance — 10 Fixed + FR-16 Deferred (#4240)
iancooper Sep 1, 2026
3e930ff
feat: onboard RMQ.Sync for conformance — config + gateway provider (#…
iancooper Sep 1, 2026
32d1a6f
feat: prove RMQ.Sync conformance — 10 Fixed + FR-5 Deferred (#4240)
iancooper Sep 1, 2026
b70db98
feat: onboard AzureServiceBus for conformance — config + gateway prov…
iancooper Sep 2, 2026
5291906
feat: defer AzureServiceBus conformance on infra grounds — ledger now…
iancooper Sep 2, 2026
10d6df1
docs: record maintainer ruling — umbrella #4240 covers every Deferred…
iancooper Sep 2, 2026
09af991
Merge origin/master into feature/4240-universal-transport-conformance…
iancooper Sep 2, 2026
47d2e8a
docs: remove ADR 0070 and its spec — merged by accident (#4240)
iancooper Sep 2, 2026
49f78c9
feat: delete the four legacy gated templates and sweep their generate…
iancooper Sep 2, 2026
6a0ad7d
feat: remove the retired gate branches and LegacyGatedTemplates from …
iancooper Sep 2, 2026
28c8536
feat: remove the three retired gate properties from MessagingGatewayC…
iancooper Sep 2, 2026
84f9973
feat: remove the three retired gate keys from every test-configuratio…
iancooper Sep 2, 2026
c9f782e
docs: mark ralph task 60 complete — #NNNN reconciliation already in p…
iancooper Sep 2, 2026
56bd570
feat: enforce the greppable linked-issue Skip convention as an in-tre…
iancooper Sep 2, 2026
f07a47c
feat: cross-check Skip markers against the conformance ledger (#4240)
iancooper Sep 2, 2026
08d6b4f
feat: check every generated Skip against its own ledger cell (#4240)
iancooper Sep 2, 2026
956461c
refactor: retire When_gate_flags_are_false_should_skip_only_legacy_te…
iancooper Sep 2, 2026
f7fa9de
feat: split the infrastructure gate so Kafka/Consumer stops skipping …
iancooper Sep 2, 2026
f80127f
docs: link the assume-detection gate to its tracking issue #4299 (#4240)
iancooper Sep 3, 2026
e0a95c0
ci: raise the AWS job timeouts to 20 minutes (#4240)
iancooper Sep 7, 2026
6c1fd91
fix: shorten the GCP Pull test ack deadline so nacked messages can re…
iancooper Sep 7, 2026
1aec682
docs: correct the ASB deferral note — the suite HAS been observed, in…
iancooper Sep 7, 2026
0e337bf
feat: bring Azure Service Bus to conformance — 9 of 11 cells now Pass…
iancooper Sep 7, 2026
1b0b5b5
Merge master into the conformance branch, keeping the AWS reaper honest
iancooper Sep 7, 2026
f4e202a
Merge remote-tracking branch 'origin/master' into feature/4240-univer…
iancooper Sep 8, 2026
5ec0016
Merge master (#4300), and generate the Sync DataSchema test it unblocks
iancooper Sep 8, 2026
98b72e6
fix(mqtt): await message arrival instead of polling, and honour the t…
iancooper Sep 8, 2026
1cb4b14
fix(mqtt): let the caller configure producer instrumentation
iancooper Sep 8, 2026
cd7b8e2
fix(gcp): keep the client's default Pull expiration when no timeout i…
iancooper Sep 8, 2026
3dfa32e
test: pace the three reject templates that polled without a delay
iancooper Sep 8, 2026
748ee92
test: fail the audit when a ledger lookup would fail open
iancooper Sep 8, 2026
d6027e8
ci: raise timeouts on the jobs that gained the canonical suite
iancooper Sep 8, 2026
20ae6f0
ci: run the test generator's own tests
iancooper Sep 8, 2026
125fdb6
fix(generator): fail loudly when the conformance ledger cannot be loc…
iancooper Sep 9, 2026
8eff835
fix(mqtt): keep the arrival signal in step with the buffer, and bound…
iancooper Sep 9, 2026
e9cbbb3
docs: correct comments the recent fixes falsified, and tighten two sm…
iancooper Sep 9, 2026
f4b9a92
fix(rocketmq): stop adding the Type property twice, and note two comp…
iancooper Sep 9, 2026
b7b007f
revert(rocketmq): move the duplicate Type property fix to its own PR
iancooper Sep 9, 2026
5acfba5
Merge branch 'master' into feature/4240-universal-transport-conforman…
iancooper Sep 10, 2026
2bc00ae
Merge branch 'master' into feature/4240-universal-transport-conforman…
iancooper Sep 10, 2026
11b8835
Merge branch 'master' into feature/4240-universal-transport-conforman…
iancooper Sep 10, 2026
1ae8e6b
fix(gcp): only read DeadlineExceeded as an empty receive when we set …
iancooper Sep 10, 2026
f5cc31e
fix(mqtt,sns): release MQTT rejection producers, and guard the SNS sc…
iancooper Sep 10, 2026
cf07583
fix(ci): drop the duplicated generator-test step my fold left behind
iancooper Sep 10, 2026
92b1bd9
fix: close the ledger parser's fail-open, log harness republish failu…
iancooper Sep 10, 2026
af1480f
feat(conformance): restore requeue-budget exhaustion to DLQ as canoni…
iancooper Sep 10, 2026
a617f48
feat(conformance): Redis FR-23 moves from Deferred to Pass, on broker…
iancooper Sep 10, 2026
cf72943
docs(conformance): record what counts the requeue budget, per configu…
iancooper Sep 10, 2026
85a6f79
feat(conformance): FR-23 drives the production pump instead of a harn…
iancooper Sep 11, 2026
bfd6b86
Merge remote-tracking branch 'origin/master' into feature/4240-univer…
iancooper Sep 11, 2026
aeb0e67
feat(conformance): FR-23 passes on MSSQL, Postgres and RMQ.Async
iancooper Sep 11, 2026
539ae68
docs(conformance): point the AWS FR-23 cells at #4341, framed against…
iancooper Sep 11, 2026
1448683
docs(conformance): sign the deferred cells, and record the gateway/pu…
iancooper Sep 12, 2026
66d13ac
test(conformance): fail the build when the ledger loses its pump-side…
iancooper Sep 12, 2026
c958f88
Merge remote-tracking branch 'origin/master' into feature/4240-univer…
iancooper Sep 12, 2026
2b5324c
feat(conformance): FR-23 passes on RMQ.Sync
iancooper Sep 12, 2026
3c9a51e
docs(conformance): correct the FR-23 deferred count to 15
iancooper Sep 12, 2026
4a2b406
docs(conformance): MQTT FR-23 stays deferred — the Proactor pump dead…
iancooper Sep 12, 2026
96b8908
Merge remote-tracking branch 'origin/master' into feature/4240-univer…
iancooper Sep 12, 2026
8dca2ca
docs(conformance): point the MQTT FR-23 cell at #4351
iancooper Sep 12, 2026
1a70427
docs(conformance): GCP FR-23 attempted — the emulator cannot create a…
iancooper Sep 12, 2026
3aeaf4b
docs(conformance): RocketMQ FR-23 attempted — Requeue is a no-op, so …
iancooper Sep 12, 2026
be2ebd8
fix(rocketmq): make create-topic actually work, and point FR-23 at #4353
iancooper Sep 12, 2026
fd20bc0
Merge remote-tracking branch 'origin/master' into feature/4240-univer…
iancooper Sep 12, 2026
8db5307
ci(rmq): migrate off the retiring delayed-message plugin onto stock i…
iancooper Sep 12, 2026
5599881
fix(rmq-async): default subscriptions to durable queues so RabbitMQ 4…
iancooper Sep 12, 2026
4023bc7
docs(release-notes): explain why the RMQ.Async durability default had…
iancooper Sep 12, 2026
58eb33d
test(rmq-async): declare durable queues so the hand-written suite run…
iancooper Sep 12, 2026
b498136
test(generator): reject a placeholder sign-off handle in the conforma…
iancooper Sep 13, 2026
ea89e1f
docs(generator): refresh generated_tests.md and move the manual test …
iancooper Sep 13, 2026
dd2aaa3
refactor(generator): read the conformance ledger through one parser, …
iancooper Sep 13, 2026
2d2d7a2
test(generator): audit the FR-8 rejection-metadata contract
iancooper Sep 13, 2026
80532da
test(kafka): ride out a transient channel failure in the retryable ch…
iancooper Sep 13, 2026
d8bb211
fix(kafka): only swallow a channel failure when a message actually ar…
iancooper Sep 13, 2026
93b27ae
Merge remote-tracking branch 'origin/master' into feature/4240-univer…
iancooper Sep 13, 2026
ed6ef02
fix: make rejection-destination helpers a single bounded receive (bac…
iancooper Sep 14, 2026
9e15218
feat(generator): a shared conformance harness scheduler, with a Cance…
iancooper Sep 15, 2026
9faa41e
test(generator): a republish in flight during Dispose must not leak w…
iancooper Sep 15, 2026
3996c8c
refactor(tests): move the 17 harness-scheduler sites onto the shared …
iancooper Sep 15, 2026
9aa21b0
fix(generator): close what a republish allocated when its send throws
iancooper Sep 15, 2026
6594474
docs: record that RMQ.Sync cannot run against RabbitMQ 4.3+
iancooper Sep 15, 2026
db2eca4
feat(tests): require both pump variants to cover a ledger behaviour
iancooper Sep 16, 2026
a30e563
feat(tests): fail the pump-coverage audit on a test hollowed out in p…
iancooper Sep 16, 2026
1efd77b
docs: record what the pump-coverage audit now guards, and what it doe…
iancooper Sep 16, 2026
52abdf7
docs: release notes for three undocumented gateway behaviour changes
iancooper Sep 16, 2026
715b556
fix(mqtt): drop a payload the consumer cannot read instead of writing it
iancooper Sep 16, 2026
3f12a34
fix(mqtt): catch every fault parsing a payload, and run the test in CI
iancooper Sep 16, 2026
fc6a6fb
Merge remote-tracking branch 'origin/master' into feature/4240-univer…
iancooper Sep 16, 2026
f67a62c
docs: the MQTT tracing note promised configurability the consumer can…
iancooper Sep 16, 2026
41c2ef8
Merge remote-tracking branch 'origin/master' into feature/4240-univer…
iancooper Sep 16, 2026
52334e8
refactor: replace both InternalsVisibleTo seams with public mapper types
iancooper Sep 16, 2026
d7738f0
refactor: state the rule in template comments instead of citing a spe…
iancooper Sep 17, 2026
5166e81
refactor: state the rule in audit and provider comments too
iancooper Sep 17, 2026
febd0d7
fix: make the no-channels rejection test able to see the failure it f…
iancooper Sep 17, 2026
59f8b42
refactor: say which behaviour a ledger column is, and where the ledge…
iancooper Sep 17, 2026
2e650c3
fix: make the nack-redelivery test able to see the failure it forbids
iancooper Sep 17, 2026
c49c6ab
docs: make the conformance ACs ordering-neutral
iancooper Sep 17, 2026
f7ad18d
fix: identify canonical two-message arms by id, not arrival order
iancooper Sep 17, 2026
194522a
docs: record the aws-ci verification of the ordering fix
iancooper Sep 18, 2026
6c1908e
docs: give the generated test suites a contributor-facing front door
iancooper Sep 18, 2026
95eebfa
docs: add the three transport conformance guides
iancooper Sep 18, 2026
56acf36
docs: make CONTRIBUTING the front door for the generated suites
iancooper Sep 18, 2026
3837651
docs: measure the zero-delay window from the requeue's return
iancooper Sep 18, 2026
353b6e1
fix: start the zero-delay window when the requeue returns
iancooper Sep 18, 2026
4d52ae1
Merge remote-tracking branch 'origin/master' into feature/4240-univer…
iancooper Sep 18, 2026
e721bc9
docs: state the real reason the FIFO dedup id is stamped
iancooper Sep 18, 2026
dc47376
docs: record the ordering guarantee NFR-4 owed, per configuration
iancooper Sep 18, 2026
31e69c4
fix: check every canonical behaviour in the generate-everywhere gate
iancooper Sep 18, 2026
7bf4444
docs(conformance): GCP Pull's five claimed cells came from the emulat…
iancooper Sep 19, 2026
725eed6
fix(asb-tests): create the topic once, before four threads race to cr…
iancooper Sep 19, 2026
69a05e1
ci(rocketmq): run the broker-free RocketMQ tests in the build job
iancooper Sep 19, 2026
39e02f1
fix(ci): reference GitHubActionsTestLogger in RocketMQ.Tests
iancooper Sep 19, 2026
0d12eea
docs(conformance): tie the GCP deferral to #4321 and mark the umbrell…
iancooper Sep 19, 2026
89d5740
docs(conformance): correct the GCP elapsed claim - 7.12 s exists
iancooper Sep 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
82 changes: 45 additions & 37 deletions .agent_instructions/generated_tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ tools/Paramore.Brighter.Test.Generator/
│ ├── IAmAMessageBuilder.cs.liquid ← Message builder interface
│ ├── IAmAMessageAssertion.cs.liquid ← Message assertion interface
│ ├── Outbox/
│ │ ├── Sync/ ← 13 Liquid templates for sync outbox tests (12 tests + 1 interface)
│ │ ├── Async/ ← 13 Liquid templates for async outbox tests (12 tests + 1 interface)
│ │ ├── Sync/ ← 14 Liquid templates for sync outbox tests (13 tests + 1 interface)
│ │ ├── Async/ ← 14 Liquid templates for async outbox tests (13 tests + 1 interface)
│ │ └── Causation/ ← Liquid template for causation-tracking outbox tests (subclass of CausationTrackingOutboxBaseTests)
│ └── MessagingGateway/
│ ├── Reactor/ ← 13 Liquid templates for sync messaging gateway tests (12 tests + 1 interface)
│ └── Proactor/ ← 13 Liquid templates for async messaging gateway tests (12 tests + 1 interface)
│ ├── Reactor/ ← 21 Liquid templates for sync messaging gateway tests (20 tests + 1 interface)
│ ├── Proactor/ ← 21 Liquid templates for async messaging gateway tests (20 tests + 1 interface)
│ └── Shared/ ← 2 Liquid templates shared by both variants (ConformanceDeferredPump, RejectionMetadataKeys)
├── Generators/
│ ├── BaseGenerator.cs
│ ├── OutboxGenerator.cs
Expand Down Expand Up @@ -50,20 +51,28 @@ tests/Paramore.Brighter.*.Tests/

| Project | Outbox | Messaging Gateway | Variants |
|---|---|---|---|
| `Paramore.Brighter.MySQL.Tests` | ✅ | | Text, Binary |
| `Paramore.Brighter.PostgresSQL.Tests` | ✅ | ✅ | Text, Binary (outbox); single (gateway) |
| `Paramore.Brighter.MSSQL.Tests` | ✅ | ✅ | Text, Binary (outbox); single (gateway) |
| `Paramore.Brighter.Sqlite.Tests` | ✅ | | Text, Binary |
| `Paramore.Brighter.DynamoDB.Tests` | ✅ | | single |
| `Paramore.Brighter.DynamoDB.V4.Tests` | ✅ | | single |
| `Paramore.Brighter.MongoDb.Tests` | ✅ | | single |
| `Paramore.Brighter.AWS.Tests` | | ✅ | SnsStandard, SnsFifo, SqsStandard, SqsFifo |
| `Paramore.Brighter.AWS.V4.Tests` | | ✅ | SnsStandard, SnsFifo, SqsStandard, SqsFifo |
| `Paramore.Brighter.AzureServiceBus.Tests` | | ✅ | single |
| `Paramore.Brighter.DynamoDB.Tests` | ✅ | | single |
| `Paramore.Brighter.DynamoDB.V4.Tests` | ✅ | | single |
| `Paramore.Brighter.Gcp.Tests` | ✅ | ✅ | Firestore, SpannerBinary, SpannerText (outbox); Pull, PullOrdering, Stream, StreamOrdering (gateway) |
| `Paramore.Brighter.RMQ.Async.Tests` | | ✅ | Classic, Quorum |
| `Paramore.Brighter.AWS.Tests` | | ✅ | SnsStandard, SnsFifo, SqsStandard, SqsFifo |
| `Paramore.Brighter.AWS.V4.Tests` | | ✅ | SnsStandard, SnsFifo, SqsStandard, SqsFifo |
| `Paramore.Brighter.Kafka.Tests` | | ✅ | Standard, PartitionKey |
| `Paramore.Brighter.Redis.Tests` | | ✅ | single |
| `Paramore.Brighter.RocketMQ.Tests` | | ✅ | single |
| `Paramore.Brighter.Kafka.Tests` | | ✅ | Classic, Consumer, PartitionKey |
| `Paramore.Brighter.MQTT.Tests` | | ✅ | single |
| `Paramore.Brighter.MSSQL.Tests` | ✅ | ✅ | Text, Binary (outbox); single (gateway) |
| `Paramore.Brighter.MongoDb.Tests` | ✅ | | single |
| `Paramore.Brighter.MySQL.Tests` | ✅ | | Text, Binary |
| `Paramore.Brighter.PostgresSQL.Tests` | ✅ | ✅ | Text, Binary (outbox); single (gateway) |
| `Paramore.Brighter.RMQ.Async.Tests` | | ✅ | Classic, Quorum |
| `Paramore.Brighter.RMQ.Sync.Tests` | | ✅ | single |
| `Paramore.Brighter.Redis.Tests` | | ✅ | single |
| `Paramore.Brighter.RocketMQ.Tests` | | ✅ | single |
| `Paramore.Brighter.Sqlite.Tests` | ✅ | | Text, Binary |

> **All 17 projects carrying a `test-configuration.json` are listed above**, derived from those
> files. If you add a project or change its variants, rebuild the whole row set from
> `tests/*/test-configuration.json` rather than editing one line — that is how this table came to
> be missing three projects and to describe Kafka's variants as they were two renames ago.

## Templates

Expand All @@ -80,7 +89,7 @@ Generated into the test project root. These provide common helpers used by both

### Outbox Templates

**Sync** (13 templates) and **Async** (13 templates) — each contains 1 provider interface + 12 test scenarios:
**Sync** (14 templates) and **Async** (14 templates) — each contains 1 provider interface + 13 test scenarios:

| Template | Description |
|---|---|
Expand All @@ -97,6 +106,7 @@ Generated into the test project root. These provide common helpers used by both
| `When_Retrieving_All_Messages_They_Should_Include_Dispatched_And_Undispatched` | Full message listing |
| `When_Retrieving_Outstanding_Messages_It_Should_Filter_By_Age` | Outstanding message age filtering |
| `When_Retrieving_Dispatched_Messages_It_Should_Filter_By_Age` | Dispatched message age filtering |
| `When_Storing_A_Message_With_A_Relative_DataSchema_It_Should_Be_Read_Back` | Relative `DataSchema` URI survives round-trip |

Templates containing `Transaction` in the filename are skipped when `SupportsTransactions` is `false`.

Expand All @@ -114,7 +124,7 @@ Templates containing `Transaction` in the filename are skipped when `SupportsTra

### Messaging Gateway Templates

**Reactor** (13 templates) and **Proactor** (13 templates) — each contains 1 provider interface + 12 test scenarios:
**Reactor** (21 templates) and **Proactor** (21 templates) — each contains 1 provider interface + 20 test scenarios:

| Template | Description |
|---|---|
Expand All @@ -125,12 +135,20 @@ Templates containing `Transaction` in the filename are skipped when `SupportsTra
| `When_a_message_consumer_reads_multiple_messages_should_receive_all_messages` | Batch receive |
| `When_sending_a_message_should_propagate_activity_context` | OpenTelemetry context propagation |
| `When_confirming_posting_a_message_should_receive_publish_confirmation` | Publisher confirms |
| `When_requeuing_a_failed_message_should_receive_message_again` | Basic requeue |
| `When_requeuing_a_failed_message_with_delay_should_receive_message_again` | Delayed requeue |
| `When_requeuing_a_message_too_many_times_should_move_to_dead_letter_queue` | DLQ redrive |
| `When_infrastructure_missing_and_assume_channel_should_throw_exception` | Assume mode error |
| `When_infrastructure_missing_and_validate_channel_should_throw_exception` | Validate mode error |
| `When_reading_a_delayed_message_via_the_messaging_gateway_should_delay_delivery` | Scheduled delivery |
| `When_nacking_a_message_it_should_be_redelivered` | Nack redelivery (FR-16) |
| `When_requeuing_a_failed_message_should_be_redelivered` | Basic requeue |
| `When_requeuing_a_failed_message_with_delay_should_redeliver_after_delay` | Delayed requeue (FR-2) |
| `When_requeuing_a_failed_message_with_zero_delay_should_redeliver_immediately` | Zero-delay requeue |
| `When_requeuing_a_message_too_many_times_should_move_to_dead_letter_queue` | Requeue budget exhausted to DLQ (FR-23) |
| `When_sending_a_delayed_message_should_deliver_after_delay` | Delayed send (FR-9) |
| `When_rejecting_message_should_include_metadata` | Rejection metadata stamped on the rejected message (FR-8) |
| `When_rejecting_message_with_delivery_error_should_send_to_dlq` | Delivery-error reject routes to the DLQ |
| `When_rejecting_message_with_unknown_reason_should_send_to_dlq` | Unknown reason defaults to the DLQ |
| `When_rejecting_message_with_unacceptable_reason_should_send_to_invalid_channel` | Unacceptable routes to the invalid channel |
| `When_rejecting_message_with_unacceptable_and_no_invalid_channel_should_fallback_to_dlq` | Unacceptable falls back to the DLQ when no invalid channel exists |
| `When_rejecting_message_with_no_channels_configured_should_acknowledge_and_log` | No DLQ and no invalid channel: acknowledge and continue |

Templates are skipped based on feature support flags (see [Feature Flags](#messaging-gateway-feature-flags) below).

Expand Down Expand Up @@ -213,8 +231,6 @@ To disable transaction tests for providers that don't support them (e.g. MongoDB
"MessageGatewayProvider": "Paramore.Brighter.Redis.Tests.MessagingGateway.RedisMessageGatewayProvider",
"Category": "Redis",
"CollectionName": "RedisMessagingGateway",
"HasSupportToDeadLetterQueue": true,
"HasSupportToRequeue": true,
"HasSupportToValidateInfrastructure": false
}
}
Expand All @@ -240,10 +256,7 @@ This generates tests into:
"CollectionName": "Classic",
"ReceiveMessageTimeoutInMilliseconds": 4000,
"HasSupportToPublishConfirmation": true,
"HasSupportToDeadLetterQueue": true,
"HasSupportToDelayedMessages": false,
"HasSupportToValidateBrokerExistence": true,
"HasSupportToRequeue": true
"HasSupportToValidateBrokerExistence": true
},
"Quorum": {
"Publication": "Paramore.Brighter.MessagingGateway.RMQ.Async.RmqPublication",
Expand All @@ -253,10 +266,7 @@ This generates tests into:
"CollectionName": "Quorum",
"ReceiveMessageTimeoutInMilliseconds": 4000,
"HasSupportToPublishConfirmation": true,
"HasSupportToDeadLetterQueue": true,
"HasSupportToDelayedMessages": false,
"HasSupportToValidateBrokerExistence": true,
"HasSupportToRequeue": true
"HasSupportToValidateBrokerExistence": true
}
}
}
Expand All @@ -280,11 +290,9 @@ Feature flags control which test templates are generated. When a flag is `false`
| Flag | Default | Skips templates containing | Use case |
|---|---|---|---|
| `HasSupportToPublishConfirmation` | `false` | `confirming_posting` | Transport doesn't support publisher confirms |
| `HasSupportToDelayedMessages` | `false` | `delayed_message`, `with_delay` | No delayed/scheduled message support |
| `HasSupportToDeadLetterQueue` | `false` | `dead_letter_queue` | No dead letter queue support |
| `HasSupportToValidateBrokerExistence` | `false` | `no_broker_created` | Transport can't validate broker existence |
| `HasSupportToRequeue` | `false` | `requeuing` | Transport doesn't support message requeue |
| `HasSupportToValidateInfrastructure` | **`true`** | `assume_channel`, `validate_channel` | Transport can't validate infrastructure existence |
| `HasSupportToDetectMissingInfrastructureOnAssume` | **`true`** | `assume_channel` | Transport honours an explicit `Validate` but completes silently against infrastructure that is absent when `OnMissingChannel.Assume` told it not to look (Kafka's KIP-848 consumer — gateway defect, tracked by #4299; drop the flag when fixed) |

### Messaging Gateway Provider Pattern

Expand Down Expand Up @@ -430,7 +438,7 @@ If you change a template pattern that also exists in these base classes, update

### Important: Generator Does Not Delete Stale Files

The generator only creates or overwrites files — it **never deletes** existing generated files. If you change a feature flag from `true` to `false` (e.g. disabling `HasSupportToDelayedMessages`), you must **manually delete** the previously-generated test files that are no longer wanted. Otherwise stale tests will remain and may fail.
The generator only creates or overwrites files — it **never deletes** existing generated files. If you change a feature flag from `true` to `false` (e.g. disabling `HasSupportToPublishConfirmation`), you must **manually delete** the previously-generated test files that are no longer wanted. Otherwise stale tests will remain and may fail.

Similarly, if you rename or remove a template, the old generated files remain on disk.

Expand Down
22 changes: 21 additions & 1 deletion .agent_instructions/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,24 @@ A run in `review-after` that drops any of these is defective — it is not "a di
- Write the integration test that exercises the behavior
- Get approval for the test
- Implement the code to make it pass
- This ensures you're building the right behavior from the start
- This ensures you're building the right behavior from the start

### RabbitMQ: run each suite against the broker version it targets

The two RabbitMQ suites do not target the same broker, and pointing one at the other's version
produces a wall of red that is not a regression.

- **`RMQ.Async` runs on 4.2 and 4.3+.** `RmqSubscription.isDurable` defaults to `true` there (#4355),
so a default subscription declares a queue 4.3 accepts.
- **`RMQ.Sync` runs on 4.2 only.** It targets the RabbitMQ 3.x line through `RabbitMQ.Client` 6.x, so
its `isDurable` default is deliberately still `false`. RabbitMQ **4.3 removed transient
non-exclusive queues**, so on a 4.3+ broker every queue declaration is rejected with
`INTERNAL_ERROR - Feature 'transient_nonexcl_queues' is deprecated`. Measured against 4.3.5:
**46 failed / 35 passed / 3 skipped**. This applies to the package, not just its tests — a default
subscription from `Paramore.Brighter.MessagingGateway.RMQ.Sync` is rejected by 4.3+ too.

`docker-compose-rmq.yaml` is pinned to 4.2 for this reason and CI uses it, so `rabbitmq-sync-ci` is
green. **Check the broker version before reading a local RabbitMQ failure** — `docker ps` will show
an unrelated 4.3 container holding 5672 on a developer machine. Do not "fix" the `isDurable: false`
sites in `Paramore.Brighter.RMQ.Sync.Tests` to make a 4.3 run pass; they match the product default
the package deliberately keeps.
42 changes: 24 additions & 18 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@ env:

jobs:
build:
# Increased from 30 to 40 minutes to prevent cancellations during test execution.
# The build includes compilation + running 3 test suites (Core.Tests, Extensions.Tests,
# Transforms.Adaptors.Tests) which can take 20-30 minutes in slower CI environments.
# Compilation plus four test suites: Core.Tests, Extensions.Tests, Transforms.Adaptors.Tests
# and Test.Generator.Tests. 60 minutes leaves room for a cold NuGet cache on a slow runner.
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -68,6 +67,13 @@ jobs:
# question already answered. net10.0 matches what generate-test.sh runs.
run: dotnet test tests/Paramore.Brighter.Test.Generator.Tests/Paramore.Brighter.Test.Generator.Tests.csproj -c Release --no-restore --logger GitHubActions --no-build -f net10.0

# The RocketMQ gateway's broker-free tests. rocketmq-ci is commented out below, so without
# this step the whole RocketMQ suite - and with it the builder-block extraction in
# RocketMqMessagePublisher - is executed by nothing in CI. The filter is what keeps the step
# honest: the other 47 tests in that project need a live broker and would fail here.
- name: RocketMQ Broker-Free Tests
run: dotnet test tests/Paramore.Brighter.RocketMQ.Tests/Paramore.Brighter.RocketMQ.Tests.csproj --filter "Category=RocketMQBrokerFree" -c Release --logger GitHubActions --no-restore --no-build

- name: Core Tests
run: |
dotnet test tests/Paramore.Brighter.Core.Tests/Paramore.Brighter.Core.Tests.csproj --filter "Fragile!=CI" -c Release --logger GitHubActions --no-restore --no-build
Expand Down Expand Up @@ -172,10 +178,9 @@ jobs:

redis-ci:
runs-on: ubuntu-latest
# Increased from 5 to 8 minutes to accommodate slower CI environments
# and service initialization time. This provides adequate buffer without
# being excessive for typical test execution (P95 < 5 min observed).
timeout-minutes: 8
# Raised from 8 to 15 when the generated conformance suite landed. Run 34214484655 measured
# this job at 7.0 minutes against the old 8-minute cap - the closest of any job to timing out.
timeout-minutes: 15
needs: [build]

services:
Expand Down Expand Up @@ -204,7 +209,7 @@ jobs:

mqtt-ci:
runs-on: ubuntu-latest
timeout-minutes: 8
timeout-minutes: 15
needs: [build]

services:
Expand All @@ -229,12 +234,12 @@ jobs:

rabbitmq-async-ci:
runs-on: ubuntu-latest
timeout-minutes: 8
timeout-minutes: 15
needs: [build]

services:
rabbitmq:
image: brightercommand/rabbitmq:4.2-management-delay
image: rabbitmq:4.2-management
ports:
- 5672:5672
# needed because the rabbitmq container does not provide a healthcheck
Expand All @@ -257,12 +262,12 @@ jobs:

rabbitmq-sync-ci:
runs-on: ubuntu-latest
timeout-minutes: 8
timeout-minutes: 15
needs: [build]

services:
rabbitmq:
image: brightercommand/rabbitmq:3.13-management-delay
image: rabbitmq:3.13-management
ports:
- 5672:5672
# needed because the rabbitmq container does not provide a healthcheck
Expand Down Expand Up @@ -362,7 +367,7 @@ jobs:

postgres-ci:
runs-on: ubuntu-latest
timeout-minutes: 8
timeout-minutes: 15
needs: [build]

services:
Expand Down Expand Up @@ -393,7 +398,7 @@ jobs:

sqlserver-ci:
runs-on: ubuntu-latest
timeout-minutes: 8
timeout-minutes: 15
needs: [build]

services:
Expand Down Expand Up @@ -479,7 +484,7 @@ jobs:
dotnet test ./tests/Paramore.Brighter.DynamoDB.V4.Tests/Paramore.Brighter.DynamoDB.V4.Tests.csproj --filter "Fragile!=CI" --configuration Release --logger "console;verbosity=normal" --logger GitHubActions --blame -v n
aws-mock-ci:
runs-on: ubuntu-latest
timeout-minutes: 8
timeout-minutes: 20
needs: build
env:
AWS_SERVICE_URL: http://localhost:4566
Expand Down Expand Up @@ -527,8 +532,9 @@ jobs:
runs-on: ubuntu-latest
# Two projects, run one after the other, and each carries live teardown tests that poll a
# deletion to a deadline — SQS documents a deleted queue as visible for up to sixty seconds,
# so the waiting is the test rather than slack in it. 8 minutes no longer leaves room.
timeout-minutes: 12
# so the waiting is the test rather than slack in it. 8 minutes no longer leaves room, and
# the conformance suite takes the AWS generated files from 168 to 312, so 12 does not either.
timeout-minutes: 20
if: |
(github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master')) ||
(github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork)
Expand Down Expand Up @@ -616,7 +622,7 @@ jobs:

azure-ci:
runs-on: ubuntu-latest
timeout-minutes: 8
timeout-minutes: 15
if: |
(github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master')) ||
(github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork)
Expand Down
Loading
Loading