improve stability of FileSystemWatcher tests (dotnet/corefx#40543)
authorTomas Weinfurt <tweinfurt@yahoo.com>
Wed, 25 Sep 2019 21:30:10 +0000 (14:30 -0700)
committerGitHub <noreply@github.com>
Wed, 25 Sep 2019 21:30:10 +0000 (14:30 -0700)
* improve stability of watcher tests

* feedback from review

* more feedback

* disable parallelization for dangerous tests

* enable FileSystemWatcher_File_Create_ForceLoopRestart  again

* feedback from review

Commit migrated from https://github.com/dotnet/corefx/commit/e8fd8931d488d2e06a25a49c0d722b67f35e10fa

src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.MultipleWatchers.cs
src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.unit.cs
src/libraries/System.IO.FileSystem.Watcher/tests/Utility/FileSystemWatcherTest.cs

index 37ed4c1..a322cd3 100644 (file)
 using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
+
 using Xunit;
+using Xunit.Abstractions;
 
 namespace System.IO.Tests
 {
     public class FileSystemWatcher_Multiple_Test : FileSystemWatcherTest
     {
+        private readonly ITestOutputHelper _output;
+
+        private void OnError(object source, ErrorEventArgs e)
+        {
+            string msg = $"Watcher failed: {e.GetException()} source={source} {source.GetHashCode()}";
+            _output.WriteLine(msg);
+            // Repeat on Console so it easier to triage in CI.
+            Console.WriteLine(msg);
+        }
+
+        public FileSystemWatcher_Multiple_Test(ITestOutputHelper output)
+        {
+            _output = output;
+        }
+
         [OuterLoop]
         [Fact]
         public void FileSystemWatcher_File_Create_ExecutionContextFlowed()
         {
-            ExecuteWithRetry(() =>
+            using (var watcher1 = new FileSystemWatcher(TestDirectory))
+            using (var watcher2 = new FileSystemWatcher(TestDirectory))
             {
-                using (var watcher1 = new FileSystemWatcher(TestDirectory))
-                using (var watcher2 = new FileSystemWatcher(TestDirectory))
-                {
-                    string fileName = Path.Combine(TestDirectory, "file");
-                    watcher1.Filter = Path.GetFileName(fileName);
-                    watcher2.Filter = Path.GetFileName(fileName);
+                string fileName = Path.Combine(TestDirectory, "file");
+                watcher1.Filter = Path.GetFileName(fileName);
+                watcher2.Filter = Path.GetFileName(fileName);
 
-                    var local = new AsyncLocal<int>();
+                var local = new AsyncLocal<int>();
 
-                    var tcs1 = new TaskCompletionSource<int>();
-                    var tcs2 = new TaskCompletionSource<int>();
-                    watcher1.Created += (s, e) => tcs1.SetResult(local.Value);
-                    watcher2.Created += (s, e) => tcs2.SetResult(local.Value);
+                var tcs1 = new TaskCompletionSource<int>();
+                var tcs2 = new TaskCompletionSource<int>();
+                watcher1.Created += (s, e) => tcs1.SetResult(local.Value);
+                watcher2.Created += (s, e) => tcs2.SetResult(local.Value);
 
-                    local.Value = 42;
-                    watcher1.EnableRaisingEvents = true;
-                    local.Value = 84;
-                    watcher2.EnableRaisingEvents = true;
-                    local.Value = 168;
+                watcher1.Error += OnError;
+                watcher2.Error += OnError;
 
-                    File.Create(fileName).Dispose();
-                    Task.WaitAll(new[] { tcs1.Task, tcs2.Task }, WaitForExpectedEventTimeout);
+                local.Value = 42;
+                watcher1.EnableRaisingEvents = true;
+                local.Value = 84;
+                watcher2.EnableRaisingEvents = true;
+                local.Value = 168;
 
-                    Assert.Equal(42, tcs1.Task.Result);
-                    Assert.Equal(84, tcs2.Task.Result);
-                }
-            });
+                File.Create(fileName).Dispose();
+                Task.WaitAll(new[] { tcs1.Task, tcs2.Task }, WaitForExpectedEventTimeout);
+
+                Assert.Equal(42, tcs1.Task.Result);
+                Assert.Equal(84, tcs2.Task.Result);
+            }
         }
 
         [OuterLoop]
         [Fact]
         public void FileSystemWatcher_File_Create_SuppressedExecutionContextHandled()
         {
-            ExecuteWithRetry(() =>
+            using (var watcher1 = new FileSystemWatcher(TestDirectory))
             {
-                using (var watcher1 = new FileSystemWatcher(TestDirectory))
-                {
-                    string fileName = Path.Combine(TestDirectory, "file");
-                    watcher1.Filter = Path.GetFileName(fileName);
+                string fileName = Path.Combine(TestDirectory, "FileSystemWatcher_File_Create_SuppressedExecutionContextHandled");
+                watcher1.Filter = Path.GetFileName(fileName);
+                watcher1.Error += OnError;
 
-                    var local = new AsyncLocal<int>();
+                var local = new AsyncLocal<int>();
 
-                    var tcs1 = new TaskCompletionSource<int>();
-                    watcher1.Created += (s, e) => tcs1.SetResult(local.Value);
+                var tcs1 = new TaskCompletionSource<int>();
+                watcher1.Created += (s, e) => tcs1.SetResult(local.Value);
 
-                    local.Value = 42;
+                local.Value = 42;
 
-                    ExecutionContext.SuppressFlow();
-                    try
-                    {
-                        watcher1.EnableRaisingEvents = true;
-                    }
-                    finally
-                    {
-                        ExecutionContext.RestoreFlow();
-                    }
+                ExecutionContext.SuppressFlow();
+                try
+                {
+                    watcher1.EnableRaisingEvents = true;
+                }
+                finally
+                {
+                    ExecutionContext.RestoreFlow();
+                }
 
                     File.Create(fileName).Dispose();
                     tcs1.Task.Wait(WaitForExpectedEventTimeout);
 
                     Assert.Equal(0, tcs1.Task.Result);
-                }
-            });
+           }
         }
 
         [OuterLoop]
         [Fact]
         public void FileSystemWatcher_File_Create_NotAffectEachOther()
         {
-            ExecuteWithRetry(() =>
+            using (var watcher1 = new FileSystemWatcher(TestDirectory))
+            using (var watcher2 = new FileSystemWatcher(TestDirectory))
+            using (var watcher3 = new FileSystemWatcher(TestDirectory))
             {
-                using (var watcher1 = new FileSystemWatcher(TestDirectory))
-                using (var watcher2 = new FileSystemWatcher(TestDirectory))
-                using (var watcher3 = new FileSystemWatcher(TestDirectory))
-                {
-                    string fileName = Path.Combine(TestDirectory, "file");
-                    watcher1.Filter = Path.GetFileName(fileName);
-                    watcher2.Filter = Path.GetFileName(fileName);
-                    watcher3.Filter = Path.GetFileName(fileName);
+                string fileName = Path.Combine(TestDirectory, "FileSystemWatcher_File_Create_NotAffectEachOther");
+                watcher1.Filter = Path.GetFileName(fileName);
+                watcher2.Filter = Path.GetFileName(fileName);
+                watcher3.Filter = Path.GetFileName(fileName);
 
-                    AutoResetEvent autoResetEvent1 = WatchCreated(watcher1, new[] { fileName }).EventOccured;
-                    AutoResetEvent autoResetEvent2 = WatchCreated(watcher2, new[] { fileName }).EventOccured;
-                    AutoResetEvent autoResetEvent3 = WatchCreated(watcher3, new[] { fileName }).EventOccured;
+                watcher1.Error += OnError;
+                watcher2.Error += OnError;
+                watcher3.Error += OnError;
 
-                    watcher1.EnableRaisingEvents = true;
-                    watcher2.EnableRaisingEvents = true;
-                    watcher3.EnableRaisingEvents = true;
+                AutoResetEvent autoResetEvent1 = WatchCreated(watcher1, new[] { fileName }).EventOccured;
+                AutoResetEvent autoResetEvent2 = WatchCreated(watcher2, new[] { fileName }).EventOccured;
+                AutoResetEvent autoResetEvent3 = WatchCreated(watcher3, new[] { fileName }).EventOccured;
 
-                    File.Create(fileName).Dispose();
-                    Assert.True(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent2, autoResetEvent3 }, WaitForExpectedEventTimeout_NoRetry));
+                watcher1.EnableRaisingEvents = true;
+                watcher2.EnableRaisingEvents = true;
+                watcher3.EnableRaisingEvents = true;
 
-                    File.Delete(fileName);
-                    watcher1.EnableRaisingEvents = false;
+                File.Create(fileName).Dispose();
+                Assert.True(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent2, autoResetEvent3 }, WaitForExpectedEventTimeout_NoRetry));
 
-                    File.Create(fileName).Dispose();
-                    Assert.False(autoResetEvent1.WaitOne(WaitForUnexpectedEventTimeout));
-                    Assert.True(WaitHandle.WaitAll(new[] { autoResetEvent2, autoResetEvent3 }, WaitForExpectedEventTimeout_NoRetry));
-                }
-            });
+                File.Delete(fileName);
+                watcher1.EnableRaisingEvents = false;
+
+                File.Create(fileName).Dispose();
+                Assert.False(autoResetEvent1.WaitOne(WaitForUnexpectedEventTimeout));
+                Assert.True(WaitHandle.WaitAll(new[] { autoResetEvent2, autoResetEvent3 }, WaitForExpectedEventTimeout_NoRetry));
+            }
         }
 
         [OuterLoop]
         [Fact]
         public void FileSystemWatcher_File_Create_WatchOwnPath()
         {
-            ExecuteWithRetry(() =>
+            using (var dir = new TempDirectory(GetTestFilePath()))
+            using (var dir1 = new TempDirectory(Path.Combine(dir.Path, "dir1")))
+            using (var dir2 = new TempDirectory(Path.Combine(dir.Path, "dir2")))
+            using (var watcher1 = new FileSystemWatcher(dir1.Path, "*"))
+            using (var watcher2 = new FileSystemWatcher(dir2.Path, "*"))
             {
-                using (var dir = new TempDirectory(GetTestFilePath()))
-                using (var dir1 = new TempDirectory(Path.Combine(dir.Path, "dir1")))
-                using (var dir2 = new TempDirectory(Path.Combine(dir.Path, "dir2")))
-                using (var watcher1 = new FileSystemWatcher(dir1.Path, "*"))
-                using (var watcher2 = new FileSystemWatcher(dir2.Path, "*"))
-                {
-                    string fileName1 = Path.Combine(dir1.Path, "file");
-                    string fileName2 = Path.Combine(dir2.Path, "file");
+                watcher1.Error += OnError;
+                watcher2.Error += OnError;
 
-                    AutoResetEvent autoResetEvent1 = WatchCreated(watcher1, new[] { fileName1 }).EventOccured;
-                    AutoResetEvent autoResetEvent2 = WatchCreated(watcher2, new[] { fileName2 }).EventOccured;
+                string fileName1 = Path.Combine(dir1.Path, "file");
+                string fileName2 = Path.Combine(dir2.Path, "file");
 
-                    watcher1.EnableRaisingEvents = true;
-                    watcher2.EnableRaisingEvents = true;
+                AutoResetEvent autoResetEvent1 = WatchCreated(watcher1, new[] { fileName1 }).EventOccured;
+                AutoResetEvent autoResetEvent2 = WatchCreated(watcher2, new[] { fileName2 }).EventOccured;
 
-                    File.Create(fileName1).Dispose();
-                    Assert.True(autoResetEvent1.WaitOne(WaitForExpectedEventTimeout_NoRetry));
-                    Assert.False(autoResetEvent2.WaitOne(WaitForUnexpectedEventTimeout));
+                watcher1.EnableRaisingEvents = true;
+                watcher2.EnableRaisingEvents = true;
 
-                    File.Create(fileName2).Dispose();
-                    Assert.True(autoResetEvent2.WaitOne(WaitForExpectedEventTimeout_NoRetry));
-                    Assert.False(autoResetEvent1.WaitOne(WaitForUnexpectedEventTimeout));
-                }
-            });
+                File.Create(fileName1).Dispose();
+                Assert.True(autoResetEvent1.WaitOne(WaitForExpectedEventTimeout_NoRetry));
+                Assert.False(autoResetEvent2.WaitOne(WaitForUnexpectedEventTimeout));
+
+                File.Create(fileName2).Dispose();
+
+                Assert.True(autoResetEvent2.WaitOne(WaitForExpectedEventTimeout_NoRetry));
+                Assert.False(autoResetEvent1.WaitOne(WaitForUnexpectedEventTimeout));
+            }
         }
 
-        [ActiveIssue(34361, TestPlatforms.Linux)]
         [OuterLoop]
         [Theory]
         [InlineData(true)]
         [InlineData(false)]
         public void FileSystemWatcher_File_Create_ForceLoopRestart(bool useExistingWatchers)
         {
-            ExecuteWithRetry(() =>
+            FileSystemWatcher[] watchers = new FileSystemWatcher[64];
+            FileSystemWatcher[] watchers1 = new FileSystemWatcher[64];
+
+            try
             {
-                FileSystemWatcher[] watchers = new FileSystemWatcher[64];
-                FileSystemWatcher[] watchers1 = new FileSystemWatcher[64];
+                string fileName = Path.Combine(TestDirectory, "FileSystemWatcher_File_Create_ForceLoopRestart");
+                AutoResetEvent[] autoResetEvents = new AutoResetEvent[64];
+                for (var i = 0; i < watchers.Length; i++)
+                {
+                    watchers[i] = new FileSystemWatcher(TestDirectory);
+                    watchers[i].Filter = Path.GetFileName(fileName);
+                    autoResetEvents[i] = WatchCreated(watchers[i], new[] { fileName }).EventOccured;
+                    watchers[i].EnableRaisingEvents = true;
+                }
 
-                try
+                File.Create(fileName).Dispose();
+                Assert.True(WaitHandle.WaitAll(autoResetEvents, WaitForExpectedEventTimeout_NoRetry));
+
+                File.Delete(fileName);
+                for (var i = 0; i < watchers.Length; i++)
+                {
+                    watchers[i].EnableRaisingEvents = false;
+                }
+
+                File.Create(fileName).Dispose();
+                Assert.False(WaitHandle.WaitAll(autoResetEvents, WaitForUnexpectedEventTimeout));
+
+                File.Delete(fileName);
+
+                if (useExistingWatchers)
                 {
-                    string fileName = Path.Combine(TestDirectory, "file");
-                    AutoResetEvent[] autoResetEvents = new AutoResetEvent[64];
                     for (var i = 0; i < watchers.Length; i++)
                     {
-                        watchers[i] = new FileSystemWatcher(TestDirectory);
-                        watchers[i].Filter = Path.GetFileName(fileName);
-                        autoResetEvents[i] = WatchCreated(watchers[i], new[] { fileName }).EventOccured;
                         watchers[i].EnableRaisingEvents = true;
                     }
 
                     File.Create(fileName).Dispose();
                     Assert.True(WaitHandle.WaitAll(autoResetEvents, WaitForExpectedEventTimeout_NoRetry));
-
-                    File.Delete(fileName);
-                    for (var i = 0; i < watchers.Length; i++)
+                }
+                else
+                {
+                    AutoResetEvent[] autoResetEvents1 = new AutoResetEvent[64];
+                    for (var i = 0; i < watchers1.Length; i++)
                     {
-                        watchers[i].EnableRaisingEvents = false;
+                        watchers1[i] = new FileSystemWatcher(TestDirectory);
+                        watchers1[i].Filter = Path.GetFileName(fileName);
+                        autoResetEvents1[i] = WatchCreated(watchers1[i], new[] { fileName }).EventOccured;
+                        watchers1[i].EnableRaisingEvents = true;
                     }
 
                     File.Create(fileName).Dispose();
-                    Assert.False(WaitHandle.WaitAll(autoResetEvents, WaitForUnexpectedEventTimeout));
-
-                    File.Delete(fileName);
-
-                    if (useExistingWatchers)
-                    {
-                        for (var i = 0; i < watchers.Length; i++)
-                        {
-                            watchers[i].EnableRaisingEvents = true;
-                        }
-
-                        File.Create(fileName).Dispose();
-                        Assert.True(WaitHandle.WaitAll(autoResetEvents, WaitForExpectedEventTimeout_NoRetry));
-                    }
-                    else
-                    {
-                        AutoResetEvent[] autoResetEvents1 = new AutoResetEvent[64];
-                        for (var i = 0; i < watchers1.Length; i++)
-                        {
-                            watchers1[i] = new FileSystemWatcher(TestDirectory);
-                            watchers1[i].Filter = Path.GetFileName(fileName);
-                            autoResetEvents1[i] = WatchCreated(watchers1[i], new[] { fileName }).EventOccured;
-                            watchers1[i].EnableRaisingEvents = true;
-                        }
-
-                        File.Create(fileName).Dispose();
-                        Assert.True(WaitHandle.WaitAll(autoResetEvents1, WaitForExpectedEventTimeout_NoRetry));
-                    }
+                    Assert.True(WaitHandle.WaitAll(autoResetEvents1, WaitForExpectedEventTimeout_NoRetry));
                 }
-                finally
+            }
+            finally
+            {
+                for (var i = 0; i < watchers.Length; i++)
                 {
-                    for (var i = 0; i < watchers.Length; i++)
-                    {
-                        watchers[i]?.Dispose();
-                        watchers1[i]?.Dispose();
-                    }
+                    watchers[i]?.Dispose();
+                    watchers1[i]?.Dispose();
                 }
-            });
+            }
         }
 
         [OuterLoop]
         [Fact]
         public void  FileSystemWatcher_File_Changed_NotAffectEachOther()
         {
-            ExecuteWithRetry(() =>
+            using (var testDirectory = new TempDirectory(GetTestFilePath()))
+            using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
+            using (var otherFile = new TempFile(Path.Combine(testDirectory.Path, "otherfile")))
+            using (var watcher1 = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
+            using (var watcher2 = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
+            using (var watcher3 = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(otherFile.Path)))
             {
-                using (var testDirectory = new TempDirectory(GetTestFilePath()))
-                using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
-                using (var otherFile = new TempFile(Path.Combine(testDirectory.Path, "otherfile")))
-                using (var watcher1 = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
-                using (var watcher2 = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
-                using (var watcher3 = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(otherFile.Path)))
-                {
-                    AutoResetEvent autoResetEvent1 = WatchChanged(watcher1, new[] { Path.Combine(testDirectory.Path, "file") }).EventOccured;
-                    AutoResetEvent autoResetEvent2 = WatchChanged(watcher2, new[] { Path.Combine(testDirectory.Path, "file") }).EventOccured;
-                    AutoResetEvent autoResetEvent3 = WatchChanged(watcher3, new[] { Path.Combine(testDirectory.Path, "otherfile") }).EventOccured;
+                AutoResetEvent autoResetEvent1 = WatchChanged(watcher1, new[] { Path.Combine(testDirectory.Path, "file") }).EventOccured;
+                AutoResetEvent autoResetEvent2 = WatchChanged(watcher2, new[] { Path.Combine(testDirectory.Path, "file") }).EventOccured;
+                AutoResetEvent autoResetEvent3 = WatchChanged(watcher3, new[] { Path.Combine(testDirectory.Path, "otherfile") }).EventOccured;
 
-                    watcher1.EnableRaisingEvents = true;
-                    watcher2.EnableRaisingEvents = true;
-                    watcher3.EnableRaisingEvents = true;
+                watcher1.Error += OnError;
+                watcher2.Error += OnError;
+                watcher3.Error += OnError;
 
-                    Directory.SetLastWriteTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
-                    Assert.True(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent2 }, WaitForExpectedEventTimeout_NoRetry));
-                    Assert.False(autoResetEvent3.WaitOne(WaitForUnexpectedEventTimeout));
+                watcher1.EnableRaisingEvents = true;
+                watcher2.EnableRaisingEvents = true;
+                watcher3.EnableRaisingEvents = true;
 
-                    Directory.SetLastWriteTime(otherFile.Path, DateTime.Now + TimeSpan.FromSeconds(10));
-                    Assert.False(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent2 }, WaitForUnexpectedEventTimeout));
-                    Assert.True(autoResetEvent3.WaitOne(WaitForExpectedEventTimeout_NoRetry));
+                Directory.SetLastWriteTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
+                Assert.True(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent2 }, WaitForExpectedEventTimeout_NoRetry));
+                Assert.False(autoResetEvent3.WaitOne(WaitForUnexpectedEventTimeout));
 
-                    watcher1.EnableRaisingEvents = false;
+                Directory.SetLastWriteTime(otherFile.Path, DateTime.Now + TimeSpan.FromSeconds(10));
+                Assert.False(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent2 }, WaitForUnexpectedEventTimeout));
+                Assert.True(autoResetEvent3.WaitOne(WaitForExpectedEventTimeout_NoRetry));
 
-                    Directory.SetLastWriteTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
-                    Assert.False(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent3 }, WaitForUnexpectedEventTimeout));
-                    Assert.True(autoResetEvent2.WaitOne(WaitForExpectedEventTimeout_NoRetry));
+                watcher1.EnableRaisingEvents = false;
 
-                    Directory.SetLastWriteTime(otherFile.Path, DateTime.Now + TimeSpan.FromSeconds(10));
-                    Assert.False(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent2 }, WaitForUnexpectedEventTimeout));
-                    Assert.True(autoResetEvent3.WaitOne(WaitForExpectedEventTimeout_NoRetry));
-                }
-            });
+                Directory.SetLastWriteTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
+                Assert.False(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent3 }, WaitForUnexpectedEventTimeout));
+                Assert.True(autoResetEvent2.WaitOne(WaitForExpectedEventTimeout_NoRetry));
+
+                Directory.SetLastWriteTime(otherFile.Path, DateTime.Now + TimeSpan.FromSeconds(10));
+                Assert.False(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent2 }, WaitForUnexpectedEventTimeout));
+                Assert.True(autoResetEvent3.WaitOne(WaitForExpectedEventTimeout_NoRetry));
+            }
         }
 
         [OuterLoop]
         [Fact]
         public void FileSystemWatcher_File_Delet_NotAffectEachOther()
         {
-            ExecuteWithRetry(() =>
+            using (var watcher1 = new FileSystemWatcher(TestDirectory))
+            using (var watcher2 = new FileSystemWatcher(TestDirectory))
+            using (var watcher3 = new FileSystemWatcher(TestDirectory))
             {
-                using (var watcher1 = new FileSystemWatcher(TestDirectory))
-                using (var watcher2 = new FileSystemWatcher(TestDirectory))
-                using (var watcher3 = new FileSystemWatcher(TestDirectory))
-                {
-                    string fileName = Path.Combine(TestDirectory, "file");
-                    File.Create(fileName).Dispose();
+                string fileName = Path.Combine(TestDirectory, "file");
+                File.Create(fileName).Dispose();
 
-                    watcher1.Filter = Path.GetFileName(fileName);
-                    watcher2.Filter = Path.GetFileName(fileName);
-                    watcher3.Filter = Path.GetFileName(fileName);
+                watcher1.Filter = Path.GetFileName(fileName);
+                watcher2.Filter = Path.GetFileName(fileName);
+                watcher3.Filter = Path.GetFileName(fileName);
 
-                    AutoResetEvent autoResetEvent1 = WatchDeleted(watcher1, new[] { fileName }).EventOccured;
-                    AutoResetEvent autoResetEvent2 = WatchDeleted(watcher2, new[] { fileName }).EventOccured;
-                    AutoResetEvent autoResetEvent3 = WatchDeleted(watcher3, new[] { fileName }).EventOccured;
+                watcher1.Error += OnError;
+                watcher2.Error += OnError;
+                watcher3.Error += OnError;
 
-                    watcher1.EnableRaisingEvents = true;
-                    watcher2.EnableRaisingEvents = true;
-                    watcher3.EnableRaisingEvents = true;
+                AutoResetEvent autoResetEvent1 = WatchDeleted(watcher1, new[] { fileName }).EventOccured;
+                AutoResetEvent autoResetEvent2 = WatchDeleted(watcher2, new[] { fileName }).EventOccured;
+                AutoResetEvent autoResetEvent3 = WatchDeleted(watcher3, new[] { fileName }).EventOccured;
 
-                    File.Delete(fileName);
-                    Assert.True(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent2, autoResetEvent3 }, WaitForExpectedEventTimeout_NoRetry));
+                watcher1.EnableRaisingEvents = true;
+                watcher2.EnableRaisingEvents = true;
+                watcher3.EnableRaisingEvents = true;
 
-                    File.Create(fileName).Dispose();
-                    watcher1.EnableRaisingEvents = false;
+                File.Delete(fileName);
+                Assert.True(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent2, autoResetEvent3 }, WaitForExpectedEventTimeout_NoRetry));
 
-                    File.Delete(fileName);
-                    Assert.False(autoResetEvent1.WaitOne(WaitForUnexpectedEventTimeout));
-                    Assert.True(WaitHandle.WaitAll(new[] { autoResetEvent2, autoResetEvent3 }, WaitForExpectedEventTimeout_NoRetry));
-                }
-            });
+                File.Create(fileName).Dispose();
+                watcher1.EnableRaisingEvents = false;
+
+                File.Delete(fileName);
+                Assert.False(autoResetEvent1.WaitOne(WaitForUnexpectedEventTimeout));
+                Assert.True(WaitHandle.WaitAll(new[] { autoResetEvent2, autoResetEvent3 }, WaitForExpectedEventTimeout_NoRetry));
+            }
         }
 
         [OuterLoop]
@@ -309,41 +324,41 @@ namespace System.IO.Tests
         [PlatformSpecific(TestPlatforms.OSX)]
         public void FileSystemWatcher_File_Rename_NotAffectEachOther()
         {
-            ExecuteWithRetry(() =>
+            using (var testDirectory = new TempDirectory(GetTestFilePath()))
+            using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
+            using (var watcher1 = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
+            using (var watcher2 = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
             {
-                using (var testDirectory = new TempDirectory(GetTestFilePath()))
-                using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
-                using (var watcher1 = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
-                using (var watcher2 = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
-                {
-                    AutoResetEvent autoResetEvent1_created = WatchCreated(watcher1, new[] { Path.Combine(testDirectory.Path, "file") }).EventOccured;
-                    AutoResetEvent autoResetEvent1_deleted = WatchDeleted(watcher1, new[] { Path.Combine(testDirectory.Path, "file") }).EventOccured;
-                    AutoResetEvent autoResetEvent2_created = WatchCreated(watcher2, new[] { Path.Combine(testDirectory.Path, "file") }).EventOccured;
-                    AutoResetEvent autoResetEvent2_deleted = WatchDeleted(watcher2, new[] { Path.Combine(testDirectory.Path, "file") }).EventOccured;
-
-                    watcher1.EnableRaisingEvents = true;
-                    watcher2.EnableRaisingEvents = true;
-
-                    string filePath = file.Path;
-                    string filePathRenamed = file.Path + "_renamed";
-
-                    File.Move(filePath, filePathRenamed);
-                    Assert.True(WaitHandle.WaitAll(
-                        new[] { autoResetEvent1_created, autoResetEvent1_deleted, autoResetEvent2_created, autoResetEvent2_deleted },
-                        WaitForExpectedEventTimeout_NoRetry));
-
-                    File.Move(filePathRenamed, filePath);
-                    watcher1.EnableRaisingEvents = false;
-
-                    File.Move(filePath, filePathRenamed);
-                    Assert.False(WaitHandle.WaitAll(
-                        new[] { autoResetEvent1_created, autoResetEvent1_deleted },
-                        WaitForUnexpectedEventTimeout));
-                    Assert.True(WaitHandle.WaitAll(
-                        new[] { autoResetEvent2_created, autoResetEvent2_deleted },
-                        WaitForExpectedEventTimeout_NoRetry));
-                }
-            });
+                AutoResetEvent autoResetEvent1_created = WatchCreated(watcher1, new[] { Path.Combine(testDirectory.Path, "file") }).EventOccured;
+                AutoResetEvent autoResetEvent1_deleted = WatchDeleted(watcher1, new[] { Path.Combine(testDirectory.Path, "file") }).EventOccured;
+                AutoResetEvent autoResetEvent2_created = WatchCreated(watcher2, new[] { Path.Combine(testDirectory.Path, "file") }).EventOccured;
+                AutoResetEvent autoResetEvent2_deleted = WatchDeleted(watcher2, new[] { Path.Combine(testDirectory.Path, "file") }).EventOccured;
+
+                watcher1.Error += OnError;
+                watcher2.Error += OnError;
+
+                watcher1.EnableRaisingEvents = true;
+                watcher2.EnableRaisingEvents = true;
+
+                string filePath = file.Path;
+                string filePathRenamed = file.Path + "_renamed";
+
+                File.Move(filePath, filePathRenamed);
+                Assert.True(WaitHandle.WaitAll(
+                    new[] { autoResetEvent1_created, autoResetEvent1_deleted, autoResetEvent2_created, autoResetEvent2_deleted },
+                    WaitForExpectedEventTimeout_NoRetry));
+
+                File.Move(filePathRenamed, filePath);
+                watcher1.EnableRaisingEvents = false;
+
+                File.Move(filePath, filePathRenamed);
+                Assert.False(WaitHandle.WaitAll(
+                    new[] { autoResetEvent1_created, autoResetEvent1_deleted },
+                    WaitForUnexpectedEventTimeout));
+                Assert.True(WaitHandle.WaitAll(
+                    new[] { autoResetEvent2_created, autoResetEvent2_deleted },
+                    WaitForExpectedEventTimeout_NoRetry));
+            }
         }
     }
 }
index 0e9b25c..2dd0613 100644 (file)
@@ -7,7 +7,11 @@ using System.Linq;
 using System.Runtime.InteropServices;
 using System.Threading;
 using System.Threading.Tasks;
+
+using Microsoft.DotNet.XUnitExtensions;
+
 using Xunit;
+using Xunit.Abstractions;
 
 namespace System.IO.Tests
 {
@@ -550,41 +554,6 @@ namespace System.IO.Tests
         }
 
         [Fact]
-        [PlatformSpecific(TestPlatforms.Linux)]  // Reads MaxUsersWatches from Linux OS files
-        [OuterLoop("This test has high system resource demands and may cause failures in other concurrent tests")]
-        public void FileSystemWatcher_CreateManyConcurrentWatches()
-        {
-            int maxUserWatches = int.Parse(File.ReadAllText("/proc/sys/fs/inotify/max_user_watches"));
-
-            using (var dir = new TempDirectory(GetTestFilePath()))
-            using (var watcher = new FileSystemWatcher(dir.Path) { IncludeSubdirectories = true, NotifyFilter = NotifyFilters.FileName })
-            {
-                Action action = () =>
-                {
-                    // Create enough directories to exceed the number of allowed watches
-                    for (int i = 0; i <= maxUserWatches; i++)
-                    {
-                        Directory.CreateDirectory(Path.Combine(dir.Path, i.ToString()));
-                    }
-                };
-                Action cleanup = () =>
-                {
-                    for (int i = 0; i <= maxUserWatches; i++)
-                    {
-                        Directory.Delete(Path.Combine(dir.Path, i.ToString()));
-                    }
-                };
-
-                ExpectError(watcher, action, cleanup);
-
-                // Make sure existing watches still work even after we've had one or more failures
-                Action createAction = () => File.WriteAllText(Path.Combine(dir.Path, Path.GetRandomFileName()), "text");
-                Action createCleanup = () => File.Delete(Path.Combine(dir.Path, Path.GetRandomFileName()));
-                ExpectEvent(watcher, WatcherChangeTypes.Created, createAction, createCleanup);
-            }
-        }
-
-        [Fact]
         public void FileSystemWatcher_StopCalledOnBackgroundThreadDoesNotDeadlock()
         {
             // Check the case where Stop or Dispose (they do the same thing) is called from
@@ -1117,4 +1086,43 @@ namespace System.IO.Tests
             }
         }
     }
+
+    [Collection("NoParallelTests")]
+    public class DangerousFileSystemWatcherTests : FileSystemWatcherTest
+    {
+        [PlatformSpecific(TestPlatforms.Linux)]  // Reads MaxUsersWatches from Linux OS files
+        [OuterLoop("This test will use all available watchers and can cause failures in other concurrent tests or system processes.")]
+        [Fact]
+        public void FileSystemWatcher_CreateManyConcurrentWatches()
+        {
+            int maxUserWatches = int.Parse(File.ReadAllText("/proc/sys/fs/inotify/max_user_watches"));
+
+            using (var dir = new TempDirectory(GetTestFilePath()))
+            using (var watcher = new FileSystemWatcher(dir.Path) { IncludeSubdirectories = true, NotifyFilter = NotifyFilters.FileName })
+            {
+                Action action = () =>
+                {
+                    // Create enough directories to exceed the number of allowed watches
+                    for (int i = 0; i <= maxUserWatches; i++)
+                    {
+                        Directory.CreateDirectory(Path.Combine(dir.Path, i.ToString()));
+                    }
+                };
+                Action cleanup = () =>
+                {
+                    for (int i = 0; i <= maxUserWatches; i++)
+                    {
+                        Directory.Delete(Path.Combine(dir.Path, i.ToString()));
+                    }
+                };
+
+                ExpectError(watcher, action, cleanup);
+
+                // Make sure existing watches still work even after we've had one or more failures
+                Action createAction = () => File.WriteAllText(Path.Combine(dir.Path, Path.GetRandomFileName()), "text");
+                Action createCleanup = () => File.Delete(Path.Combine(dir.Path, Path.GetRandomFileName()));
+                ExpectEvent(watcher, WatcherChangeTypes.Created, createAction, createCleanup);
+            }
+        }
+    }
 }
index eaa6f19..4f100b8 100644 (file)
@@ -11,6 +11,9 @@ using Xunit.Sdk;
 
 namespace System.IO.Tests
 {
+    [CollectionDefinition("NoParallelTests", DisableParallelization = true)]
+    public partial class NoParallelTests { }
+
     public abstract partial class FileSystemWatcherTest : FileCleanupTestBase
     {
         // Events are reported asynchronously by the OS, so allow an amount of time for