From 7e87de255ba67eed5953f9899887a73420dff5d9 Mon Sep 17 00:00:00 2001 From: Ian Hays Date: Mon, 14 Nov 2016 14:15:02 -0800 Subject: [PATCH] Add missing FileSystemWatcher methods Adds source and tests for the remaining missing members in FileSystemWatcher. This required that FileSystemWatcher take a dependency on System.ComponentModel.TypeConverter. --- .../ref/System.IO.FileSystem.Watcher.cs | 7 +- .../ref/project.json | 3 +- .../src/System/IO/FileSystemWatcher.Linux.cs | 10 + .../src/System/IO/FileSystemWatcher.OSX.cs | 10 + .../src/System/IO/FileSystemWatcher.Win32.cs | 10 + .../src/System/IO/FileSystemWatcher.cs | 127 ++++++++- .../src/project.json | 1 + .../tests/FileSystemWatcher.netstandard17.cs | 269 ++++++++++++++++++ .../System.IO.FileSystem.Watcher.Tests.csproj | 17 +- .../tests/Utility/TestFileSystemWatcher.cs | 8 + 10 files changed, 442 insertions(+), 20 deletions(-) create mode 100644 src/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.netstandard17.cs diff --git a/src/System.IO.FileSystem.Watcher/ref/System.IO.FileSystem.Watcher.cs b/src/System.IO.FileSystem.Watcher/ref/System.IO.FileSystem.Watcher.cs index 5117c515c999..b33b52968670 100644 --- a/src/System.IO.FileSystem.Watcher/ref/System.IO.FileSystem.Watcher.cs +++ b/src/System.IO.FileSystem.Watcher/ref/System.IO.FileSystem.Watcher.cs @@ -22,7 +22,7 @@ public FileSystemEventArgs(System.IO.WatcherChangeTypes changeType, string direc public string Name { get { throw null; } } } public delegate void FileSystemEventHandler(object sender, System.IO.FileSystemEventArgs e); - public partial class FileSystemWatcher : System.ComponentModel.Component + public partial class FileSystemWatcher : System.ComponentModel.Component, System.ComponentModel.ISupportInitialize { public FileSystemWatcher() { } public FileSystemWatcher(string path) { } @@ -45,6 +45,11 @@ protected void OnError(System.IO.ErrorEventArgs e) { } protected void OnRenamed(System.IO.RenamedEventArgs e) { } public System.IO.WaitForChangedResult WaitForChanged(System.IO.WatcherChangeTypes changeType) { throw null; } public System.IO.WaitForChangedResult WaitForChanged(System.IO.WatcherChangeTypes changeType, int timeout) { throw null; } + public override System.ComponentModel.ISite Site { get { throw null; } set { } } + public System.ComponentModel.ISynchronizeInvoke SynchronizingObject { get { throw null; } set { } } + public void BeginInit() { } + protected override void Dispose(bool disposing) { } + public void EndInit() { } } [Serializable] public partial class InternalBufferOverflowException : System.SystemException diff --git a/src/System.IO.FileSystem.Watcher/ref/project.json b/src/System.IO.FileSystem.Watcher/ref/project.json index 75769edcda6a..e45d59377e9f 100644 --- a/src/System.IO.FileSystem.Watcher/ref/project.json +++ b/src/System.IO.FileSystem.Watcher/ref/project.json @@ -1,7 +1,8 @@ { "dependencies": { "System.Runtime": "4.4.0-beta-24715-03", - "System.ComponentModel.Primitives": "4.4.0-beta-24715-03" + "System.ComponentModel.Primitives": "4.4.0-beta-24715-03", + "System.ComponentModel.TypeConverter": "4.4.0-beta-24715-03" }, "frameworks": { "netstandard1.7": {} diff --git a/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs b/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs index 3babb644417a..7c7d22a60b19 100644 --- a/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs +++ b/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs @@ -19,6 +19,13 @@ public partial class FileSystemWatcher /// Starts a new watch operation if one is not currently running. private void StartRaisingEvents() { + // If we're called when "Initializing" is true, set enabled to true + if (IsSuspended()) + { + _enabled = true; + return; + } + // If we already have a cancellation object, we're already running. if (_cancellation != null) { @@ -88,6 +95,9 @@ private void StopRaisingEvents() { _enabled = false; + if (IsSuspended()) + return; + // If there's an active cancellation token, cancel and release it. // The cancellation token and the processing task respond to cancellation // to handle all other cleanup. diff --git a/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs b/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs index 5d49fa766664..f66413f3f4e2 100644 --- a/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs +++ b/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs @@ -27,6 +27,13 @@ private void FinalizeDispose() private void StartRaisingEvents() { + // If we're called when "Initializing" is true, set enabled to true + if (IsSuspended()) + { + _enabled = true; + return; + } + // Don't start another instance if one is already runnings if (_cancellation != null) { @@ -53,6 +60,9 @@ private void StopRaisingEvents() { _enabled = false; + if (IsSuspended()) + return; + CancellationTokenSource token = _cancellation; if (token != null) { diff --git a/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs b/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs index 96eeba9f1278..84cb7a5c2300 100644 --- a/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs +++ b/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs @@ -14,6 +14,13 @@ public partial class FileSystemWatcher /// Start monitoring the current directory. private void StartRaisingEvents() { + // If we're called when "Initializing" is true, set enabled to true + if (IsSuspended()) + { + _enabled = true; + return; + } + // If we're already running, don't do anything. if (!IsHandleInvalid(_directoryHandle)) return; @@ -67,6 +74,9 @@ private void StopRaisingEvents() { _enabled = false; + if (IsSuspended()) + return; + // If we're not running, do nothing. if (IsHandleInvalid(_directoryHandle)) return; diff --git a/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs b/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs index 347803d5cd05..efa331ab1cc8 100644 --- a/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs +++ b/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.ComponentModel; +using System.ComponentModel.Design; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Threading; @@ -15,7 +16,7 @@ namespace System.IO /// raises events when a directory or file within a directory changes. /// - public partial class FileSystemWatcher : Component + public partial class FileSystemWatcher : Component, ISupportInitialize { /// /// Private instance variables @@ -36,11 +37,15 @@ public partial class FileSystemWatcher : Component // Flag to note whether we are attached to the thread pool and responding to changes private bool _enabled = false; + // Are we in init? + private bool _initializing = false; + // Buffer size private int _internalBufferSize = 8192; // Used for synchronization private bool _disposed; + private ISynchronizeInvoke _synchronizingObject; // Event handlers private FileSystemEventHandler _onChangedHandler = null; @@ -146,14 +151,21 @@ public bool EnableRaisingEvents { return; } - - if (value) + + if (IsSuspended()) { - StartRaisingEventsIfNotDisposed(); // will set _enabled to true once successfully started + _enabled = value; // Alert the Component to start watching for events when EndInit is called. } else - { - StopRaisingEvents(); // will set _enabled to false + { + if (value) + { + StartRaisingEventsIfNotDisposed(); // will set _enabled to true once successfully started + } + else + { + StopRaisingEvents(); // will set _enabled to false + } } } } @@ -371,6 +383,7 @@ protected override void Dispose(bool disposing) finally { _disposed = true; + base.Dispose(disposing); } } @@ -446,7 +459,7 @@ private void NotifyFileSystemEventArgs(WatcherChangeTypes changeType, string nam [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")] protected void OnChanged(FileSystemEventArgs e) { - _onChangedHandler?.Invoke(this, e); + InvokeOn(e, _onChangedHandler); } /// @@ -455,7 +468,7 @@ protected void OnChanged(FileSystemEventArgs e) [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")] protected void OnCreated(FileSystemEventArgs e) { - _onCreatedHandler?.Invoke(this, e); + InvokeOn(e, _onCreatedHandler); } /// @@ -464,7 +477,19 @@ protected void OnCreated(FileSystemEventArgs e) [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")] protected void OnDeleted(FileSystemEventArgs e) { - _onDeletedHandler?.Invoke(this, e); + InvokeOn(e, _onDeletedHandler); + } + + private void InvokeOn(FileSystemEventArgs e, FileSystemEventHandler handler) + { + if (handler != null) + { + ISynchronizeInvoke syncObj = SynchronizingObject; + if (syncObj != null && syncObj.InvokeRequired) + syncObj.BeginInvoke(handler, new object[] { this, e }); + else + handler(this, e); + } } /// @@ -473,7 +498,15 @@ protected void OnDeleted(FileSystemEventArgs e) [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")] protected void OnError(ErrorEventArgs e) { - _onErrorHandler?.Invoke(this, e); + ErrorEventHandler handler = _onErrorHandler; + if (handler != null) + { + ISynchronizeInvoke syncObj = SynchronizingObject; + if (syncObj != null && syncObj.InvokeRequired) + syncObj.BeginInvoke(handler, new object[] { this, e }); + else + handler(this, e); + } } /// @@ -482,7 +515,15 @@ protected void OnError(ErrorEventArgs e) [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")] protected void OnRenamed(RenamedEventArgs e) { - _onRenamedHandler?.Invoke(this, e); + RenamedEventHandler handler = _onRenamedHandler; + if (handler != null) + { + ISynchronizeInvoke syncObj = SynchronizingObject; + if (syncObj != null && syncObj.InvokeRequired) + syncObj.BeginInvoke(handler, new object[] { this, e }); + else + handler(this, e); + } } public WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType) => @@ -566,7 +607,7 @@ public WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType, int ti /// private void Restart() { - if (_enabled) + if ((!IsSuspended()) && _enabled) { StopRaisingEvents(); StartRaisingEventsIfNotDisposed(); @@ -580,5 +621,67 @@ private void StartRaisingEventsIfNotDisposed() throw new ObjectDisposedException(GetType().Name); StartRaisingEvents(); } + + public override ISite Site + { + get + { + return base.Site; + } + set + { + base.Site = value; + + // set EnableRaisingEvents to true at design time so the user + // doesn't have to manually. + if (Site != null && Site.DesignMode) + EnableRaisingEvents = true; + } + } + + public ISynchronizeInvoke SynchronizingObject + { + get + { + if (_synchronizingObject == null && DesignMode) + { + IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); + if (host != null) + { + object baseComponent = host.RootComponent; + if (baseComponent != null && baseComponent is ISynchronizeInvoke) + _synchronizingObject = (ISynchronizeInvoke)baseComponent; + } + } + + return _synchronizingObject; + } + + set + { + _synchronizingObject = value; + } + } + + public void BeginInit() + { + bool oldEnabled = _enabled; + StopRaisingEvents(); + _enabled = oldEnabled; + _initializing = true; + } + + public void EndInit() + { + _initializing = false; + // Start listening to events if _enabled was set to true at some point. + if (_directory.Length != 0 && _enabled) + StartRaisingEvents(); + } + + private bool IsSuspended() + { + return _initializing || DesignMode; + } } } diff --git a/src/System.IO.FileSystem.Watcher/src/project.json b/src/System.IO.FileSystem.Watcher/src/project.json index 1a281f209daf..151d495fee72 100644 --- a/src/System.IO.FileSystem.Watcher/src/project.json +++ b/src/System.IO.FileSystem.Watcher/src/project.json @@ -6,6 +6,7 @@ "Microsoft.Win32.Primitives": "4.4.0-beta-24715-03", "System.Collections": "4.4.0-beta-24715-03", "System.ComponentModel.Primitives": "4.4.0-beta-24715-03", + "System.ComponentModel.TypeConverter": "4.4.0-beta-24715-03", "System.Diagnostics.Debug": "4.4.0-beta-24715-03", "System.Diagnostics.Tools": "4.4.0-beta-24715-03", "System.IO": "4.4.0-beta-24715-03", diff --git a/src/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.netstandard17.cs b/src/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.netstandard17.cs new file mode 100644 index 000000000000..34347fd98e45 --- /dev/null +++ b/src/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.netstandard17.cs @@ -0,0 +1,269 @@ +// 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; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; +using Xunit; + +namespace System.IO.Tests +{ + public class FileSystemWatcherTests_netstandard17 : FileSystemWatcherTest + { + public class TestSite : ISite + { + public bool designMode; + public bool DesignMode => designMode; + public IComponent Component => null; + public IContainer Container => null; + public string Name { get; set; } + public object GetService(Type serviceType) => null; + } + + [Fact] + public void Site_GetSetRoundtrips() + { + using (var testDirectory = new TempDirectory(GetTestFilePath())) + using (var watcher = new TestFileSystemWatcher(testDirectory.Path, "*")) + { + TestSite site = new TestSite(); + Assert.Null(watcher.Site); + watcher.Site = site; + Assert.Equal(site, watcher.Site); + watcher.Site = null; + Assert.Null(watcher.Site); + Assert.False(watcher.EnableRaisingEvents); + } + } + + /// + /// When the FSW Site is set to a nonnull Site with DesignMode enabled, Event raising will be set to true + /// + [Fact] + public void Site_NonNullSetEnablesRaisingEvents() + { + using (var testDirectory = new TempDirectory(GetTestFilePath())) + using (var watcher = new TestFileSystemWatcher(testDirectory.Path, "*")) + { + TestSite site = new TestSite() { designMode = true }; + watcher.Site = site; + Assert.True(watcher.EnableRaisingEvents); + } + } + + internal class TestISynchronizeInvoke : ISynchronizeInvoke + { + public bool BeginInvoke_Called; + public Delegate ExpectedDelegate; + + public IAsyncResult BeginInvoke(Delegate method, object[] args) + { + Assert.Equal(ExpectedDelegate, method); + BeginInvoke_Called = true; + return null; + } + + public bool InvokeRequired => true; + public object EndInvoke(IAsyncResult result) => null; + public object Invoke(Delegate method, object[] args) => null; + } + + [Fact] + public void SynchronizingObject_GetSetRoundtrips() + { + TestISynchronizeInvoke invoker = new TestISynchronizeInvoke() { }; + using (var testDirectory = new TempDirectory(GetTestFilePath())) + using (var watcher = new TestFileSystemWatcher(testDirectory.Path, "*")) + { + Assert.Null(watcher.SynchronizingObject); + watcher.SynchronizingObject = invoker; + Assert.Equal(invoker, watcher.SynchronizingObject); + watcher.SynchronizingObject = null; + Assert.Null(watcher.SynchronizingObject); + } + } + + /// + /// Ensure that the SynchronizeObject is invoked when an event occurs + /// + [Theory] + [InlineData(WatcherChangeTypes.Changed)] + [InlineData(WatcherChangeTypes.Deleted)] + [InlineData(WatcherChangeTypes.Created)] + public void SynchronizingObject_CalledOnEvent(WatcherChangeTypes expectedChangeType) + { + FileSystemEventHandler dele = (sender, e) => { Assert.Equal(expectedChangeType, e.ChangeType); }; + TestISynchronizeInvoke invoker = new TestISynchronizeInvoke() { ExpectedDelegate = dele }; + using (var testDirectory = new TempDirectory(GetTestFilePath())) + using (var watcher = new TestFileSystemWatcher(testDirectory.Path, "*")) + { + watcher.SynchronizingObject = invoker; + if (expectedChangeType == WatcherChangeTypes.Created) + { + watcher.Created += dele; + watcher.CallOnCreated(new FileSystemEventArgs(WatcherChangeTypes.Created, "test", "name")); + } + else if (expectedChangeType == WatcherChangeTypes.Deleted) + { + watcher.Deleted += dele; + watcher.CallOnDeleted(new FileSystemEventArgs(WatcherChangeTypes.Deleted, "test", "name")); + } + else if (expectedChangeType == WatcherChangeTypes.Changed) + { + watcher.Changed += dele; + watcher.CallOnChanged(new FileSystemEventArgs(WatcherChangeTypes.Changed, "test", "name")); + } + Assert.True(invoker.BeginInvoke_Called); + } + } + + /// + /// Ensure that the SynchronizeObject is invoked when an Renamed event occurs + /// + [Fact] + public void SynchronizingObject_CalledOnRenamed() + { + RenamedEventHandler dele = (sender, e) => { Assert.Equal(WatcherChangeTypes.Renamed, e.ChangeType); }; + TestISynchronizeInvoke invoker = new TestISynchronizeInvoke() { ExpectedDelegate = dele }; + using (var testDirectory = new TempDirectory(GetTestFilePath())) + using (var watcher = new TestFileSystemWatcher(testDirectory.Path, "*")) + { + watcher.SynchronizingObject = invoker; + watcher.Renamed += dele; + watcher.CallOnRenamed(new RenamedEventArgs(WatcherChangeTypes.Changed, "test", "name", "oldname")); + Assert.True(invoker.BeginInvoke_Called); + } + } + + /// + /// Ensure that the SynchronizeObject is invoked when an Error event occurs + /// + [Fact] + public void SynchronizingObject_CalledOnError() + { + ErrorEventHandler dele = (sender, e) => { Assert.IsType(e.GetException()); }; + TestISynchronizeInvoke invoker = new TestISynchronizeInvoke() { ExpectedDelegate = dele }; + using (var testDirectory = new TempDirectory(GetTestFilePath())) + using (var watcher = new TestFileSystemWatcher(testDirectory.Path, "*")) + { + watcher.SynchronizingObject = invoker; + watcher.Error += dele; + watcher.CallOnError(new ErrorEventArgs(new FileNotFoundException())); + Assert.True(invoker.BeginInvoke_Called); + } + } + + /// + /// Calling BeginInit and EndInit in a loop is fine. If events are enabled, they will start and stop in the loop as well. + /// + [Fact] + public void BeginEndInit_Repeated() + { + using (var testDirectory = new TempDirectory(GetTestFilePath())) + using (var watcher = new TestFileSystemWatcher(testDirectory.Path, "*")) + { + watcher.BeginInit(); + watcher.EndInit(); + watcher.BeginInit(); + watcher.EndInit(); + Assert.False(watcher.EnableRaisingEvents); + } + } + + /// + /// BeginInit followed by a EnableRaisingEvents=true does not cause the watcher to begin. + /// + [Fact] + public void BeginInit_PausesEnableRaisingEvents() + { + using (var testDirectory = new TempDirectory(GetTestFilePath())) + using (var watcher = new TestFileSystemWatcher(testDirectory.Path, "*")) + { + watcher.Created += (obj, e) => { Assert.False(true, "Created event should not occur"); }; + watcher.Deleted += (obj, e) => { Assert.False(true, "Deleted event should not occur"); }; + watcher.BeginInit(); + watcher.EnableRaisingEvents = true; + new TempFile(Path.Combine(testDirectory.Path, GetTestFileName())).Dispose(); + Thread.Sleep(WaitForExpectedEventTimeout); + } + } + + /// + /// EndInit will begin EnableRaisingEvents if we previously set EnableRaisingEvents=true + /// + [Fact] + public void EndInit_ResumesPausedEnableRaisingEvents() + { + using (var testDirectory = new TempDirectory(GetTestFilePath())) + using (var watcher = new TestFileSystemWatcher(testDirectory.Path, "*")) + { + watcher.BeginInit(); + watcher.EnableRaisingEvents = true; + watcher.EndInit(); + ExpectEvent(watcher, WatcherChangeTypes.Created | WatcherChangeTypes.Deleted, () => new TempFile(Path.Combine(testDirectory.Path, GetTestFileName())).Dispose(), null); + } + } + + /// + /// EndInit will begin EnableRaisingEvents if we previously set EnableRaisingEvents=true + /// + [Theory] + [InlineData(true)] + [InlineData(false)] + public void EndInit_ResumesPausedEnableRaisingEvents(bool setBeforeBeginInit) + { + using (var testDirectory = new TempDirectory(GetTestFilePath())) + using (var watcher = new TestFileSystemWatcher(testDirectory.Path, "*")) + { + if (setBeforeBeginInit) + watcher.EnableRaisingEvents = true; + watcher.BeginInit(); + if (!setBeforeBeginInit) + watcher.EnableRaisingEvents = true; + watcher.EndInit(); + ExpectEvent(watcher, WatcherChangeTypes.Created | WatcherChangeTypes.Deleted, () => new TempFile(Path.Combine(testDirectory.Path, GetTestFileName())).Dispose(), null); + } + } + + /// + /// Stopping events during the initialization period will prevent the watcher from restarting after EndInit() + /// + [Fact] + public void EndRaisingEventsDuringPause() + { + using (var testDirectory = new TempDirectory(GetTestFilePath())) + using (var watcher = new TestFileSystemWatcher(testDirectory.Path, "*")) + { + watcher.EnableRaisingEvents = true; + watcher.BeginInit(); + watcher.EnableRaisingEvents = false; + watcher.EndInit(); + new TempFile(Path.Combine(testDirectory.Path, GetTestFileName())).Dispose(); + Thread.Sleep(WaitForExpectedEventTimeout); + } + } + + /// + /// EndInit will not start event raising unless EnableRaisingEvents was set to true. + /// + [Fact] + public void EndInit_DoesNotEnableEventRaisedEvents() + { + using (var testDirectory = new TempDirectory(GetTestFilePath())) + using (var watcher = new TestFileSystemWatcher(testDirectory.Path, "*")) + { + watcher.Created += (obj, e) => { Assert.False(true, "Created event should not occur"); }; + watcher.Deleted += (obj, e) => { Assert.False(true, "Deleted event should not occur"); }; + watcher.BeginInit(); + watcher.EndInit(); + new TempFile(Path.Combine(testDirectory.Path, GetTestFileName())).Dispose(); + Thread.Sleep(WaitForExpectedEventTimeout); + } + } + } +} diff --git a/src/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj b/src/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj index f0ee99371aa0..04baed0cab6c 100644 --- a/src/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj +++ b/src/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj @@ -1,4 +1,4 @@ - + Windows_Debug @@ -21,6 +21,13 @@ True + + + + + Common\System\Runtime\Serialization\Formatters\BinaryFormatterHelpers.cs + + @@ -38,9 +45,10 @@ - - + + Component + Common\System\IO\FileCleanupTestBase.cs @@ -54,9 +62,6 @@ Common\System\PlatformDetection.cs - - Common\System\Runtime\Serialization\Formatters\BinaryFormatterHelpers.cs - diff --git a/src/System.IO.FileSystem.Watcher/tests/Utility/TestFileSystemWatcher.cs b/src/System.IO.FileSystem.Watcher/tests/Utility/TestFileSystemWatcher.cs index 0b80691bdada..3d60e47510e4 100644 --- a/src/System.IO.FileSystem.Watcher/tests/Utility/TestFileSystemWatcher.cs +++ b/src/System.IO.FileSystem.Watcher/tests/Utility/TestFileSystemWatcher.cs @@ -9,6 +9,14 @@ namespace System.IO.Tests /// public class TestFileSystemWatcher : FileSystemWatcher { + public TestFileSystemWatcher() : base() + { + } + + public TestFileSystemWatcher(string path, string filter) : base(path, filter) + { + } + public void CallOnChanged(FileSystemEventArgs e) { this.OnChanged(e);