Fix flaky PhysicalFileProvider TokensFiredForOldAndNewNamesOnRename test#130977
Fix flaky PhysicalFileProvider TokensFiredForOldAndNewNamesOnRename test#130977svick wants to merge 3 commits into
Conversation
The test waited a fixed 500ms after triggering the rename before asserting that the tokens had fired. PhysicalFilesWatcher.CancelToken cancels the token on a background thread-pool task, so under load (e.g. JitStress on slow arm64) the cancellation was not guaranteed to run within that window, causing the test to intermittently fail. Replace the fixed delay with the deterministic RegisterChangeCallback + TaskCompletionSource pattern already used by the sibling TokensFiredForNewDirectoryContentsOnRename test, awaiting the callbacks with a generous timeout instead. Fixes dotnet#129027 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7e73cf9d-189a-4b07-96d7-156844a6d647
Extract the repeated 30-second token-fire timeout into a single s_maxWaitForTokenToFire field and convert the existing WaitTimeForTokenToFire and WaitTimeForTokenCallback constants to TimeSpan fields for consistency. No behavioral change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7e73cf9d-189a-4b07-96d7-156844a6d647
|
Azure Pipelines: Successfully started running 3 pipeline(s). 12 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
Tagging subscribers to this area: @dotnet/area-extensions-filesystem |
There was a problem hiding this comment.
Pull request overview
This PR improves reliability of Microsoft.Extensions.FileProviders.Physical tests by removing a timing-based assertion from TokensFiredForOldAndNewNamesOnRename and replacing it with a deterministic callback + TaskCompletionSource wait (with a generous timeout). It also refactors the various timeout constants to TimeSpan fields for consistency and reuse.
Changes:
- Refactor test timeouts from
const intmillisecond values to sharedTimeSpanfields. - Fix
TokensFiredForOldAndNewNamesOnRenameflakiness by awaitingRegisterChangeCallbackcompletion (instead ofTask.Delay(500)). - Reuse a shared max-wait timeout (
s_maxWaitForTokenToFire) in the rename and polling tests.
| var oldTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously); | ||
| oldToken.RegisterChangeCallback(_ => oldTcs.TrySetResult(true), null); |
There was a problem hiding this comment.
Although this comment isn't wrong, but the recommendation is a low-value nit that conflicts with the established pattern the PR is intentionally following. I would ignore this comment.
There was a problem hiding this comment.
I like TCS<bool> slightly better, so I changed all instances in the file.
| var newTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously); | ||
| newToken.RegisterChangeCallback(_ => newTcs.TrySetResult(true), null); |
Address review feedback: use TaskCompletionSource<bool> instead of TaskCompletionSource<object> for the token-fired signals, which keeps the intent explicit and avoids boxing. Apply the same change to the existing signals in TokensFiredForNewDirectoryContentsOnRename for consistency. The non-generic TaskCompletionSource is not used because the test project also targets .NET Framework, where it is unavailable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7e73cf9d-189a-4b07-96d7-156844a6d647
Fixes #129027.
Problem
TokensFiredForOldAndNewNamesOnRenamewaited a fixed 500ms after triggering the rename before asserting that the tokens had fired.PhysicalFilesWatcher.CancelTokencancels the token on a background thread-pool task, so under load (e.g. JitStress on slow arm64) the cancellation was not guaranteed to run within that window, causing the test to intermittently fail.Fix
Replace the fixed delay with the deterministic
RegisterChangeCallback+TaskCompletionSourcepattern already used by the siblingTokensFiredForNewDirectoryContentsOnRenametest, awaiting the callbacks with a generous timeout instead.A second commit refactors the test's timeout values: the repeated 30-second token-fire timeout is extracted into a shared
s_maxWaitForTokenToFirefield, and the existingWaitTimeForTokenToFire/WaitTimeForTokenCallbackconstants are converted toTimeSpanfields for consistency. No behavioral change.Note
This PR was generated with the assistance of GitHub Copilot.