Skip to content

test: create each SQL Server test database once, as rows arriving together would race it - #252

Merged
CaffeinatedCoder merged 2 commits into
release/2.3.1from
test/linux-leg-sweeps-2-3-1
Oct 31, 2026
Merged

CaffeinatedCoder merged 2 commits into
release/2.3.1from
test/linux-leg-sweeps-2-3-1

Conversation

@CaffeinatedCoder

@CaffeinatedCoder CaffeinatedCoder commented Oct 31, 2026 •

Copy link
Copy Markdown
Owner

Closes #251

Problem

After #250, CI's Linux test leg ends every run, with the analyzer tests and EF Core finishing within 40 s of each other (#251). The profile found two things. CMTK0003's sweep has nothing to share between rows. EF Core's query sweeps ran their rows one after another, which looked like the lever. On the way, the whole suite under parallel rows found a race in the SQL Server fixture: SqlServer.DatabaseAsync used ConcurrentDictionary.GetOrAdd(name, CreateAsync), which can run the factory more than once for callers that arrive together. The first rows of a sweep then dropped and created typekit_queries under each other (11,832 failures in that run).

Change

  • SqlServer.DatabaseAsync creates each database once, behind a Lazy<Task<string>>, the pattern the query sweeps already use for their seeded databases.
  • SqlServerFixtureTests: a guard that asks for one database from 32 callers at once.

Parallel rows for the EF Core project were in this PR's first commit and are taken out by its second. On CI they bought almost nothing, because the database containers share the runner's four cores with the tests:

#250's run This PR's first run
Test step, Linux 9m 28s 9m 17s
Test step, Windows 5m 17s 7m 11s

Test code only: no package, no changelog entry.

Tests

  • The guard fails 3 runs of 3 with the plain GetOrAdd restored, and passes with the Lazy.
  • The whole solution passes: 35,337 passed (one more, the guard) and 1,248 skipped, as before.

🤖 Generated with Claude Code

… SQL Server database once

After #250, CI's Linux leg ends every run, and the EF Core project is half of it: its two query sweeps are one
class each of 12,275 rows, which xunit's default mode ran one after another (#251). A row waits on SQLite, SQL
Server or PostgreSQL more than it computes: at four threads the project took 55 s instead of 123 s for the same
CPU. The project now runs with parallelMode "all" (xunit.runner.json). A row reads only what was seeded for its
model, and each SQLite class opens its own database per test.

SqlServerRoundTripTests opts out ([TestClass(DisableParallelization = true)]): each of its tests creates the
same tables in one database. Seeded by removing the opt-out: 5 of its 7 tests fail.

The whole suite found a race in the SQL Server fixture: DatabaseAsync's GetOrAdd ran its factory more than once
for callers that arrived together, and the first rows of a sweep dropped and created typekit_queries under each
other. Each database is now created once behind a Lazy, as the sweeps' own seeded databases are.
SqlServerFixtureTests asks for one database from 32 callers at once; with the plain GetOrAdd restored it fails
3 runs of 3.

The profile also answered the issue's other half: a CMTK0003 sweep row costs its own file, and reusing the
compilation or compiling the declarations to metadata saves nothing, so DroppedTaskVariantTests is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e fixture's create-once

On CI, parallel rows bought the EF Core project almost nothing (#251, #252's run): the database containers share
the runner's four cores with the tests, so what looked like waiting on a local machine with spare cores became
CPU. The Linux test step went from 9m 28s to 9m 17s, and the Windows one from 5m 17s to 7m 11s, as the projects
beside EF Core slowed. xunit.runner.json and SqlServerRoundTripTests' opt-out go.

SqlServer.DatabaseAsync keeps creating each database once behind a Lazy, with SqlServerFixtureTests as its guard:
GetOrAdd may run its factory twice for callers that arrive together, which rows run in parallel did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@CaffeinatedCoder CaffeinatedCoder changed the title test: run the EF Core query sweeps' rows in parallel, and create each SQL Server database once test: create each SQL Server test database once, as rows arriving together would race it Oct 31, 2026
@CaffeinatedCoder
CaffeinatedCoder merged commit abe2763 into release/2.3.1 Oct 31, 2026
9 checks passed
@CaffeinatedCoder
CaffeinatedCoder deleted the test/linux-leg-sweeps-2-3-1 branch October 31, 2026 11:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tests Adds or changes tests only (tests, probes, harnesses); no library code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant