@
Symptom
On a full dotnet test run, D365FO.Core.Tests.WorkflowScaffolderTests.Scaffolded_workflow_objects_pass_the_pre_write_guards intermittently fails:
Assert.Equal() Failure: Values differ
Expected: 3
Actual: 2
at D365FO.Core.Tests.WorkflowScaffolderTests.Scaffolded_workflow_objects_pass_the_pre_write_guards()
in tests/D365FO.Core.Tests/WorkflowScaffolderTests.cs:line 189
The test writes three scaffolded workflow documents into a fresh GUID-named temp directory and asserts three *.xml files exist.
What is notable about the failure mode
It fails on the count, not on an exception. All three ScaffoldFileWriter.Write calls returned successfully — WriteCore either writes the file or throws, and nothing threw. So a file was written and then went missing, or one write landed somewhere other than its explicit path.
Reproduction
Not reliably reproducible. Observed once on a cold full-suite run (that run took 1m11s; the passing re-run took 18s, so the failing run was under noticeably more contention).
Does not reproduce:
- in isolation:
dotnet test --filter "FullyQualifiedName~WorkflowScaffolderTests" → 11/11 pass
- on a full-suite re-run → 962/962 pass
- via a standalone console repro driving the same three
WorkflowScaffolder factories through ScaffoldFileWriter.Write — all three files land every time:
--- WorkflowTemplate: root=<AxWorkflowTemplate> WROTE ConVehicleReview.xml (460 bytes)
--- WorkflowApproval: root=<AxWorkflowApproval> WROTE ConVehicleApproval.xml (645 bytes)
--- WorkflowTask: root=<AxWorkflowTask> WROTE ConVehicleTask.xml (576 bytes)
*.xml count = 3
Suspected cause
ScaffoldFileWriter.WriteCore reads process-wide state on every call:
var cfg = D365FoSettings.FromEnvironment();
PathGuard.EnsureWithinBoundary(full, new[] { cfg.PackagesPath, cfg.WorkspacePath }
.Concat(cfg.CustomPackagesPaths).ToArray());
Four Core test classes mutate environment variables and run in parallel with this one:
D365FoSettingsResolveTests
ObjectModifyEngineTests
ProvenanceStoreTests
ScaffoldFileWriterJournalTests
A race there is the most plausible explanation for the write path behaving differently under load. It does not fully explain a silent loss (a boundary rejection throws), so the journal path (RecordJournalEntry) and the atomic .tmp → target File.Move are also worth looking at — a File.Move that reports success while another process holds/reaps the target would fit the symptom.
Why this is being filed separately
Discovered while validating #157 (landing knowledge-audit Phase 2 on main). It is not a regression from that merge: neither side of the merge touches WorkflowScaffolderTests.cs, WorkflowScaffolder.cs, or the ScaffoldFileWriter write path, and CI is green on main.
Suggested fix direction
Give the env-mutating test classes a shared xUnit collection (or an IDisposable fixture that serialises them) so they cannot interleave with tests that call D365FoSettings.FromEnvironment(). If the loss turns out not to be env-related, add a post-write existence assertion inside WriteCore so the failure surfaces at the write rather than at a later count.
🤖 Generated with Claude Code
@
@
Symptom
On a full
dotnet testrun,D365FO.Core.Tests.WorkflowScaffolderTests.Scaffolded_workflow_objects_pass_the_pre_write_guardsintermittently fails:The test writes three scaffolded workflow documents into a fresh GUID-named temp directory and asserts three
*.xmlfiles exist.What is notable about the failure mode
It fails on the count, not on an exception. All three
ScaffoldFileWriter.Writecalls returned successfully —WriteCoreeither writes the file or throws, and nothing threw. So a file was written and then went missing, or one write landed somewhere other than its explicit path.Reproduction
Not reliably reproducible. Observed once on a cold full-suite run (that run took 1m11s; the passing re-run took 18s, so the failing run was under noticeably more contention).
Does not reproduce:
dotnet test --filter "FullyQualifiedName~WorkflowScaffolderTests"→ 11/11 passWorkflowScaffolderfactories throughScaffoldFileWriter.Write— all three files land every time:Suspected cause
ScaffoldFileWriter.WriteCorereads process-wide state on every call:Four Core test classes mutate environment variables and run in parallel with this one:
D365FoSettingsResolveTestsObjectModifyEngineTestsProvenanceStoreTestsScaffoldFileWriterJournalTestsA race there is the most plausible explanation for the write path behaving differently under load. It does not fully explain a silent loss (a boundary rejection throws), so the journal path (
RecordJournalEntry) and the atomic.tmp→ targetFile.Moveare also worth looking at — aFile.Movethat reports success while another process holds/reaps the target would fit the symptom.Why this is being filed separately
Discovered while validating #157 (landing knowledge-audit Phase 2 on main). It is not a regression from that merge: neither side of the merge touches
WorkflowScaffolderTests.cs,WorkflowScaffolder.cs, or theScaffoldFileWriterwrite path, and CI is green onmain.Suggested fix direction
Give the env-mutating test classes a shared xUnit collection (or an
IDisposablefixture that serialises them) so they cannot interleave with tests that callD365FoSettings.FromEnvironment(). If the loss turns out not to be env-related, add a post-write existence assertion insideWriteCoreso the failure surfaces at the write rather than at a later count.🤖 Generated with Claude Code
@