Merge branch 'release/2.1' into dev
This commit is contained in:
commit
07517187b6
|
|
@ -286,98 +286,63 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
||||||
{
|
{
|
||||||
var filesChanged = new HashSet<string>();
|
var filesChanged = new HashSet<string>();
|
||||||
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
_output.WriteLine("Clear files changed list");
|
|
||||||
filesChanged.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
UsingTempDirectory(dir =>
|
UsingTempDirectory(dir =>
|
||||||
{
|
{
|
||||||
using (var changedEv = new AutoResetEvent(false))
|
|
||||||
using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling))
|
using (var watcher = FileWatcherFactory.CreateWatcher(dir, usePolling))
|
||||||
{
|
{
|
||||||
|
|
||||||
EventHandler<string> handler = null;
|
|
||||||
handler = (_, f) =>
|
|
||||||
{
|
|
||||||
_output.WriteLine("File changed: " + f);
|
|
||||||
filesChanged.Add(f);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
changedEv.Set();
|
|
||||||
}
|
|
||||||
catch (ObjectDisposedException)
|
|
||||||
{
|
|
||||||
// There's a known race condition here:
|
|
||||||
// even though we tell the watcher to stop raising events and we unsubscribe the handler
|
|
||||||
// there might be in-flight events that will still process. Since we dispose the reset
|
|
||||||
// event, this code will fail if the handler executes after Dispose happens. There's no
|
|
||||||
// better way to guard against it than catch because we cannot check if the object is
|
|
||||||
// disposed nor can we check if there are any in-flight events.
|
|
||||||
// This is actually a known issue in the corefx file watcher. It can trigger multiple
|
|
||||||
// times for the same item.
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
watcher.OnFileChange += handler;
|
|
||||||
watcher.EnableRaisingEvents = true;
|
watcher.EnableRaisingEvents = true;
|
||||||
|
|
||||||
// On Unix the file write time is in 1s increments;
|
for (var i = 0; i < 5; i++)
|
||||||
// if we don't wait, there's a chance that the polling
|
{
|
||||||
// watcher will not detect the change
|
AssertFileChangeRaisesEvent(dir, watcher);
|
||||||
Thread.Sleep(1000);
|
}
|
||||||
|
|
||||||
var testFileFullPath = Path.Combine(dir, "foo1");
|
|
||||||
File.WriteAllText(testFileFullPath, string.Empty);
|
|
||||||
Assert.True(changedEv.WaitOne(DefaultTimeout));
|
|
||||||
var fileChanged = Assert.Single(filesChanged);
|
|
||||||
Assert.Equal(testFileFullPath, fileChanged);
|
|
||||||
Clear();
|
|
||||||
changedEv.Reset();
|
|
||||||
|
|
||||||
// On Unix the file write time is in 1s increments;
|
|
||||||
// if we don't wait, there's a chance that the polling
|
|
||||||
// watcher will not detect the change
|
|
||||||
Thread.Sleep(1000);
|
|
||||||
|
|
||||||
testFileFullPath = Path.Combine(dir, "foo2");
|
|
||||||
File.WriteAllText(testFileFullPath, string.Empty);
|
|
||||||
Assert.True(changedEv.WaitOne(DefaultTimeout));
|
|
||||||
fileChanged = Assert.Single(filesChanged);
|
|
||||||
Assert.Equal(testFileFullPath, fileChanged);
|
|
||||||
Clear();
|
|
||||||
changedEv.Reset();
|
|
||||||
|
|
||||||
// On Unix the file write time is in 1s increments;
|
|
||||||
// if we don't wait, there's a chance that the polling
|
|
||||||
// watcher will not detect the change
|
|
||||||
Thread.Sleep(1000);
|
|
||||||
|
|
||||||
testFileFullPath = Path.Combine(dir, "foo3");
|
|
||||||
File.WriteAllText(testFileFullPath, string.Empty);
|
|
||||||
Assert.True(changedEv.WaitOne(DefaultTimeout));
|
|
||||||
fileChanged = Assert.Single(filesChanged);
|
|
||||||
Assert.Equal(testFileFullPath, fileChanged);
|
|
||||||
Clear();
|
|
||||||
changedEv.Reset();
|
|
||||||
|
|
||||||
// On Unix the file write time is in 1s increments;
|
|
||||||
// if we don't wait, there's a chance that the polling
|
|
||||||
// watcher will not detect the change
|
|
||||||
Thread.Sleep(1000);
|
|
||||||
|
|
||||||
File.WriteAllText(testFileFullPath, string.Empty);
|
|
||||||
Assert.True(changedEv.WaitOne(DefaultTimeout));
|
|
||||||
fileChanged = Assert.Single(filesChanged);
|
|
||||||
Assert.Equal(testFileFullPath, fileChanged);
|
|
||||||
|
|
||||||
watcher.EnableRaisingEvents = false;
|
watcher.EnableRaisingEvents = false;
|
||||||
watcher.OnFileChange -= handler;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AssertFileChangeRaisesEvent(string directory, IFileSystemWatcher watcher)
|
||||||
|
{
|
||||||
|
var semaphoreSlim = new SemaphoreSlim(0);
|
||||||
|
var expectedPath = Path.Combine(directory, Path.GetRandomFileName());
|
||||||
|
EventHandler<string> handler = (object _, string f) =>
|
||||||
|
{
|
||||||
|
_output.WriteLine("File changed: " + f);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.Equals(f, expectedPath, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
semaphoreSlim.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
// There's a known race condition here:
|
||||||
|
// even though we tell the watcher to stop raising events and we unsubscribe the handler
|
||||||
|
// there might be in-flight events that will still process. Since we dispose the reset
|
||||||
|
// event, this code will fail if the handler executes after Dispose happens.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
File.AppendAllText(expectedPath, " ");
|
||||||
|
|
||||||
|
watcher.OnFileChange += handler;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// On Unix the file write time is in 1s increments;
|
||||||
|
// if we don't wait, there's a chance that the polling
|
||||||
|
// watcher will not detect the change
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
File.AppendAllText(expectedPath, " ");
|
||||||
|
Assert.True(semaphoreSlim.Wait(DefaultTimeout), "Expected a file change event for " + expectedPath);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
watcher.OnFileChange -= handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(true)]
|
[InlineData(true)]
|
||||||
[InlineData(false)]
|
[InlineData(false)]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue