Skip to content

[ci-fix-net11] De-flake Essentials.AI file-based tests (FileShare.ReadWrite) - #36604

Closed
github-actions[bot] wants to merge 1 commit into
net11.0from
ci-fix/issue-36452-9eedadc60c56de99
Closed

[ci-fix-net11] De-flake Essentials.AI file-based tests (FileShare.ReadWrite)#36604
github-actions[bot] wants to merge 1 commit into
net11.0from
ci-fix/issue-36452-9eedadc60c56de99

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Summary

Fixes an intermittent IOException ("The process cannot access the file because it is being used by another process") in the Essentials.AI.UnitTests file-based tests on Windows Helix.

Root cause: Multiple parallel xUnit test classes (StreamingJsonDeserializerTests.FileBasedTests, JsonStreamingRoundtripTests.FileBasedTests, JsonStreamChunkerTests.IntegrationTests) read the same shared TestData/DataStreams files via File.ReadAllLines(...). File.ReadAllLines opens with FileShare.Read, so a concurrent opener that holds a write/exclusive handle races and throws on Windows.

Fix: Added DataStreamsHelper.ReadAllLinesShared(path) which opens the file with FileShare.ReadWrite and routes all shared-file reads through it. This is a pure test-synchronization de-flake — no assertions were changed or weakened, and no test was muted/ignored/retried.

Changed call sites (10, test project only)

  • TestHelpers/DataStreamsHelper.cs (new helper + GetFileLines)
  • Tests/StreamingJsonDeserializerTests/FileBasedTests.cs (6)
  • Tests/JsonStreamingRoundtripTests/FileBasedTests.cs (2)
  • Tests/JsonStreamChunkerTests/Integration.cs (1)

Validation

Not run locally — the failure is a Windows-only, intermittent parallel-file-access race (2/10 builds) that is not deterministically reproducible on this Linux runner. The change is confined to the test project and preserves all assertions; correctness is validated by CI.


Target branch: net11.0
Refs: #36452
Attempt: 1/10

Generated by CI Failure Fixer (net11.0) · 367.5 AIC · ⌖ 29.8 AIC · ⊞ 5.1K ·

…estData with FileShare.ReadWrite

Parallel xUnit test classes read the same TestData files via File.ReadAllLines,
which defaults to FileShare.Read and races on Windows, intermittently throwing
IOException 'The process cannot access the file because it is being used by
another process'. Route all shared-file reads through a DataStreamsHelper
helper that opens with FileShare.ReadWrite. No assertions changed.

Refs: #36452

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
There may be pipelines that require an authorized user to comment /azp run to run.

@PureWeen

Copy link
Copy Markdown
Member

/azp run maui-pr-uitests

@PureWeen

Copy link
Copy Markdown
Member

/azp run maui-pr-devicetests

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

1 similar comment
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@github-actions

Copy link
Copy Markdown
Contributor Author

Target test StreamingJsonDeserializerTests + FileBasedTests validated green on head 0f84184 — Windows Helix Unit Tests Debug + Release both succeeded (build 1511617). Windows-only tests, so no cross-platform gap. Remaining CI red is unrelated flake/baseline (AOT macOS #36081; iOS Blazor canceled/infra). De-flake introduces no muting or test weakening. Ready for maintainer review.

Generated by CI Failure Fixer (net11.0) · 282.8 AIC · ⌖ 11.9 AIC · ⊞ 5.1K

@github-actions
github-actions Bot marked this pull request as ready for review July 16, 2026 12:55
@github-actions

Copy link
Copy Markdown
Contributor Author

♻️ Attempt 1/10 — red is unrelated flake/baseline, not this fix. On 0f8418486288404add5dcc06ddde7acb184fbac7 (merge build 1511617) the only non-green legs are:

The target legs for this de-flake — Windows Helix Unit Tests (Debug) and (Release) — both succeeded. This PR only swaps File.ReadAllLines for a shared-read helper in the test project, so it is not implicated in either red leg. A maintainer re-run (/azp run maui-pr) should clear the transient iOS cancellation.

Generated by CI Failure Fixer (net11.0) · 282.8 AIC · ⌖ 11.9 AIC · ⊞ 5.1K ·

@github-actions

Copy link
Copy Markdown
Contributor Author

🎯 Target test validated green on 0f8418486288404add5dcc06ddde7acb184fbac7. StreamingJsonDeserializerTests + the sibling file-based tests passed on every platform they run on — Windows Helix Unit Tests Debug + Release (build 1511617). These are Windows-only unit tests, so there is no other-platform coverage gap.

The change is a genuine de-flake (replacing File.ReadAllLines with a FileShare.ReadWrite shared-read helper across the affected test call sites) — no test is skipped, weakened, or muted. The remaining CI red is unrelated (AOT macOS baseline #36081; iOS Blazor canceled/infra).

Transitioning from draft → ready for review and adding p/0. A maintainer still reviews and merges.

Generated by CI Failure Fixer (net11.0) · 282.8 AIC · ⌖ 11.9 AIC · ⊞ 5.1K ·

@github-actions github-actions Bot added the p/0 Current heighest priority issues that we are targeting for a release. label Jul 16, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
There may be pipelines that require an authorized user to comment /azp run to run.

@github-actions github-actions Bot mentioned this pull request Jul 16, 2026

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 AI-generated review (multi-model pipeline: Opus 4.8 · GPT-5.5 · Gemini 3.1 Pro), on behalf of @kubaflo.

Multi-model consensus: the fix masks the symptom, not the root cause

All three models independently converged on the same mechanism, and I verified it against the source at this PR's head. The de-flake is a net improvement for the reported IOException, but it targets the wrong half of the race and can trade a loud failure for a silent torn read.

The real root cause (verified)

The PR premise — "multiple parallel xUnit classes using File.ReadAllLines conflict" — is not what causes the sharing violation. File.ReadAllLines opens with FileAccess.Read / FileShare.Read; concurrent pure readers can never conflict with each other.

The actual writer is here:

// src/AI/tests/Essentials.AI.UnitTests/Tests/JsonStreamChunkerTests/Integration.cs:31-33
// For debugging - write chunks to .txt file
var txtPath = DataStreamsHelper.GetTxtItinerary(fileName);
File.WriteAllLines(txtPath, chunks);
  • Writer (JsonStreamChunkerTests.IntegrationTests) does File.WriteAllLinesFileMode.Create (truncate-then-write) on TestData/DataStreams/Itinerary/<name>.txt.
  • Reader (StreamingJsonDeserializerTests.FileBasedTests, via DataStreamsHelper.TxtItineraries MemberData) reads those exact same *.txt files — a different class ⇒ parallel under xUnit.

The original IOException was reader (FileShare.Read) vs. concurrent writer — the writer's granted Write access is not permitted by the reader's FileShare.Read. The IOException is itself the proof the two collide.

Why FileShare.ReadWrite is a regression in disguise

Relaxing the reader to FileShare.ReadWrite lets the open succeed while the writer holds the file open. But because File.WriteAllLines truncates to 0 bytes first, a reader that opens inside the write window can now observe an empty or partially-written filechunks short/empty → e.g. lastItinerary stays null (Assert.NotNull fails) or partial JSON fails an equivalence assert. The comment claiming this "makes the shared reads deterministic" is inaccurate — it makes them non-throwing, not deterministic; content-wise it becomes less deterministic. Net effect: a loud, obviously-infra IOException becomes a rare, hard-to-diagnose content flake that looks like a real test failure (or silently false-passes).

Model panel

Model Verdict Note
Gemini 3.1 Pro NEEDS_CHANGES Root-cause misdiagnosis + silent-corruption race; revert and delete the debug-write
GPT-5.5 NEEDS_DISCUSSION Torn/partial-read risk from the concurrent truncating writer
Opus 4.8 LGTM (⚠️ non-blocking) Confirms the identical writer/reader race; flags it as a follow-up

Unanimous on the mechanism; the split is only on whether it blocks. Because a trivial, strictly-better fix exists that removes the root cause, we're landing on NEEDS_CHANGES.

Suggested fix (trivial, eliminates the root cause)

Prefer any of these over relaxing the share mode:

  1. Delete the debug-write at Integration.cs:31-33 — it's labeled "For debugging" and mutates checked-in fixtures that another parallel class reads. Removing it makes every access to Itinerary/*.txt a pure read, so no share-mode change is needed at all. (Recommended — smallest, and it's what makes the reads genuinely deterministic.)
  2. Redirect the debug-write to a unique temp path outside the Itinerary/*.txt read set (e.g. Path.GetTempFileName()), so no test writes a file another test reads.
  3. Put the writer and reader classes in the same xUnit [Collection] to serialize them.

What's genuinely good here

  • ReadAllLinesShared is rigorously equivalent to File.ReadAllLines (UTF-8 + BOM detection, all line terminators, single trailing newline, empty-file → empty array) and is stateless/thread-safe — all three models verified this.
  • All racing read sites are covered (direct + via GetFileLines).
  • CI red is not PR-caused — the failing legs are UI/device-test builds and AOT-Blazor integration; none touch Essentials.AI.UnitTests.

Bottom line: keep the equivalence work if you like, but fix the writer — dropping the Integration.cs:31-33 debug-write is the clean, root-cause fix. As written, the PR reduces the IOException frequency at the cost of a subtler torn-read possibility on the same shared files.

ℹ Automated multi-model review. This is advisory — a human maintainer makes the final merge decision.

@PureWeen

Copy link
Copy Markdown
Member

/azp run maui-pr

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agentic-workflows p/0 Current heighest priority issues that we are targeting for a release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants