You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.239
Former-commit-id: 7b85789fc05cc44b56bcb66c7f08d3bab02d7ee9
This commit is contained in:
parent
fbc511bfbe
commit
3b70b8a7f6
@@ -26,6 +26,45 @@ namespace System.IO.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[OuterLoop]
|
||||
public void FileSystemWatcher_File_Create_EnablingDisablingNotAffectRaisingEvent()
|
||||
{
|
||||
ExecuteWithRetry(() =>
|
||||
{
|
||||
using (var testDirectory = new TempDirectory(GetTestFilePath()))
|
||||
using (var watcher = new FileSystemWatcher(testDirectory.Path))
|
||||
{
|
||||
string fileName = Path.Combine(testDirectory.Path, "file");
|
||||
watcher.Filter = Path.GetFileName(fileName);
|
||||
|
||||
int numberOfRaisedEvents = 0;
|
||||
AutoResetEvent autoResetEvent = new AutoResetEvent(false);
|
||||
FileSystemEventHandler handler = (o, e) =>
|
||||
{
|
||||
Interlocked.Increment(ref numberOfRaisedEvents);
|
||||
autoResetEvent.Set();
|
||||
};
|
||||
|
||||
watcher.Created += handler;
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
watcher.EnableRaisingEvents = true;
|
||||
watcher.EnableRaisingEvents = false;
|
||||
}
|
||||
|
||||
watcher.EnableRaisingEvents = true;
|
||||
|
||||
// this should raise one and only one event
|
||||
File.Create(fileName).Dispose();
|
||||
Assert.True(autoResetEvent.WaitOne(WaitForExpectedEventTimeout_NoRetry));
|
||||
Assert.False(autoResetEvent.WaitOne(SubsequentExpectedWait));
|
||||
Assert.True(numberOfRaisedEvents == 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileSystemWatcher_File_Create_ForcedRestart()
|
||||
{
|
||||
|
||||
351
external/corefx/src/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.MultipleWatchers.cs
vendored
Normal file
351
external/corefx/src/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.MultipleWatchers.cs
vendored
Normal file
@@ -0,0 +1,351 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace System.IO.Tests
|
||||
{
|
||||
public class FileSystemWatcher_Multiple_Test : FileSystemWatcherTest
|
||||
{
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "#34017")]
|
||||
[OuterLoop]
|
||||
[Fact]
|
||||
public void FileSystemWatcher_File_Create_ExecutionContextFlowed()
|
||||
{
|
||||
ExecuteWithRetry(() =>
|
||||
{
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
local.Value = 42;
|
||||
watcher1.EnableRaisingEvents = true;
|
||||
local.Value = 84;
|
||||
watcher2.EnableRaisingEvents = true;
|
||||
local.Value = 168;
|
||||
|
||||
File.Create(fileName).Dispose();
|
||||
Task.WaitAll(new[] { tcs1.Task, tcs2.Task }, WaitForExpectedEventTimeout);
|
||||
|
||||
Assert.Equal(42, tcs1.Task.Result);
|
||||
Assert.Equal(84, tcs2.Task.Result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "#34017")]
|
||||
[OuterLoop]
|
||||
[Fact]
|
||||
public void FileSystemWatcher_File_Create_SuppressedExecutionContextHandled()
|
||||
{
|
||||
ExecuteWithRetry(() =>
|
||||
{
|
||||
using (var watcher1 = new FileSystemWatcher(TestDirectory))
|
||||
{
|
||||
string fileName = Path.Combine(TestDirectory, "file");
|
||||
watcher1.Filter = Path.GetFileName(fileName);
|
||||
|
||||
var local = new AsyncLocal<int>();
|
||||
|
||||
var tcs1 = new TaskCompletionSource<int>();
|
||||
watcher1.Created += (s, e) => tcs1.SetResult(local.Value);
|
||||
|
||||
local.Value = 42;
|
||||
|
||||
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))
|
||||
{
|
||||
string fileName = Path.Combine(TestDirectory, "file");
|
||||
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.EnableRaisingEvents = true;
|
||||
watcher2.EnableRaisingEvents = true;
|
||||
watcher3.EnableRaisingEvents = true;
|
||||
|
||||
File.Create(fileName).Dispose();
|
||||
Assert.True(WaitHandle.WaitAll(new[] { autoResetEvent1, 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, "*"))
|
||||
{
|
||||
string fileName1 = Path.Combine(dir1.Path, "file");
|
||||
string fileName2 = Path.Combine(dir2.Path, "file");
|
||||
|
||||
AutoResetEvent autoResetEvent1 = WatchCreated(watcher1, new[] { fileName1 }).EventOccured;
|
||||
AutoResetEvent autoResetEvent2 = WatchCreated(watcher2, new[] { fileName2 }).EventOccured;
|
||||
|
||||
watcher1.EnableRaisingEvents = true;
|
||||
watcher2.EnableRaisingEvents = true;
|
||||
|
||||
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));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[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
|
||||
{
|
||||
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++)
|
||||
{
|
||||
watchers[i].EnableRaisingEvents = false;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
for (var i = 0; i < watchers.Length; i++)
|
||||
{
|
||||
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)))
|
||||
{
|
||||
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;
|
||||
|
||||
Directory.SetLastWriteTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
|
||||
Assert.True(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent2 }, WaitForExpectedEventTimeout_NoRetry));
|
||||
Assert.False(autoResetEvent3.WaitOne(WaitForUnexpectedEventTimeout));
|
||||
|
||||
Directory.SetLastWriteTime(otherFile.Path, DateTime.Now + TimeSpan.FromSeconds(10));
|
||||
Assert.False(WaitHandle.WaitAll(new[] { autoResetEvent1, autoResetEvent2 }, WaitForUnexpectedEventTimeout));
|
||||
Assert.True(autoResetEvent3.WaitOne(WaitForExpectedEventTimeout_NoRetry));
|
||||
|
||||
watcher1.EnableRaisingEvents = false;
|
||||
|
||||
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))
|
||||
{
|
||||
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);
|
||||
|
||||
AutoResetEvent autoResetEvent1 = WatchDeleted(watcher1, new[] { fileName }).EventOccured;
|
||||
AutoResetEvent autoResetEvent2 = WatchDeleted(watcher2, new[] { fileName }).EventOccured;
|
||||
AutoResetEvent autoResetEvent3 = WatchDeleted(watcher3, new[] { fileName }).EventOccured;
|
||||
|
||||
watcher1.EnableRaisingEvents = true;
|
||||
watcher2.EnableRaisingEvents = true;
|
||||
watcher3.EnableRaisingEvents = true;
|
||||
|
||||
File.Delete(fileName);
|
||||
Assert.True(WaitHandle.WaitAll(new[] { autoResetEvent1, 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]
|
||||
[Fact]
|
||||
[PlatformSpecific(TestPlatforms.OSX)]
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.Mono)]
|
||||
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)))
|
||||
{
|
||||
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));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -474,7 +474,7 @@ namespace System.IO.Tests
|
||||
using (var file = new TempFile(Path.Combine(dir.Path, "file")))
|
||||
using (var fsw = new FileSystemWatcher(dir.Path))
|
||||
{
|
||||
AutoResetEvent eventOccurred = WatchRenamed(fsw);
|
||||
AutoResetEvent eventOccurred = WatchRenamed(fsw).EventOccured;
|
||||
|
||||
string newPath = Path.Combine(dir.Path, "newPath");
|
||||
|
||||
@@ -626,7 +626,7 @@ namespace System.IO.Tests
|
||||
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
|
||||
using (var fsw = new FileSystemWatcher(dir.Path))
|
||||
{
|
||||
AutoResetEvent are = WatchCreated(fsw);
|
||||
AutoResetEvent are = WatchCreated(fsw).EventOccured;
|
||||
|
||||
fsw.Filter = "*";
|
||||
fsw.EnableRaisingEvents = true;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
<Compile Include="FileSystemWatcher.File.Move.cs" />
|
||||
<Compile Include="FileSystemWatcher.File.NotifyFilter.cs" />
|
||||
<Compile Include="FileSystemWatcher.InternalBufferSize.cs" />
|
||||
<Compile Include="FileSystemWatcher.MultipleWatchers.cs" />
|
||||
<Compile Include="FileSystemWatcher.WaitForChanged.cs" />
|
||||
<Compile Include="FileSystemWatcher.unit.cs" />
|
||||
<!-- Helpers -->
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using Xunit;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace System.IO.Tests
|
||||
{
|
||||
public abstract class FileSystemWatcherTest : FileCleanupTestBase
|
||||
public abstract partial class FileSystemWatcherTest : FileCleanupTestBase
|
||||
{
|
||||
// Events are reported asynchronously by the OS, so allow an amount of time for
|
||||
// them to arrive before testing an assertion. If we expect an event to occur,
|
||||
@@ -23,18 +23,20 @@ namespace System.IO.Tests
|
||||
public const int LongWaitTimeout = 50000; // ms to wait for an event that takes a longer time than the average operation
|
||||
public const int SubsequentExpectedWait = 10; // ms to wait for checks that occur after the first.
|
||||
public const int WaitForExpectedEventTimeout_NoRetry = 3000;// ms to wait for an event that isn't surrounded by a retry.
|
||||
public const int WaitForUnexpectedEventTimeout = 150; // ms to wait for a non-expected event.
|
||||
public const int DefaultAttemptsForExpectedEvent = 3; // Number of times an expected event should be retried if failing.
|
||||
public const int DefaultAttemptsForUnExpectedEvent = 2; // Number of times an unexpected event should be retried if failing.
|
||||
public const int RetryDelayMilliseconds = 500; // ms to wait when retrying after failure
|
||||
|
||||
/// <summary>
|
||||
/// Watches the Changed WatcherChangeType and unblocks the returned AutoResetEvent when a
|
||||
/// Changed event is thrown by the watcher.
|
||||
/// </summary>
|
||||
public static AutoResetEvent WatchChanged(FileSystemWatcher watcher, string[] expectedPaths = null)
|
||||
public static (AutoResetEvent EventOccured, FileSystemEventHandler Handler) WatchChanged(FileSystemWatcher watcher, string[] expectedPaths = null)
|
||||
{
|
||||
AutoResetEvent eventOccurred = new AutoResetEvent(false);
|
||||
|
||||
watcher.Changed += (o, e) =>
|
||||
FileSystemEventHandler changeHandler = (o, e) =>
|
||||
{
|
||||
Assert.Equal(WatcherChangeTypes.Changed, e.ChangeType);
|
||||
if (expectedPaths != null)
|
||||
@@ -44,18 +46,19 @@ namespace System.IO.Tests
|
||||
eventOccurred.Set();
|
||||
};
|
||||
|
||||
return eventOccurred;
|
||||
watcher.Changed += changeHandler;
|
||||
return (eventOccurred, changeHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Watches the Created WatcherChangeType and unblocks the returned AutoResetEvent when a
|
||||
/// Created event is thrown by the watcher.
|
||||
/// </summary>
|
||||
public static AutoResetEvent WatchCreated(FileSystemWatcher watcher, string[] expectedPaths = null)
|
||||
public static (AutoResetEvent EventOccured, FileSystemEventHandler Handler) WatchCreated(FileSystemWatcher watcher, string[] expectedPaths = null)
|
||||
{
|
||||
AutoResetEvent eventOccurred = new AutoResetEvent(false);
|
||||
|
||||
watcher.Created += (o, e) =>
|
||||
FileSystemEventHandler handler = (o, e) =>
|
||||
{
|
||||
Assert.Equal(WatcherChangeTypes.Created, e.ChangeType);
|
||||
if (expectedPaths != null)
|
||||
@@ -65,18 +68,18 @@ namespace System.IO.Tests
|
||||
eventOccurred.Set();
|
||||
};
|
||||
|
||||
return eventOccurred;
|
||||
watcher.Created += handler;
|
||||
return (eventOccurred, handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Watches the Renamed WatcherChangeType and unblocks the returned AutoResetEvent when a
|
||||
/// Renamed event is thrown by the watcher.
|
||||
/// </summary>
|
||||
public static AutoResetEvent WatchDeleted(FileSystemWatcher watcher, string[] expectedPaths = null)
|
||||
public static (AutoResetEvent EventOccured, FileSystemEventHandler Handler) WatchDeleted(FileSystemWatcher watcher, string[] expectedPaths = null)
|
||||
{
|
||||
AutoResetEvent eventOccurred = new AutoResetEvent(false);
|
||||
|
||||
watcher.Deleted += (o, e) =>
|
||||
FileSystemEventHandler handler = (o, e) =>
|
||||
{
|
||||
Assert.Equal(WatcherChangeTypes.Deleted, e.ChangeType);
|
||||
if (expectedPaths != null)
|
||||
@@ -86,18 +89,19 @@ namespace System.IO.Tests
|
||||
eventOccurred.Set();
|
||||
};
|
||||
|
||||
return eventOccurred;
|
||||
watcher.Deleted += handler;
|
||||
return (eventOccurred, handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Watches the Renamed WatcherChangeType and unblocks the returned AutoResetEvent when a
|
||||
/// Renamed event is thrown by the watcher.
|
||||
/// </summary>
|
||||
public static AutoResetEvent WatchRenamed(FileSystemWatcher watcher, string[] expectedPaths = null)
|
||||
public static (AutoResetEvent EventOccured, RenamedEventHandler Handler) WatchRenamed(FileSystemWatcher watcher, string[] expectedPaths = null)
|
||||
{
|
||||
AutoResetEvent eventOccurred = new AutoResetEvent(false);
|
||||
|
||||
watcher.Renamed += (o, e) =>
|
||||
RenamedEventHandler handler = (o, e) =>
|
||||
{
|
||||
Assert.Equal(WatcherChangeTypes.Renamed, e.ChangeType);
|
||||
if (expectedPaths != null)
|
||||
@@ -107,7 +111,8 @@ namespace System.IO.Tests
|
||||
eventOccurred.Set();
|
||||
};
|
||||
|
||||
return eventOccurred;
|
||||
watcher.Renamed += handler;
|
||||
return (eventOccurred, handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -115,7 +120,7 @@ namespace System.IO.Tests
|
||||
/// </summary>
|
||||
public static void ExpectEvent(WaitHandle eventOccurred, string eventName_NoRetry)
|
||||
{
|
||||
string message = String.Format("Didn't observe a {0} event within {1}ms", eventName_NoRetry, WaitForExpectedEventTimeout_NoRetry);
|
||||
string message = string.Format("Didn't observe a {0} event within {1}ms", eventName_NoRetry, WaitForExpectedEventTimeout_NoRetry);
|
||||
Assert.True(eventOccurred.WaitOne(WaitForExpectedEventTimeout_NoRetry), message);
|
||||
}
|
||||
|
||||
@@ -161,32 +166,63 @@ namespace System.IO.Tests
|
||||
{
|
||||
int attemptsCompleted = 0;
|
||||
bool result = false;
|
||||
FileSystemWatcher newWatcher = watcher;
|
||||
while (!result && attemptsCompleted++ < attempts)
|
||||
{
|
||||
if (attemptsCompleted > 1)
|
||||
{
|
||||
// Re-create the watcher to get a clean iteration.
|
||||
watcher = new FileSystemWatcher()
|
||||
{
|
||||
IncludeSubdirectories = watcher.IncludeSubdirectories,
|
||||
NotifyFilter = watcher.NotifyFilter,
|
||||
Filter = watcher.Filter,
|
||||
Path = watcher.Path,
|
||||
InternalBufferSize = watcher.InternalBufferSize
|
||||
};
|
||||
newWatcher = RecreateWatcher(newWatcher);
|
||||
// Most intermittent failures in FSW are caused by either a shortage of resources (e.g. inotify instances)
|
||||
// or by insufficient time to execute (e.g. CI gets bogged down). Immediately re-running a failed test
|
||||
// won't resolve the first issue, so we wait a little while hoping that things clear up for the next run.
|
||||
Thread.Sleep(500);
|
||||
Thread.Sleep(RetryDelayMilliseconds);
|
||||
}
|
||||
|
||||
result = ExecuteAndVerifyEvents(watcher, expectedEvents, action, attemptsCompleted == attempts, expectedPaths, timeout);
|
||||
result = ExecuteAndVerifyEvents(newWatcher, expectedEvents, action, attemptsCompleted == attempts, expectedPaths, timeout);
|
||||
|
||||
if (cleanup != null)
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Invokes the specified test action with retry on failure (other than assertion failure).</summary>
|
||||
/// <param name="action">The test action.</param>
|
||||
/// <param name="maxAttempts">The maximum number of times to attempt to run the test.</param>
|
||||
public static void ExecuteWithRetry(Action action, int maxAttempts = DefaultAttemptsForExpectedEvent)
|
||||
{
|
||||
for (int retry = 0; retry < maxAttempts; retry++)
|
||||
{
|
||||
try
|
||||
{
|
||||
action();
|
||||
return;
|
||||
}
|
||||
catch (Exception e) when (!(e is XunitException) && retry < maxAttempts - 1)
|
||||
{
|
||||
Thread.Sleep(RetryDelayMilliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does verification that the given watcher will not throw exactly/only the events in "expectedEvents" when
|
||||
/// "action" is executed.
|
||||
/// </summary>
|
||||
/// <param name="watcher">The FileSystemWatcher to test</param>
|
||||
/// <param name="unExpectedEvents">All of the events that are expected to be raised by this action</param>
|
||||
/// <param name="action">The Action that will trigger events.</param>
|
||||
/// <param name="cleanup">Optional. Undoes the action and cleans up the watcher so the test may be run again if necessary.</param>
|
||||
/// <param name="expectedPath">Optional. Adds path verification to all expected events.</param>
|
||||
public static void ExpectNoEvent(FileSystemWatcher watcher, WatcherChangeTypes unExpectedEvents, Action action, Action cleanup = null, string expectedPath = null, int timeout = WaitForExpectedEventTimeout)
|
||||
{
|
||||
bool result = ExecuteAndVerifyEvents(watcher, unExpectedEvents, action, false, new string[] { expectedPath }, timeout);
|
||||
Assert.False(result, "Expected Event occured");
|
||||
|
||||
if (cleanup != null)
|
||||
cleanup();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper for the ExpectEvent function.
|
||||
/// </summary>
|
||||
@@ -199,8 +235,8 @@ namespace System.IO.Tests
|
||||
public static bool ExecuteAndVerifyEvents(FileSystemWatcher watcher, WatcherChangeTypes expectedEvents, Action action, bool assertExpected, string[] expectedPaths, int timeout)
|
||||
{
|
||||
bool result = true, verifyChanged = true, verifyCreated = true, verifyDeleted = true, verifyRenamed = true;
|
||||
AutoResetEvent changed = null, created = null, deleted = null, renamed = null;
|
||||
string[] expectedFullPaths = expectedPaths == null ? null : expectedPaths.Select(e => Path.GetFullPath(e)).ToArray();
|
||||
(AutoResetEvent EventOccured, FileSystemEventHandler Handler) changed = default, created = default, deleted = default;
|
||||
(AutoResetEvent EventOccured, RenamedEventHandler Handler) renamed = default;
|
||||
|
||||
if (verifyChanged = ((expectedEvents & WatcherChangeTypes.Changed) > 0))
|
||||
changed = WatchChanged(watcher, expectedPaths);
|
||||
@@ -218,7 +254,8 @@ namespace System.IO.Tests
|
||||
if (verifyChanged)
|
||||
{
|
||||
bool Changed_expected = ((expectedEvents & WatcherChangeTypes.Changed) > 0);
|
||||
bool Changed_actual = changed.WaitOne(timeout);
|
||||
bool Changed_actual = changed.EventOccured.WaitOne(timeout);
|
||||
watcher.Changed -= changed.Handler;
|
||||
result = Changed_expected == Changed_actual;
|
||||
if (assertExpected)
|
||||
Assert.True(Changed_expected == Changed_actual, "Changed event did not occur as expected");
|
||||
@@ -228,7 +265,8 @@ namespace System.IO.Tests
|
||||
if (verifyCreated)
|
||||
{
|
||||
bool Created_expected = ((expectedEvents & WatcherChangeTypes.Created) > 0);
|
||||
bool Created_actual = created.WaitOne(verifyChanged ? SubsequentExpectedWait : timeout);
|
||||
bool Created_actual = created.EventOccured.WaitOne(verifyChanged ? SubsequentExpectedWait : timeout);
|
||||
watcher.Created -= created.Handler;
|
||||
result = result && Created_expected == Created_actual;
|
||||
if (assertExpected)
|
||||
Assert.True(Created_expected == Created_actual, "Created event did not occur as expected");
|
||||
@@ -238,7 +276,8 @@ namespace System.IO.Tests
|
||||
if (verifyDeleted)
|
||||
{
|
||||
bool Deleted_expected = ((expectedEvents & WatcherChangeTypes.Deleted) > 0);
|
||||
bool Deleted_actual = deleted.WaitOne(verifyChanged || verifyCreated ? SubsequentExpectedWait : timeout);
|
||||
bool Deleted_actual = deleted.EventOccured.WaitOne(verifyChanged || verifyCreated ? SubsequentExpectedWait : timeout);
|
||||
watcher.Deleted -= deleted.Handler;
|
||||
result = result && Deleted_expected == Deleted_actual;
|
||||
if (assertExpected)
|
||||
Assert.True(Deleted_expected == Deleted_actual, "Deleted event did not occur as expected");
|
||||
@@ -248,7 +287,8 @@ namespace System.IO.Tests
|
||||
if (verifyRenamed)
|
||||
{
|
||||
bool Renamed_expected = ((expectedEvents & WatcherChangeTypes.Renamed) > 0);
|
||||
bool Renamed_actual = renamed.WaitOne(verifyChanged || verifyCreated || verifyDeleted? SubsequentExpectedWait : timeout);
|
||||
bool Renamed_actual = renamed.EventOccured.WaitOne(verifyChanged || verifyCreated || verifyDeleted ? SubsequentExpectedWait : timeout);
|
||||
watcher.Renamed -= renamed.Handler;
|
||||
result = result && Renamed_expected == Renamed_actual;
|
||||
if (assertExpected)
|
||||
Assert.True(Renamed_expected == Renamed_actual, "Renamed event did not occur as expected");
|
||||
@@ -409,7 +449,7 @@ namespace System.IO.Tests
|
||||
foreach (NotifyFilters filter in Enum.GetValues(typeof(NotifyFilters)))
|
||||
yield return new object[] { filter };
|
||||
}
|
||||
|
||||
|
||||
// Linux and OSX systems have less precise filtering systems than Windows, so most
|
||||
// metadata filters are effectively equivalent to each other on those systems. For example
|
||||
// there isn't a way to filter only LastWrite events on either system; setting
|
||||
@@ -430,5 +470,19 @@ namespace System.IO.Tests
|
||||
NotifyFilters.LastAccess |
|
||||
NotifyFilters.LastWrite |
|
||||
NotifyFilters.Size;
|
||||
|
||||
#if MONO
|
||||
private static FileSystemWatcher RecreateWatcher(FileSystemWatcher watcher)
|
||||
{
|
||||
FileSystemWatcher newWatcher = new FileSystemWatcher()
|
||||
{
|
||||
IncludeSubdirectories = watcher.IncludeSubdirectories,
|
||||
NotifyFilter = watcher.NotifyFilter,
|
||||
Path = watcher.Path,
|
||||
InternalBufferSize = watcher.InternalBufferSize
|
||||
};
|
||||
return newWatcher;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user