Fix flaky File_Move_Multiple_From_Watched_To_Unwatched_Mac test caused by duplicate FSEvents#125779
Open
Fix flaky File_Move_Multiple_From_Watched_To_Unwatched_Mac test caused by duplicate FSEvents#125779
File_Move_Multiple_From_Watched_To_Unwatched_Mac test caused by duplicate FSEvents#125779Conversation
…duplicating FSEvents on Mac On macOS, FSEvents can deliver duplicate Deleted events when moving files/directories from a watched to an unwatched directory. The existing isFilteredOut filter only handles stale Created/Changed events, but not duplicate Deleted events. Fix by using a ConcurrentDictionary to track seen events and filter out duplicates when skipOldEvents=true (the Mac code path). Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix File_Move_Multiple_From_Watched_To_Unwatched_Mac test failure
Fix flaky Mar 19, 2026
File_Move_Multiple_From_Watched_To_Unwatched_Mac test caused by duplicate FSEvents
Contributor
|
Tagging subscribers to this area: @dotnet/area-system-io |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a macOS-specific flakiness in System.IO.FileSystem.Watcher move tests by preventing duplicate FSEvents Deleted notifications from causing ExpectEvents to complete early and record extra events.
Changes:
- Add a
ConcurrentDictionary<FiredEvent, bool>-backed deduplication filter (viaTryAdd) whenskipOldEvents=true. - Apply the same deduplication approach to both file-move and directory-move “watched → unwatched” multi-item tests on macOS.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.File.Move.cs | When skipOldEvents is enabled (macOS path), filters duplicate fired events (same (EventType, Path[, OldPath])) to avoid premature completion. |
| src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.Directory.Move.cs | Same deduplication strategy applied to directory move tests under the macOS skipOldEvents configuration. |
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.
Description
macOS FSEvents can deliver duplicate
Deletedevents when moving files/directories from a watched to an unwatched directory. The existingisFilteredOutfilter (Mac path,skipOldEvents=true) only discarded staleCreated/Changedevents—not duplicateDeletedevents—causingExpectEventsto signal completion prematurely and collect an extra event:Changes:
FileSystemWatcher.File.Move.cs/FileSystemWatcher.Directory.Move.cs: WhenskipOldEvents=true, replace the single-line lambdaisFilteredOutwith aConcurrentDictionary<FiredEvent, bool>-backed deduplicator.TryAddis atomic: first occurrence passes through, subsequent duplicates of the same(EventType, Path)are filtered out.Changes
FileMove_Multiple_FromWatchedToUnwatchedandDirectoryMove_Multiple_FromWatchedToUnwatchedto deduplicate events viaConcurrentDictionary.TryAddin addition to the existing stale-event filtering.Testing
Existing tests cover the changed paths. The fix directly addresses the observed failure mode (duplicate
Deletedevents inflating the collected event list).Original prompt
This section details on the original issue you should resolve
<issue_title>System.IO.Tests.File_Move_Tests.File_Move_Multiple_From_Watched_To_Unwatched_Mac test failure</issue_title>
<issue_description>```
Discovered: System.IO.FileSystem.Watcher.Tests (found 166 of 210 test cases)
Starting: System.IO.FileSystem.Watcher.Tests (parallel test collections = on [6 threads], stop on fail = off)
System.IO.Tests.File_Move_Tests.File_Move_Multiple_From_Watched_To_Unwatched_Mac(filesCount: 2) [FAIL]
Assert.Equal() Failure: Collections differ
↓ (pos 1)
Expected: ArraySelectIterator<<>f__AnonymousType1<string, string>, FiredEvent> [Deleted /tmp/helix/working/9FEF0885/t/#File_Move_Tests_r5rmsjek.mw5/dir_watched/file0 , Deleted /tmp/helix/working/9FEF0885/t/#File_Move_Tests_r5rmsjek.mw5/dir_watched/file1 ]
Actual: List [Deleted /tmp/helix/working/9FEF0885/t/#File_Move_Tests_r5rmsjek.mw5/dir_watched/file0 , Deleted /tmp/helix/working/9FEF0885/t/#File_Move_Tests_r5rmsjek.mw5/dir_watched/file0 , Deleted /tmp/helix/working/9FEF0885/t/#File_Move_Tests_r5rmsjek.mw5/dir_watched/file1 ]
↑ (pos 1)
Stack Trace:
//src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.File.Move.cs(234,0): at System.IO.Tests.File_Move_Tests.FileMove_Multiple_FromWatchedToUnwatched(Int32 filesCount, Boolean skipOldEvents)
//src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.File.Move.cs(48,0): at System.IO.Tests.File_Move_Tests.File_Move_Multiple_From_Watched_To_Unwatched_Mac(Int32 filesCount)
at System.Object.InvokeStub_File_Move_Tests.File_Move_Multiple_From_Watched_To_Unwatched_Mac(Object, Span`1)
/_/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs(95,0): at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
System.IO.Tests.FileSystemWatcherTests_netstandard17.DroppedWatcher_Collectible [SKIP]
Condition(s) not met: "IsPreciseGcSupported"
Finished: System.IO.FileSystem.Watcher.Tests
Known issue validation
Build: 🔎 https://dev.azure.com/dnceng-public/public/_build/results?buildId=1314668
Error message validated:
[System.IO.Tests.File_Move_Tests.File_Move_Multiple_From_Watched_To_Unwatched_Mac.*FAIL]Result validation: ✅ Known issue matched with the provided build.
Validation performed at: 3/1/2026 12:32:32 AM UTC
Report
🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.