test: concurrency / race-condition stress testing with Coyote (#207) - #312
Merged
Conversation
Adds tests/Wolfgang.Etl.Abstractions.Tests.Concurrency + .github/workflows/coyote.yaml. Microsoft Coyote rewrites the assemblies to control the task scheduler and replays each test under thousands of distinct interleavings, surfacing races/deadlocks a normal single-schedule run never hits. `coyote test` exits non-zero on a found bug, so it is an enforced gate. Two systematic tests over the base-class concurrency: - concurrent per-item counter increments never lose an update (the counter is Interlocked — a non-atomic ++ would surface as a lost update on some schedule); - DisposeAsync racing an in-flight enumeration never deadlocks. Both explore ~1600 unique execution paths locally with 0 bugs found. The project targets net8.0 because the Coyote 1.7.x CLI cannot load net10.0 assemblies (it predates that runtime); the concurrency explored is runtime-agnostic. coyote.yaml gates PRs touching src/** (1000 iterations/test) and runs the deep exploration weekly + on dispatch (10000 iterations/test). The optional 24h soak (leak hunting via dotnet-counters) is NOT implemented — it needs a persistent self-hosted runner this project lacks; documented in the workflow header for when one exists. Closes #207 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jul 24, 2026
This was referenced Aug 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds systematic concurrency testing with Microsoft Coyote (issue #207). Coyote rewrites the assemblies to control the task scheduler, then replays each test under thousands of distinct interleavings — surfacing races/deadlocks that a normal single-schedule run (a million times in CI) never hits.
coyote testexits non-zero on a found bug, so it's an enforced gate.tests/Wolfgang.Etl.Abstractions.Tests.Concurrency— two systematic tests over the base-class concurrency:Interlocked— a non-atomic++would surface as a lost update on some explored schedule);DisposeAsyncracing an in-flight enumeration never deadlocks..github/workflows/coyote.yaml— gates PRs touchingsrc/**(1000 iterations/test) and runs the deep exploration weekly + on dispatch (10000 iterations/test).Targets net8.0 deliberately: the Coyote 1.7.x CLI can't load net10.0 assemblies (it predates that runtime), and the concurrency explored is runtime-agnostic.
Validation
Ran locally (rewrite +
coyote test):Concurrent_item_count_increments…— 0 bugs, 2000 paths (1360 unique).Dispose_racing_enumeration…— 0 bugs, 2000 paths (1604 unique).This PR touches
coyote.yaml+ the concurrency project, so its own CI runs the Coyote gate end to end.Acceptance criteria (#207)
tests/…Tests.Concurrency/project instruments key public APIs with CoyoteThe two required criteria are met; the soak is the issue's own "optionally also" item.
Closes #207