Imported Upstream version 5.18.0.239

Former-commit-id: 7b85789fc05cc44b56bcb66c7f08d3bab02d7ee9
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-01-15 08:32:41 +00:00
parent fbc511bfbe
commit 3b70b8a7f6
62 changed files with 953 additions and 295 deletions

View File

@@ -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()
{

View 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));
}
});
}
}
}

View File

@@ -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;

View File

@@ -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 -->

View File

@@ -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
}
}
}