diff --git a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs index 48f13534f5..57f082a8d0 100644 --- a/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs +++ b/src/Microsoft.DotNet.Watcher.Core/Internal/Implementation/FileWatcher.cs @@ -96,8 +96,17 @@ namespace Microsoft.DotNet.Watcher.Core.Internal private void DisposeWatcher(string directory) { - _watchers[directory].Dispose(); + var watcher = _watchers[directory]; _watchers.Remove(directory); + + watcher.EnableRaisingEvents = false; + + watcher.Changed -= WatcherChangedHandler; + watcher.Created -= WatcherChangedHandler; + watcher.Deleted -= WatcherChangedHandler; + watcher.Renamed -= WatcherRenamedHandler; + + watcher.Dispose(); } private void EnsureNotDisposed() diff --git a/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs b/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs index c33696c1c0..55678cf11b 100644 --- a/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs +++ b/test/dotnet-watch.FunctionalTests/AppWithDepsTests.cs @@ -13,19 +13,22 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); // Change a file included in compilation - [Fact(Skip = "Disabled temporary")] + [Fact] public void ChangeFileInDependency() { using (var scenario = new AppWithDepsScenario()) - using (var wait = new WaitForFileToChange(scenario.StartedFile)) { - var fileToChange = Path.Combine(scenario.DependencyFolder, "Foo.cs"); - var programCs = File.ReadAllText(fileToChange); - File.WriteAllText(fileToChange, programCs); + scenario.Start(); + using (var wait = new WaitForFileToChange(scenario.StartedFile)) + { + var fileToChange = Path.Combine(scenario.DependencyFolder, "Foo.cs"); + var programCs = File.ReadAllText(fileToChange); + File.WriteAllText(fileToChange, programCs); - wait.Wait(_defaultTimeout, - expectedToChange: true, - errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + wait.Wait(_defaultTimeout, + expectedToChange: true, + errorMessage: $"Process did not restart because {scenario.StartedFile} was not changed"); + } } } @@ -51,7 +54,10 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests AppWithDepsFolder = Path.Combine(_scenario.WorkFolder, AppWithDeps); DependencyFolder = Path.Combine(_scenario.WorkFolder, Dependency); + } + public void Start() + { // Wait for the process to start using (var wait = new WaitForFileToChange(StatusFile)) { diff --git a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs index ab6fdf3328..839ce62426 100644 --- a/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/GlobbingAppTests.cs @@ -16,12 +16,14 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests private static readonly TimeSpan _negativeTestWaitTime = TimeSpan.FromSeconds(10); // Change a file included in compilation - [Fact(Skip = "Disabled temporary")] + [Fact] public void ChangeCompiledFile() { using (var scenario = new GlobbingAppScenario()) using (var wait = new WaitForFileToChange(scenario.StartedFile)) { + scenario.Start(); + var fileToChange = Path.Combine(scenario.TestAppFolder, "include", "Foo.cs"); var programCs = File.ReadAllText(fileToChange); File.WriteAllText(fileToChange, programCs); @@ -34,13 +36,15 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Add a file to a folder included in compilation - [Fact(Skip = "Disabled temporary")] + [Fact] public void AddCompiledFile() { // Add a file in a folder that's included in compilation using (var scenario = new GlobbingAppScenario()) using (var wait = new WaitForFileToChange(scenario.StartedFile)) { + scenario.Start(); + var fileToChange = Path.Combine(scenario.TestAppFolder, "include", "Bar.cs"); File.WriteAllText(fileToChange, ""); @@ -51,12 +55,14 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Delete a file included in compilation - [Fact(Skip = "Disabled temporary")] + [Fact] public void DeleteCompiledFile() { using (var scenario = new GlobbingAppScenario()) using (var wait = new WaitForFileToChange(scenario.StartedFile)) { + scenario.Start(); + var fileToChange = Path.Combine(scenario.TestAppFolder, "include", "Foo.cs"); File.Delete(fileToChange); @@ -67,13 +73,14 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Rename a file included in compilation - [Fact(Skip = "Disabled temporary")] + [Fact] public void RenameCompiledFile() { using (var scenario = new GlobbingAppScenario()) - using (var wait = new WaitForFileToChange(scenario.StatusFile)) { + scenario.Start(); + var oldFile = Path.Combine(scenario.TestAppFolder, "include", "Foo.cs"); var newFile = Path.Combine(scenario.TestAppFolder, "include", "Foo_new.cs"); File.Move(oldFile, newFile); @@ -85,19 +92,20 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Add a file that's in a included folder but not matching the globbing pattern - [Fact(Skip = "Disabled temporary")] + [Fact] public void ChangeNonCompiledFile() { using (var scenario = new GlobbingAppScenario()) - using (var wait = new WaitForFileToChange(scenario.StartedFile)) { + scenario.Start(); + var ids = File.ReadAllLines(scenario.StatusFile); var procId = int.Parse(ids[0]); var changedFile = Path.Combine(scenario.TestAppFolder, "include", "not_compiled.css"); File.WriteAllText(changedFile, ""); - Console.WriteLine($"Waiting {_negativeTestWaitTime} seconds to see if the app restarts"); + Console.WriteLine($"Waiting {_negativeTestWaitTime.TotalSeconds} seconds to see if the app restarts"); Waiters.WaitForProcessToStop( procId, _negativeTestWaitTime, @@ -107,27 +115,25 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } // Change a file that's in an excluded folder - [Fact(Skip = "Disabled temporary")] + [Fact] public void ChangeExcludedFile() { using (var scenario = new GlobbingAppScenario()) { - // Then wait for it to restart when we change a file that's included in the compilation files - using (var wait = new WaitForFileToChange(scenario.StartedFile)) - { - var ids = File.ReadAllLines(scenario.StatusFile); - var procId = int.Parse(ids[0]); - - var changedFile = Path.Combine(scenario.TestAppFolder, "exclude", "Baz.cs"); - File.WriteAllText(changedFile, ""); + scenario.Start(); - Console.WriteLine($"Waiting {_negativeTestWaitTime} seconds to see if the app restarts"); - Waiters.WaitForProcessToStop( - procId, - _negativeTestWaitTime, - expectedToStop: false, - errorMessage: "Test app restarted"); - } + var ids = File.ReadAllLines(scenario.StatusFile); + var procId = int.Parse(ids[0]); + + var changedFile = Path.Combine(scenario.TestAppFolder, "exclude", "Baz.cs"); + File.WriteAllText(changedFile, ""); + + Console.WriteLine($"Waiting {_negativeTestWaitTime.TotalSeconds} seconds to see if the app restarts"); + Waiters.WaitForProcessToStop( + procId, + _negativeTestWaitTime, + expectedToStop: false, + errorMessage: "Test app restarted"); } } @@ -146,7 +152,10 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests _scenario.Restore(); TestAppFolder = Path.Combine(_scenario.WorkFolder, TestAppName); + } + public void Start() + { // Wait for the process to start using (var wait = new WaitForFileToChange(StartedFile)) { diff --git a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs index a9d1080b30..418fe53fe1 100644 --- a/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs +++ b/test/dotnet-watch.FunctionalTests/NoDepsAppTests.cs @@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests { private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); - [Fact(Skip = "Disabled temporary")] + [Fact] public void RestartProcessOnFileChange() { using (var scenario = new NoDepsAppScenario()) @@ -51,7 +51,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } } - [Fact(Skip = "Disabled temporary")] + [Fact] public void RestartProcessThatTerminatesAfterFileChange() { using (var scenario = new NoDepsAppScenario()) @@ -91,7 +91,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests } - [Fact(Skip = "Disabled temporary")] + [Fact] public void ExitOnChange() { using (var scenario = new NoDepsAppScenario()) diff --git a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs index 41ee122cb1..be10d97fbc 100644 --- a/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs +++ b/test/dotnet-watch.FunctionalTests/Scenario/ProjectToolScenario.cs @@ -20,17 +20,14 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests Console.WriteLine($"The temporary test folder is {TempFolder}"); WorkFolder = Path.Combine(TempFolder, "work"); - PackagesFolder = Path.Combine(TempFolder, "packages"); - + CreateTestDirectory(); } - public string TempFolder { get; } = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + public string TempFolder { get; } = Path.Combine(Path.GetDirectoryName(FindNugetConfig()), "testWorkDir" , Guid.NewGuid().ToString()); public string WorkFolder { get; } - public string PackagesFolder { get; } - public void AddProject(string projectFolder) { var destinationFolder = Path.Combine(WorkFolder, Path.GetFileName(projectFolder)); @@ -95,6 +92,8 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests private void CreateTestDirectory() { Directory.CreateDirectory(WorkFolder); + File.WriteAllText(Path.Combine(WorkFolder, "global.json"), "{}"); + var nugetConfigFilePath = FindNugetConfig(); var tempNugetConfigFile = Path.Combine(WorkFolder, NugetConfigFileName); @@ -114,7 +113,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests return Process.Start(psi); } - private string FindNugetConfig() + private static string FindNugetConfig() { var currentDirPath = Directory.GetCurrentDirectory(); diff --git a/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs b/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs index 0105b74e8b..eb964f85d2 100644 --- a/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs +++ b/test/dotnet-watch.FunctionalTests/WaitForFileToChange.cs @@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests private readonly FileSystemWatcher _watcher; private readonly string _expectedFile; - private readonly ManualResetEvent _changed = new ManualResetEvent(false); + private ManualResetEvent _changed = new ManualResetEvent(false); public WaitForFileToChange(string file) { @@ -30,23 +30,33 @@ namespace Microsoft.DotNet.Watcher.FunctionalTests if (e.FullPath.Equals(_expectedFile, StringComparison.Ordinal)) { Waiters.WaitForFileToBeReadable(_expectedFile, TimeSpan.FromSeconds(10)); - _changed.Set(); + _changed?.Set(); } } public void Wait(TimeSpan timeout, bool expectedToChange, string errorMessage) { - var changed = _changed.WaitOne(timeout); - if (changed != expectedToChange) + if (_changed != null) { - throw new Exception(errorMessage); + var changed = _changed.WaitOne(timeout); + if (changed != expectedToChange) + { + throw new Exception(errorMessage); + } } } public void Dispose() { + _watcher.EnableRaisingEvents = false; + + _watcher.Changed -= WatcherEvent; + _watcher.Created -= WatcherEvent; + _watcher.Dispose(); _changed.Dispose(); + + _changed = null; } } }