Make the test suite safe to run in parallel worker processes - #389
Open
jeremydmiller wants to merge 1 commit into
Open
Make the test suite safe to run in parallel worker processes#389jeremydmiller wants to merge 1 commit into
jeremydmiller wants to merge 1 commit into
Conversation
Two changes, both needed before the suite can be split across processes that
each own a database. Measured with Bobcat's supervisor driving the MTP
executable: 15.9 min sequential -> 6.1 min at four workers, 1587/1587 green.
Never rewrite a connection string by text. This appeared in three MultiTenancy
files and was silently wrong:
ConnectionSource.ConnectionString.Replace("Initial Catalog=master", $"Database={name}")
It only rewrites while the catalog happens to be "master". Point
POLECAT_TESTING_DATABASE at anything else and the literal is absent, the
replace matches nothing, and the "other" database quietly resolves to the
current one — so the test asserts against itself. ConnectionSource now exposes
ConnectionStringFor / MasterConnectionString / DatabaseName built on
SqlConnectionStringBuilder, which is correct whatever the catalog is called.
Name every database a test creates with ConnectionSource.Scoped(...). A
database a test creates is a sibling of the process's own database, not a child
of it, so giving each worker its own catalog does NOT isolate them. A hardcoded
"polecat_tenant_a" is one database shared by every worker on the box, and they
raced to create and drop it — "User does not have permission to alter database
'polecat_tenant_a'" under four workers. Scoped() yields "master_tenant_a"
locally and "polecat_w3_tenant_a" under a parallel runner.
Schema names deliberately keep hardcoded names: they live inside the catalog,
so per-worker databases already separate them.
Fixing the Replace bug also cleared a MultiTenancy failure that predated any of
this work — the 25 MultiTenancy tests now pass against the default master
catalog too, where one was failing before.
Both rules are written up in CLAUDE.md under Testing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vmmUkRtSFMk1Pbf9E5eor
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.
Two changes needed before the suite can be split across processes that each own a database.
Measured with Bobcat's supervisor driving the MTP executable directly: 15.9 min → 6.1 min at four workers, 1587/1587 green. No changes to
Polecat.Tests.csproj— it is already an MTP host.1. Never rewrite a connection string by text
This was in three MultiTenancy files and was silently wrong:
It only rewrites while the catalog happens to be
master. PointPOLECAT_TESTING_DATABASEat anything else and the literal is absent, the replace matches nothing, and the "other" database quietly resolves to the current one — so the test asserts against itself.ConnectionSourcenow exposesConnectionStringFor(name),MasterConnectionStringandDatabaseName, built onSqlConnectionStringBuilder, which is correct whatever the catalog is called.Worth noting: fixing this also cleared a MultiTenancy failure that predated any of this work. The 25 MultiTenancy tests now pass against the default
mastercatalog too, where one was failing before.2. Scope the names of databases a test creates
A database a test creates is a sibling of the process's own database, not a child of it — so giving each worker its own catalog does not isolate them. A hardcoded name is one database shared by every worker on the box:
Under four workers this produced "User does not have permission to alter database 'polecat_tenant_a'" — non-deterministically, as they raced to create and drop it.
Schema names deliberately keep their hardcoded values: they live inside the catalog, so per-worker databases already separate them. That is why
SchemaName = "doc_usage"in nine files is fine.Not a behaviour change for CI today
Nothing here alters the sequential run. With
POLECAT_TESTING_DATABASEunset everything resolves tomasterexactly as before — verified green on the existing path. This only makes the suite able to be parallelised; adopting that is a separate decision.Both rules are written up in
CLAUDE.mdunder Testing, since they are easy to reintroduce by accident.🤖 Generated with Claude Code
https://claude.ai/code/session_012vmmUkRtSFMk1Pbf9E5eor