Imported Upstream version 5.0.0.42

Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-04-10 11:41:01 +00:00
parent 1190d13a04
commit 6bdd276d05
19939 changed files with 3099680 additions and 93811 deletions

View File

@@ -0,0 +1,35 @@
// 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 Xunit;
namespace System.IO.Tests
{
public class ErrorEventArgsTests
{
[Fact]
public void ErrorEventArgs_ctor()
{
Exception exception = new Exception();
ErrorEventArgs args = new ErrorEventArgs(exception);
Assert.Equal(exception, args.GetException());
// Make sure method is consistent.
Assert.Equal(exception, args.GetException());
}
[Fact]
public void ErrorEventArgs_ctor_Null()
{
ErrorEventArgs args = new ErrorEventArgs(null);
Assert.Null(args.GetException());
// Make sure method is consistent.
Assert.Null(args.GetException());
}
}
}

View File

@@ -0,0 +1,36 @@
// 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 Xunit;
namespace System.IO.Tests
{
public class FileSystemEventArgsTests
{
[Theory]
[InlineData(WatcherChangeTypes.Changed, "C:", "foo.txt")]
[InlineData(WatcherChangeTypes.All, "C:", "foo.txt")]
[InlineData(0, "", "")]
[InlineData(0, "", null)]
public static void FileSystemEventArgs_ctor(WatcherChangeTypes changeType, string directory, string name)
{
FileSystemEventArgs args = new FileSystemEventArgs(changeType, directory, name);
if (!directory.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
{
directory += Path.DirectorySeparatorChar;
}
Assert.Equal(changeType, args.ChangeType);
Assert.Equal(directory + name, args.FullPath);
Assert.Equal(name, args.Name);
}
[Fact]
public static void FileSystemEventArgs_ctor_Invalid()
{
Assert.Throws<NullReferenceException>(() => new FileSystemEventArgs((WatcherChangeTypes)0, null, String.Empty));
}
}
}

View File

@@ -0,0 +1,43 @@
// 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 Xunit;
namespace System.IO.Tests
{
public class RenamedEventArgsTests
{
[Theory]
[InlineData(WatcherChangeTypes.Changed, "C:", "foo.txt", "bar.txt")]
[InlineData(WatcherChangeTypes.All, "C:", "foo.txt", "bar.txt")]
[InlineData(0, "", "", "")]
[InlineData(0, "", null, null)]
public static void RenamedEventArgs_ctor(WatcherChangeTypes changeType, string directory, string name, string oldName)
{
RenamedEventArgs args = new RenamedEventArgs(changeType, directory, name, oldName);
Assert.Equal(changeType, args.ChangeType);
Assert.Equal(directory + Path.DirectorySeparatorChar + name, args.FullPath);
Assert.Equal(name, args.Name);
Assert.Equal(oldName, args.OldName);
}
[Theory]
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "OldFullPath on Desktop demands FileIOPermissions which causes failures for invalid paths.")]
[InlineData(WatcherChangeTypes.Changed, "C:", "foo.txt", "bar.txt")]
[InlineData(WatcherChangeTypes.All, "C:", "foo.txt", "bar.txt")]
[InlineData(0, "", "", "")]
[InlineData(0, "", null, null)]
public static void RenamedEventArgs_ctor_OldFullPath(WatcherChangeTypes changeType, string directory, string name, string oldName)
{
RenamedEventArgs args = new RenamedEventArgs(changeType, directory, name, oldName);
Assert.Equal(directory + Path.DirectorySeparatorChar + oldName, args.OldFullPath);
}
[Fact]
public static void RenamedEventArgs_ctor_Invalid()
{
Assert.Throws<NullReferenceException>(() => new RenamedEventArgs((WatcherChangeTypes)0, null, String.Empty, String.Empty));
}
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
netstandard1.3-Linux;
netstandard1.3-OSX;
netstandard1.3-Windows_NT;
netstandard-Linux;
netstandard-OSX;
netstandard-Windows_NT;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,83 @@
// 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.Runtime.InteropServices;
using Xunit;
namespace System.IO.Tests
{
public class Directory_Changed_Tests : FileSystemWatcherTest
{
[Fact]
public void FileSystemWatcher_Directory_Changed_LastWrite()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(dir.Path)))
{
Action action = () => Directory.SetLastWriteTime(dir.Path, DateTime.Now + TimeSpan.FromSeconds(10));
WatcherChangeTypes expected = WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, expectedPath: dir.Path);
}
}
[Fact]
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Desktop FSW disallows modification of the watched folder.")]
public void FileSystemWatcher_Directory_Changed_WatchedFolder()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
Action action = () => Directory.SetLastWriteTime(dir.Path, DateTime.Now + TimeSpan.FromSeconds(10));
ExpectEvent(watcher, 0, action, expectedPath: dir.Path);
}
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void FileSystemWatcher_Directory_Changed_Nested(bool includeSubdirectories)
{
using (var dir = new TempDirectory(GetTestFilePath()))
using (var firstDir = new TempDirectory(Path.Combine(dir.Path, "dir1")))
using (var nestedDir = new TempDirectory(Path.Combine(firstDir.Path, "nested")))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
watcher.IncludeSubdirectories = includeSubdirectories;
watcher.NotifyFilter = NotifyFilters.DirectoryName | NotifyFilters.Attributes;
var attributes = File.GetAttributes(nestedDir.Path);
Action action = () => File.SetAttributes(nestedDir.Path, attributes | FileAttributes.ReadOnly);
Action cleanup = () => File.SetAttributes(nestedDir.Path, attributes);
WatcherChangeTypes expected = includeSubdirectories ? WatcherChangeTypes.Changed : 0;
ExpectEvent(watcher, expected, action, cleanup, nestedDir.Path);
}
}
[ConditionalFact(nameof(CanCreateSymbolicLinks))]
public void FileSystemWatcher_Directory_Changed_SymLink()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var tempDir = new TempDirectory(Path.Combine(testDirectory.Path, "tempDir")))
using (var file = new TempFile(Path.Combine(tempDir.Path, "test")))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
// Setup the watcher
watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
watcher.IncludeSubdirectories = true;
Assert.True(CreateSymLink(tempDir.Path, Path.Combine(dir.Path, "link"), true));
Action action = () => File.AppendAllText(file.Path, "longtext");
Action cleanup = () => File.AppendAllText(file.Path, "short");
ExpectEvent(watcher, 0, action, cleanup, dir.Path);
}
}
}
}

View File

@@ -0,0 +1,84 @@
// 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 Xunit;
namespace System.IO.Tests
{
public class Directory_Create_Tests : FileSystemWatcherTest
{
[Fact]
public void FileSystemWatcher_Directory_Create()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var watcher = new FileSystemWatcher(testDirectory.Path))
{
string dirName = Path.Combine(testDirectory.Path, "dir");
watcher.Filter = Path.GetFileName(dirName);
Action action = () => Directory.CreateDirectory(dirName);
Action cleanup = () => Directory.Delete(dirName);
ExpectEvent(watcher, WatcherChangeTypes.Created, action, cleanup, dirName);
}
}
[Fact]
public void FileSystemWatcher_Directory_Create_InNestedDirectory()
{
using (var dir = new TempDirectory(GetTestFilePath()))
using (var firstDir = new TempDirectory(Path.Combine(dir.Path, "dir1")))
using (var nestedDir = new TempDirectory(Path.Combine(firstDir.Path, "nested")))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
watcher.IncludeSubdirectories = true;
watcher.NotifyFilter = NotifyFilters.DirectoryName;
string dirName = Path.Combine(nestedDir.Path, "dir");
Action action = () => Directory.CreateDirectory(dirName);
Action cleanup = () => Directory.Delete(dirName);
ExpectEvent(watcher, WatcherChangeTypes.Created, action, cleanup, dirName);
}
}
[Fact]
[OuterLoop("This test has a longer than average timeout and may fail intermittently")]
public void FileSystemWatcher_Directory_Create_DeepDirectoryStructure()
{
using (var dir = new TempDirectory(GetTestFilePath()))
using (var deepDir = new TempDirectory(Path.Combine(dir.Path, "dir", "dir", "dir", "dir", "dir", "dir", "dir")))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
watcher.IncludeSubdirectories = true;
watcher.NotifyFilter = NotifyFilters.DirectoryName;
// Put a directory at the very bottom and expect it to raise an event
string dirPath = Path.Combine(deepDir.Path, "leafdir");
Action action = () => Directory.CreateDirectory(dirPath);
Action cleanup = () => Directory.Delete(dirPath);
ExpectEvent(watcher, WatcherChangeTypes.Created, action, cleanup, dirPath, LongWaitTimeout);
}
}
[ConditionalFact(nameof(CanCreateSymbolicLinks))]
public void FileSystemWatcher_Directory_Create_SymLink()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var temp = new TempDirectory(GetTestFilePath()))
using (var watcher = new FileSystemWatcher(Path.GetFullPath(dir.Path), "*"))
{
// Make the symlink in our path (to the temp folder) and make sure an event is raised
string symLinkPath = Path.Combine(dir.Path, Path.GetFileName(temp.Path));
Action action = () => Assert.True(CreateSymLink(temp.Path, symLinkPath, true));
Action cleanup = () => Directory.Delete(symLinkPath);
ExpectEvent(watcher, WatcherChangeTypes.Created, action, cleanup, symLinkPath);
}
}
}
}

View File

@@ -0,0 +1,89 @@
// 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 Xunit;
namespace System.IO.Tests
{
public class Directory_Delete_Tests : FileSystemWatcherTest
{
[Fact]
public void FileSystemWatcher_Directory_Delete()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var watcher = new FileSystemWatcher(testDirectory.Path))
{
string dirName = Path.Combine(testDirectory.Path, "dir");
watcher.Filter = Path.GetFileName(dirName);
Action action = () => Directory.Delete(dirName);
Action cleanup = () => Directory.CreateDirectory(dirName);
cleanup();
ExpectEvent(watcher, WatcherChangeTypes.Deleted, action, cleanup, expectedPath: dirName);
}
}
[Fact]
public void FileSystemWatcher_Directory_Delete_InNestedDirectory()
{
using (var dir = new TempDirectory(GetTestFilePath()))
using (var firstDir = new TempDirectory(Path.Combine(dir.Path, "dir1")))
using (var nestedDir = new TempDirectory(Path.Combine(firstDir.Path, "nested")))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
watcher.IncludeSubdirectories = true;
watcher.NotifyFilter = NotifyFilters.DirectoryName;
string dirName = Path.Combine(nestedDir.Path, "dir");
Action action = () => Directory.Delete(dirName);
Action cleanup = () => Directory.CreateDirectory(dirName);
cleanup();
ExpectEvent(watcher, WatcherChangeTypes.Deleted, action, cleanup, dirName);
}
}
[Fact]
[OuterLoop("This test has a longer than average timeout and may fail intermittently")]
public void FileSystemWatcher_Directory_Delete_DeepDirectoryStructure()
{
using (var dir = new TempDirectory(GetTestFilePath()))
using (var deepDir = new TempDirectory(Path.Combine(dir.Path, "dir", "dir", "dir", "dir", "dir", "dir", "dir")))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
watcher.IncludeSubdirectories = true;
watcher.NotifyFilter = NotifyFilters.DirectoryName;
// Put a directory at the very bottom and expect it to raise an event
string dirPath = Path.Combine(deepDir.Path, "leafdir");
Action action = () => Directory.Delete(dirPath);
Action cleanup = () => Directory.CreateDirectory(dirPath);
cleanup();
ExpectEvent(watcher, WatcherChangeTypes.Deleted, action, cleanup, dirPath, LongWaitTimeout);
}
}
[ConditionalFact(nameof(CanCreateSymbolicLinks))]
public void FileSystemWatcher_Directory_Delete_SymLink()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var tempDir = new TempDirectory(GetTestFilePath()))
using (var watcher = new FileSystemWatcher(Path.GetFullPath(dir.Path), "*"))
{
// Make the symlink in our path (to the temp folder) and make sure an event is raised
string symLinkPath = Path.Combine(dir.Path, "link");
Action action = () => Directory.Delete(symLinkPath);
Action cleanup = () => Assert.True(CreateSymLink(tempDir.Path, symLinkPath, true));
cleanup();
ExpectEvent(watcher, WatcherChangeTypes.Deleted, action, cleanup, expectedPath: symLinkPath);
}
}
}
}

View File

@@ -0,0 +1,171 @@
// 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 Xunit;
namespace System.IO.Tests
{
public class Directory_Move_Tests : FileSystemWatcherTest
{
[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
public void Directory_Move_To_Same_Directory()
{
DirectoryMove_SameDirectory(WatcherChangeTypes.Renamed);
}
[Fact]
public void Directory_Move_From_Watched_To_Unwatched()
{
DirectoryMove_FromWatchedToUnwatched(WatcherChangeTypes.Deleted);
}
[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
public void Windows_Directory_Move_To_Different_Watched_Directory()
{
DirectoryMove_DifferentWatchedDirectory(WatcherChangeTypes.Changed);
}
[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)]
public void Unix_Directory_Move_To_Different_Watched_Directory()
{
DirectoryMove_DifferentWatchedDirectory(0);
}
[Fact]
public void Directory_Move_From_Unwatched_To_Watched()
{
DirectoryMove_FromUnwatchedToWatched(WatcherChangeTypes.Created);
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void Directory_Move_In_Nested_Directory(bool includeSubdirectories)
{
DirectoryMove_NestedDirectory(includeSubdirectories ? WatcherChangeTypes.Renamed : 0, includeSubdirectories);
}
[Fact]
public void Directory_Move_With_Set_NotifyFilter()
{
DirectoryMove_WithNotifyFilter(WatcherChangeTypes.Renamed);
}
#region Test Helpers
private void DirectoryMove_SameDirectory(WatcherChangeTypes eventType)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, "*"))
{
string sourcePath = dir.Path;
string targetPath = Path.Combine(testDirectory.Path, "target");
Action action = () => Directory.Move(sourcePath, targetPath);
Action cleanup = () => Directory.Move(targetPath, sourcePath);
ExpectEvent(watcher, eventType, action, cleanup, targetPath);
}
}
private void DirectoryMove_DifferentWatchedDirectory(WatcherChangeTypes eventType)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var sourceDir = new TempDirectory(Path.Combine(testDirectory.Path, "source")))
using (var adjacentDir = new TempDirectory(Path.Combine(testDirectory.Path, "adj")))
using (var dir = new TempDirectory(Path.Combine(sourceDir.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, "*"))
{
string sourcePath = dir.Path;
string targetPath = Path.Combine(adjacentDir.Path, "target");
// Move the dir to a different directory under the Watcher
Action action = () => Directory.Move(sourcePath, targetPath);
Action cleanup = () => Directory.Move(targetPath, sourcePath);
ExpectEvent(watcher, eventType, action, cleanup, new string[] { sourceDir.Path, adjacentDir.Path });
}
}
private void DirectoryMove_FromWatchedToUnwatched(WatcherChangeTypes eventType)
{
using (var watchedTestDirectory = new TempDirectory(GetTestFilePath()))
using (var unwatchedTestDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(watchedTestDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(watchedTestDirectory.Path, "*"))
{
string sourcePath = dir.Path; // watched
string targetPath = Path.Combine(unwatchedTestDirectory.Path, "target");
Action action = () => Directory.Move(sourcePath, targetPath);
Action cleanup = () => Directory.Move(targetPath, sourcePath);
ExpectEvent(watcher, eventType, action, cleanup, sourcePath);
}
}
private void DirectoryMove_FromUnwatchedToWatched(WatcherChangeTypes eventType)
{
using (var watchedTestDirectory = new TempDirectory(GetTestFilePath()))
using (var unwatchedTestDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(unwatchedTestDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(watchedTestDirectory.Path, "*"))
{
string sourcePath = dir.Path; // unwatched
string targetPath = Path.Combine(watchedTestDirectory.Path, "target");
Action action = () => Directory.Move(sourcePath, targetPath);
Action cleanup = () => Directory.Move(targetPath, sourcePath);
ExpectEvent(watcher, eventType, action, cleanup, targetPath);
}
}
private void DirectoryMove_NestedDirectory(WatcherChangeTypes eventType, bool includeSubdirectories)
{
using (var dir = new TempDirectory(GetTestFilePath()))
using (var firstDir = new TempDirectory(Path.Combine(dir.Path, "first")))
using (var secondDir = new TempDirectory(Path.Combine(firstDir.Path, "second")))
using (var nestedDir = new TempDirectory(Path.Combine(secondDir.Path, "nested")))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
watcher.IncludeSubdirectories = includeSubdirectories;
watcher.NotifyFilter = NotifyFilters.DirectoryName;
string sourcePath = nestedDir.Path;
string targetPath = nestedDir.Path + "_2";
// Move the dir to a different directory within the same nested directory
Action action = () => Directory.Move(sourcePath, targetPath);
Action cleanup = () => Directory.Move(targetPath, sourcePath);
ExpectEvent(watcher, eventType, action, cleanup, targetPath);
}
}
private void DirectoryMove_WithNotifyFilter(WatcherChangeTypes eventType)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, "*"))
{
watcher.NotifyFilter = NotifyFilters.DirectoryName;
string sourcePath = dir.Path;
string targetPath = dir.Path + "_2";
Action action = () => Directory.Move(sourcePath, targetPath);
Action cleanup = () => Directory.Move(targetPath, sourcePath);
ExpectEvent(watcher, eventType, action, cleanup, targetPath);
}
}
#endregion
}
}

View File

@@ -0,0 +1,258 @@
// 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.Runtime.InteropServices;
using Xunit;
namespace System.IO.Tests
{
public class Directory_NotifyFilter_Tests : FileSystemWatcherTest
{
[DllImport("advapi32.dll", EntryPoint = "SetNamedSecurityInfoW",
CallingConvention = CallingConvention.Winapi, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
private static extern uint SetSecurityInfoByHandle( string name, uint objectType, uint securityInformation,
IntPtr owner, IntPtr group, IntPtr dacl, IntPtr sacl);
private const uint ERROR_SUCCESS = 0;
private const uint DACL_SECURITY_INFORMATION = 0x00000004;
private const uint SE_FILE_OBJECT = 0x1;
[Theory]
[MemberData(nameof(FilterTypes))]
public void FileSystemWatcher_Directory_NotifyFilter_Attributes(NotifyFilters filter)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(dir.Path)))
{
watcher.NotifyFilter = filter;
var attributes = File.GetAttributes(dir.Path);
Action action = () => File.SetAttributes(dir.Path, attributes | FileAttributes.ReadOnly);
Action cleanup = () => File.SetAttributes(dir.Path, attributes);
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.Attributes)
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && ((filter & LinuxFiltersForAttribute) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((filter & OSXFiltersForModify) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((filter & NotifyFilters.Security) > 0))
expected |= WatcherChangeTypes.Changed; // Attribute change on OSX is a ChangeOwner operation which passes the Security NotifyFilter.
ExpectEvent(watcher, expected, action, cleanup, dir.Path);
}
}
[Theory]
[MemberData(nameof(FilterTypes))]
public void FileSystemWatcher_Directory_NotifyFilter_CreationTime(NotifyFilters filter)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(dir.Path)))
{
watcher.NotifyFilter = filter;
Action action = () => Directory.SetCreationTime(dir.Path, DateTime.Now + TimeSpan.FromSeconds(10));
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.CreationTime)
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && ((filter & LinuxFiltersForAttribute) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((filter & OSXFiltersForModify) > 0))
expected |= WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, expectedPath: dir.Path);
}
}
[Theory]
[MemberData(nameof(FilterTypes))]
public void FileSystemWatcher_Directory_NotifyFilter_DirectoryName(NotifyFilters filter)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(dir.Path)))
{
string sourcePath = dir.Path;
string targetPath = Path.Combine(testDirectory.Path, "targetDir");
watcher.NotifyFilter = filter;
Action action = () => Directory.Move(sourcePath, targetPath);
Action cleanup = () => Directory.Move(targetPath, sourcePath);
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.DirectoryName)
expected |= WatcherChangeTypes.Renamed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && (filter == NotifyFilters.FileName))
expected |= WatcherChangeTypes.Renamed;
ExpectEvent(watcher, expected, action, cleanup, targetPath);
}
}
[Theory]
[MemberData(nameof(FilterTypes))]
public void FileSystemWatcher_Directory_NotifyFilter_LastAccessTime(NotifyFilters filter)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(dir.Path)))
{
watcher.NotifyFilter = filter;
Action action = () => Directory.SetLastAccessTime(dir.Path, DateTime.Now + TimeSpan.FromSeconds(10));
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.LastAccess)
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && ((filter & LinuxFiltersForAttribute) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((filter & OSXFiltersForModify) > 0))
expected |= WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, expectedPath: dir.Path);
}
}
[Theory]
[MemberData(nameof(FilterTypes))]
public void FileSystemWatcher_Directory_NotifyFilter_LastWriteTime(NotifyFilters filter)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(dir.Path)))
{
watcher.NotifyFilter = filter;
Action action = () => Directory.SetLastWriteTime(dir.Path, DateTime.Now + TimeSpan.FromSeconds(10));
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.LastWrite)
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && ((filter & LinuxFiltersForAttribute) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((filter & OSXFiltersForModify) > 0))
expected |= WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, expectedPath: dir.Path);
}
}
[Theory]
[MemberData(nameof(FilterTypes))]
[PlatformSpecific(TestPlatforms.Windows)]
public void FileSystemWatcher_Directory_NotifyFilter_Security(NotifyFilters filter)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(dir.Path)))
{
watcher.NotifyFilter = filter;
Action action = () =>
{
// ACL support is not yet available, so pinvoke directly.
uint result = SetSecurityInfoByHandle(dir.Path,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION, // Only setting the DACL
owner: IntPtr.Zero,
group: IntPtr.Zero,
dacl: IntPtr.Zero, // full access to everyone
sacl: IntPtr.Zero);
Assert.Equal(ERROR_SUCCESS, result);
};
Action cleanup = () =>
{
// Recreate the Directory.
Directory.Delete(dir.Path);
Directory.CreateDirectory(dir.Path);
};
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.Security)
expected |= WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, cleanup, dir.Path);
}
}
/// <summary>
/// Tests a changed event on a file when filtering for LastWrite and directory name.
/// </summary>
[Fact]
public void FileSystemWatcher_Directory_NotifyFilter_LastWriteAndFileName()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
{
NotifyFilters filter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName;
watcher.NotifyFilter = filter;
Action action = () => File.SetLastWriteTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
ExpectEvent(watcher, WatcherChangeTypes.Changed, action, expectedPath: file.Path);
}
}
/// <summary>
/// Tests the watcher behavior when two events - a Modification and a Creation - happen closely
/// after each other.
/// </summary>
[Fact]
public void FileSystemWatcher_Directory_NotifyFilter_ModifyAndCreate()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, "*"))
{
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName;
string otherDir = Path.Combine(testDirectory.Path, "dir2");
Action action = () =>
{
Directory.CreateDirectory(otherDir);
Directory.SetLastWriteTime(dir.Path, DateTime.Now + TimeSpan.FromSeconds(10));
};
Action cleanup = () => Directory.Delete(otherDir);
WatcherChangeTypes expected = 0;
expected |= WatcherChangeTypes.Created | WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, cleanup, new string[] { otherDir, dir.Path });
}
}
/// <summary>
/// Tests the watcher behavior when two events - a Modification and a Deletion - happen closely
/// after each other.
/// </summary>
[Fact]
public void FileSystemWatcher_Directory_NotifyFilter_ModifyAndDelete()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, "*"))
{
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName;
string otherDir = Path.Combine(testDirectory.Path, "dir2");
Action action = () =>
{
Directory.Delete(otherDir);
Directory.SetLastWriteTime(dir.Path, DateTime.Now + TimeSpan.FromSeconds(10));
};
Action cleanup = () =>
{
Directory.CreateDirectory(otherDir);
};
cleanup();
WatcherChangeTypes expected = 0;
expected |= WatcherChangeTypes.Deleted | WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, cleanup, new string[] { otherDir, dir.Path });
}
}
}
}

View File

@@ -0,0 +1,86 @@
// 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.Runtime.InteropServices;
using Xunit;
namespace System.IO.Tests
{
public class File_Changed_Tests : FileSystemWatcherTest
{
[Fact]
public void FileSystemWatcher_File_Changed_LastWrite()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
{
Action action = () => Directory.SetLastWriteTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
WatcherChangeTypes expected = WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, expectedPath: file.Path);
}
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void FileSystemWatcher_File_Changed_Nested(bool includeSubdirectories)
{
using (var dir = new TempDirectory(GetTestFilePath()))
using (var firstDir = new TempDirectory(Path.Combine(dir.Path, "dir1")))
using (var nestedDir = new TempDirectory(Path.Combine(firstDir.Path, "nested")))
using (var nestedFile = new TempFile(Path.Combine(nestedDir.Path, "nestedFile")))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
watcher.IncludeSubdirectories = includeSubdirectories;
watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Attributes;
var attributes = File.GetAttributes(nestedFile.Path);
Action action = () => File.SetAttributes(nestedFile.Path, attributes | FileAttributes.ReadOnly);
Action cleanup = () => File.SetAttributes(nestedFile.Path, attributes);
WatcherChangeTypes expected = includeSubdirectories ? WatcherChangeTypes.Changed : 0;
ExpectEvent(watcher, expected, action, cleanup, nestedFile.Path);
}
}
[Fact]
public void FileSystemWatcher_File_Changed_DataModification()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(Path.GetFullPath(dir.Path), "*"))
{
string fileName = Path.Combine(dir.Path, "testFile.txt");
watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
Action action = () => File.AppendAllText(fileName, "longlonglong!");
Action cleanup = () => File.WriteAllText(fileName, "short");
cleanup(); // Initially create the short file.
WatcherChangeTypes expected = WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, expectedPath: fileName);
}
}
[ConditionalFact(nameof(CanCreateSymbolicLinks))]
public void FileSystemWatcher_File_Changed_SymLink()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var file = new TempFile(GetTestFilePath()))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
Assert.True(CreateSymLink(file.Path, Path.Combine(dir.Path, "link"), false));
Action action = () => File.AppendAllText(file.Path, "longtext");
Action cleanup = () => File.AppendAllText(file.Path, "short");
ExpectEvent(watcher, 0, action, cleanup, expectedPath: file.Path);
}
}
}
}

View File

@@ -0,0 +1,105 @@
// 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 Xunit;
namespace System.IO.Tests
{
public class File_Create_Tests : FileSystemWatcherTest
{
[Fact]
public void FileSystemWatcher_File_Create()
{
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);
Action action = () => File.Create(fileName).Dispose();
Action cleanup = () => File.Delete(fileName);
ExpectEvent(watcher, WatcherChangeTypes.Created, action, cleanup, fileName);
}
}
[Fact]
public void FileSystemWatcher_File_Create_ForcedRestart()
{
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);
Action action = () =>
{
watcher.NotifyFilter = NotifyFilters.FileName; // change filter to force restart
File.Create(fileName).Dispose();
};
Action cleanup = () => File.Delete(fileName);
ExpectEvent(watcher, WatcherChangeTypes.Created, action, cleanup, fileName);
}
}
[Fact]
public void FileSystemWatcher_File_Create_InNestedDirectory()
{
using (var dir = new TempDirectory(GetTestFilePath()))
using (var firstDir = new TempDirectory(Path.Combine(dir.Path, "dir1")))
using (var nestedDir = new TempDirectory(Path.Combine(firstDir.Path, "nested")))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
watcher.IncludeSubdirectories = true;
watcher.NotifyFilter = NotifyFilters.FileName;
string fileName = Path.Combine(nestedDir.Path, "file");
Action action = () => File.Create(fileName).Dispose();
Action cleanup = () => File.Delete(fileName);
ExpectEvent(watcher, WatcherChangeTypes.Created, action, cleanup, fileName);
}
}
[Fact]
[OuterLoop("This test has a longer than average timeout and may fail intermittently")]
public void FileSystemWatcher_File_Create_DeepDirectoryStructure()
{
using (var dir = new TempDirectory(GetTestFilePath()))
using (var deepDir = new TempDirectory(Path.Combine(dir.Path, "dir", "dir", "dir", "dir", "dir", "dir", "dir")))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
watcher.IncludeSubdirectories = true;
watcher.NotifyFilter = NotifyFilters.FileName;
// Put a file at the very bottom and expect it to raise an event
string fileName = Path.Combine(deepDir.Path, "file");
Action action = () => File.Create(fileName).Dispose();
Action cleanup = () => File.Delete(fileName);
ExpectEvent(watcher, WatcherChangeTypes.Created, action, cleanup, fileName, LongWaitTimeout);
}
}
[ConditionalFact(nameof(CanCreateSymbolicLinks))]
public void FileSystemWatcher_File_Create_SymLink()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var temp = new TempFile(GetTestFilePath()))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
// Make the symlink in our path (to the temp file) and make sure an event is raised
string symLinkPath = Path.Combine(dir.Path, Path.GetFileName(temp.Path));
Action action = () => Assert.True(CreateSymLink(temp.Path, symLinkPath, false));
Action cleanup = () => File.Delete(symLinkPath);
ExpectEvent(watcher, WatcherChangeTypes.Created, action, cleanup, symLinkPath);
}
}
}
}

View File

@@ -0,0 +1,110 @@
// 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 Xunit;
namespace System.IO.Tests
{
public class File_Delete_Tests : FileSystemWatcherTest
{
[Fact]
public void FileSystemWatcher_File_Delete()
{
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);
Action action = () => File.Delete(fileName);
Action cleanup = () => File.Create(fileName).Dispose();
cleanup();
ExpectEvent(watcher, WatcherChangeTypes.Deleted, action, cleanup, fileName);
}
}
[Fact]
public void FileSystemWatcher_File_Delete_ForcedRestart()
{
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);
Action action = () =>
{
watcher.NotifyFilter = NotifyFilters.FileName; // change filter to force restart
File.Delete(fileName);
};
Action cleanup = () => File.Create(fileName).Dispose();
cleanup();
ExpectEvent(watcher, WatcherChangeTypes.Deleted, action, cleanup, fileName);
}
}
[Fact]
public void FileSystemWatcher_File_Delete_InNestedDirectory()
{
using (var dir = new TempDirectory(GetTestFilePath()))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
using (var firstDir = new TempDirectory(Path.Combine(dir.Path, "dir1")))
using (var nestedDir = new TempDirectory(Path.Combine(firstDir.Path, "nested")))
{
watcher.IncludeSubdirectories = true;
watcher.NotifyFilter = NotifyFilters.FileName;
string fileName = Path.Combine(nestedDir.Path, "file");
Action action = () => File.Delete(fileName);
Action cleanup = () => File.Create(fileName).Dispose();
cleanup();
ExpectEvent(watcher, WatcherChangeTypes.Deleted, action, cleanup, fileName);
}
}
[Fact]
[OuterLoop("This test has a longer than average timeout and may fail intermittently")]
public void FileSystemWatcher_File_Delete_DeepDirectoryStructure()
{
using (var dir = new TempDirectory(GetTestFilePath()))
using (var deepDir = new TempDirectory(Path.Combine(dir.Path, "dir", "dir", "dir", "dir", "dir", "dir", "dir")))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
watcher.IncludeSubdirectories = true;
watcher.NotifyFilter = NotifyFilters.FileName;
// Put a file at the very bottom and expect it to raise an event
string fileName = Path.Combine(deepDir.Path, "file");
Action action = () => File.Delete(fileName);
Action cleanup = () => File.Create(fileName).Dispose();
cleanup();
ExpectEvent(watcher, WatcherChangeTypes.Deleted, action, cleanup, fileName, LongWaitTimeout);
}
}
[ConditionalFact(nameof(CanCreateSymbolicLinks))]
public void FileSystemWatcher_File_Delete_SymLink()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var temp = new TempFile(GetTestFilePath()))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
// Make the symlink in our path (to the temp file) and make sure an event is raised
string symLinkPath = Path.Combine(dir.Path, Path.GetFileName(temp.Path));
Action action = () => File.Delete(symLinkPath);
Action cleanup = () => Assert.True(CreateSymLink(temp.Path, symLinkPath, false));
cleanup();
ExpectEvent(watcher, WatcherChangeTypes.Deleted, action, cleanup, symLinkPath);
}
}
}
}

View File

@@ -0,0 +1,216 @@
// 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 Xunit;
namespace System.IO.Tests
{
public class File_Move_Tests : FileSystemWatcherTest
{
[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
public void Windows_File_Move_To_Same_Directory()
{
FileMove_SameDirectory(WatcherChangeTypes.Renamed);
}
[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)]
public void Unix_File_Move_To_Same_Directory()
{
FileMove_SameDirectory(WatcherChangeTypes.Created | WatcherChangeTypes.Deleted);
}
[Fact]
public void File_Move_From_Watched_To_Unwatched()
{
FileMove_FromWatchedToUnwatched(WatcherChangeTypes.Deleted);
}
[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
public void Windows_File_Move_To_Different_Watched_Directory()
{
FileMove_DifferentWatchedDirectory(WatcherChangeTypes.Changed);
}
[Fact]
[PlatformSpecific(TestPlatforms.OSX)]
public void OSX_File_Move_To_Different_Watched_Directory()
{
FileMove_DifferentWatchedDirectory(WatcherChangeTypes.Changed);
}
[Fact]
[PlatformSpecific(TestPlatforms.Linux)]
public void Linux_File_Move_To_Different_Watched_Directory()
{
FileMove_DifferentWatchedDirectory(0);
}
[Fact]
public void File_Move_From_Unwatched_To_Watched()
{
FileMove_FromUnwatchedToWatched(WatcherChangeTypes.Created);
}
[Theory]
[InlineData(false)]
[InlineData(true)]
[PlatformSpecific(TestPlatforms.Windows)]
public void Windows_File_Move_In_Nested_Directory(bool includeSubdirectories)
{
FileMove_NestedDirectory(includeSubdirectories ? WatcherChangeTypes.Renamed : 0, includeSubdirectories);
}
[Theory]
[InlineData(false)]
[InlineData(true)]
[PlatformSpecific(TestPlatforms.AnyUnix)]
public void Unix_File_Move_In_Nested_Directory(bool includeSubdirectories)
{
FileMove_NestedDirectory(includeSubdirectories ? WatcherChangeTypes.Created | WatcherChangeTypes.Deleted : 0, includeSubdirectories);
}
[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
public void Windows_File_Move_With_Set_NotifyFilter()
{
FileMove_WithNotifyFilter(WatcherChangeTypes.Renamed);
}
[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)]
public void Unix_File_Move_With_Set_NotifyFilter()
{
FileMove_WithNotifyFilter(WatcherChangeTypes.Deleted);
}
#region Test Helpers
private void FileMove_SameDirectory(WatcherChangeTypes eventType)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var testFile = new TempFile(Path.Combine(dir.Path, "file")))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
string sourcePath = testFile.Path;
string targetPath = testFile.Path + "_" + eventType.ToString();
// Move the testFile to a different name in the same directory
Action action = () => File.Move(sourcePath, targetPath);
Action cleanup = () => File.Move(targetPath, sourcePath);
if ((eventType & WatcherChangeTypes.Deleted) > 0)
ExpectEvent(watcher, eventType, action, cleanup, new string[] { sourcePath, targetPath });
else
ExpectEvent(watcher, eventType, action, cleanup, targetPath);
}
}
private void FileMove_DifferentWatchedDirectory(WatcherChangeTypes eventType)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var dir_adjacent = new TempDirectory(Path.Combine(testDirectory.Path, "dir_adj")))
using (var testFile = new TempFile(Path.Combine(dir.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, "*"))
{
string sourcePath = testFile.Path;
string targetPath = Path.Combine(dir_adjacent.Path, Path.GetFileName(testFile.Path) + "_" + eventType.ToString());
// Move the testFile to a different directory under the Watcher
Action action = () => File.Move(sourcePath, targetPath);
Action cleanup = () => File.Move(targetPath, sourcePath);
ExpectEvent(watcher, eventType, action, cleanup, new string[] { dir.Path, dir_adjacent.Path });
}
}
private void FileMove_FromWatchedToUnwatched(WatcherChangeTypes eventType)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir_watched = new TempDirectory(Path.Combine(testDirectory.Path, "dir_watched")))
using (var dir_unwatched = new TempDirectory(Path.Combine(testDirectory.Path, "dir_unwatched")))
using (var testFile = new TempFile(Path.Combine(dir_watched.Path, "file")))
using (var watcher = new FileSystemWatcher(dir_watched.Path, "*"))
{
string sourcePath = testFile.Path; // watched
string targetPath = Path.Combine(dir_unwatched.Path, "file");
Action action = () => File.Move(sourcePath, targetPath);
Action cleanup = () => File.Move(targetPath, sourcePath);
ExpectEvent(watcher, eventType, action, cleanup, sourcePath);
}
}
private void FileMove_FromUnwatchedToWatched(WatcherChangeTypes eventType)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir_watched = new TempDirectory(Path.Combine(testDirectory.Path, "dir_watched")))
using (var dir_unwatched = new TempDirectory(Path.Combine(testDirectory.Path, "dir_unwatched")))
using (var testFile = new TempFile(Path.Combine(dir_unwatched.Path, "file")))
using (var watcher = new FileSystemWatcher(dir_watched.Path, "*"))
{
string sourcePath = testFile.Path; // unwatched
string targetPath = Path.Combine(dir_watched.Path, "file");
Action action = () => File.Move(sourcePath, targetPath);
Action cleanup = () => File.Move(targetPath, sourcePath);
ExpectEvent(watcher, eventType, action, cleanup, targetPath);
}
}
private void FileMove_NestedDirectory(WatcherChangeTypes eventType, bool includeSubdirectories)
{
using (var dir = new TempDirectory(GetTestFilePath()))
using (var firstDir = new TempDirectory(Path.Combine(dir.Path, "dir1")))
using (var nestedDir = new TempDirectory(Path.Combine(firstDir.Path, "nested")))
using (var nestedFile = new TempFile(Path.Combine(nestedDir.Path, "nestedFile" + eventType.ToString())))
using (var watcher = new FileSystemWatcher(dir.Path, "*"))
{
watcher.NotifyFilter = NotifyFilters.FileName;
watcher.IncludeSubdirectories = includeSubdirectories;
string sourcePath = nestedFile.Path;
string targetPath = nestedFile.Path + "_2";
// Move the testFile to a different name within the same nested directory
Action action = () => File.Move(sourcePath, targetPath);
Action cleanup = () => File.Move(targetPath, sourcePath);
if ((eventType & WatcherChangeTypes.Deleted) > 0)
ExpectEvent(watcher, eventType, action, cleanup, new string[] { targetPath, sourcePath });
else
ExpectEvent(watcher, eventType, action, cleanup, targetPath);
}
}
private void FileMove_WithNotifyFilter(WatcherChangeTypes eventType)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
{
watcher.NotifyFilter = NotifyFilters.FileName;
string sourcePath = file.Path;
string targetPath = Path.Combine(testDirectory.Path, "target");
// Move the testFile to a different name under the same directory with active notifyfilters
Action action = () => File.Move(sourcePath, targetPath);
Action cleanup = () => File.Move(targetPath, sourcePath);
if ((eventType & WatcherChangeTypes.Deleted) > 0)
ExpectEvent(watcher, eventType, action, cleanup, sourcePath);
else
ExpectEvent(watcher, eventType, action, cleanup, targetPath);
}
}
#endregion
}
}

View File

@@ -0,0 +1,285 @@
// 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.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace System.IO.Tests
{
public class File_NotifyFilter_Tests : FileSystemWatcherTest
{
[DllImport("advapi32.dll", EntryPoint = "SetNamedSecurityInfoW",
CallingConvention = CallingConvention.Winapi, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
private static extern uint SetSecurityInfoByHandle(string name, uint objectType, uint securityInformation,
IntPtr owner, IntPtr group, IntPtr dacl, IntPtr sacl);
private const uint ERROR_SUCCESS = 0;
private const uint DACL_SECURITY_INFORMATION = 0x00000004;
private const uint SE_FILE_OBJECT = 0x1;
[Theory]
[MemberData(nameof(FilterTypes))]
public void FileSystemWatcher_File_NotifyFilter_Attributes(NotifyFilters filter)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
{
watcher.NotifyFilter = filter;
var attributes = File.GetAttributes(file.Path);
Action action = () => File.SetAttributes(file.Path, attributes | FileAttributes.ReadOnly);
Action cleanup = () => File.SetAttributes(file.Path, attributes);
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.Attributes)
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && ((filter & LinuxFiltersForAttribute) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((filter & OSXFiltersForModify) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((filter & NotifyFilters.Security) > 0))
expected |= WatcherChangeTypes.Changed; // Attribute change on OSX is a ChangeOwner operation which passes the Security NotifyFilter.
ExpectEvent(watcher, expected, action, cleanup, file.Path);
}
}
[Theory]
[MemberData(nameof(FilterTypes))]
public void FileSystemWatcher_File_NotifyFilter_CreationTime(NotifyFilters filter)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
{
watcher.NotifyFilter = filter;
Action action = () => File.SetCreationTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.CreationTime)
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && ((filter & LinuxFiltersForAttribute) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((filter & OSXFiltersForModify) > 0))
expected |= WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, expectedPath: file.Path);
}
}
[Theory]
[MemberData(nameof(FilterTypes))]
public void FileSystemWatcher_File_NotifyFilter_DirectoryName(NotifyFilters filter)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(dir.Path)))
{
string sourcePath = dir.Path;
string targetPath = Path.Combine(testDirectory.Path, "targetDir");
watcher.NotifyFilter = filter;
Action action = () => Directory.Move(sourcePath, targetPath);
Action cleanup = () => Directory.Move(targetPath, sourcePath);
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.DirectoryName)
expected |= WatcherChangeTypes.Renamed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && (filter == NotifyFilters.FileName))
expected |= WatcherChangeTypes.Renamed;
ExpectEvent(watcher, expected, action, cleanup, targetPath);
}
}
[Theory]
[MemberData(nameof(FilterTypes))]
public void FileSystemWatcher_File_NotifyFilter_LastAccessTime(NotifyFilters filter)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
{
watcher.NotifyFilter = filter;
Action action = () => File.SetLastAccessTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.LastAccess)
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && ((filter & LinuxFiltersForAttribute) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((filter & OSXFiltersForModify) > 0))
expected |= WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, expectedPath: file.Path);
}
}
[Theory]
[MemberData(nameof(FilterTypes))]
public void FileSystemWatcher_File_NotifyFilter_LastWriteTime(NotifyFilters filter)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
{
watcher.NotifyFilter = filter;
Action action = () => File.SetLastWriteTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.LastWrite)
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && ((filter & LinuxFiltersForAttribute) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((filter & OSXFiltersForModify) > 0))
expected |= WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, expectedPath: file.Path);
}
}
[Theory]
[MemberData(nameof(FilterTypes))]
public void FileSystemWatcher_File_NotifyFilter_Size(NotifyFilters filter)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
{
watcher.NotifyFilter = filter;
Action action = () => File.AppendAllText(file.Path, "longText!");
Action cleanup = () => File.AppendAllText(file.Path, "short");
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.Size || filter == NotifyFilters.LastWrite)
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && ((filter & LinuxFiltersForModify) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((filter & OSXFiltersForModify) > 0))
expected |= WatcherChangeTypes.Changed;
else if (PlatformDetection.IsWindows7 && filter == NotifyFilters.Attributes) // win7 FSW Size change passes the Attribute filter
expected |= WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, expectedPath: file.Path);
}
}
[Theory]
[MemberData(nameof(FilterTypes))]
[PlatformSpecific(TestPlatforms.Windows)]
public void FileSystemWatcher_File_NotifyFilter_Security(NotifyFilters filter)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
{
watcher.NotifyFilter = filter;
Action action = () =>
{
// ACL support is not yet available, so pinvoke directly.
uint result = SetSecurityInfoByHandle(file.Path,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION, // Only setting the DACL
owner: IntPtr.Zero,
group: IntPtr.Zero,
dacl: IntPtr.Zero, // full access to everyone
sacl: IntPtr.Zero);
Assert.Equal(ERROR_SUCCESS, result);
};
Action cleanup = () =>
{
// Recreate the file.
File.Delete(file.Path);
File.AppendAllText(file.Path, "text");
};
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.Security)
expected |= WatcherChangeTypes.Changed;
else if (PlatformDetection.IsWindows7 && filter == NotifyFilters.Attributes) // win7 FSW Security change passes the Attribute filter
expected |= WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, expectedPath: file.Path);
}
}
/// <summary>
/// Tests a changed event on a directory when filtering for LastWrite and FileName.
/// </summary>
[Fact]
public void FileSystemWatcher_File_NotifyFilter_LastWriteAndFileName()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(dir.Path)))
{
NotifyFilters filter = NotifyFilters.LastWrite | NotifyFilters.FileName;
watcher.NotifyFilter = filter;
Action action = () => Directory.SetLastWriteTime(dir.Path, DateTime.Now + TimeSpan.FromSeconds(10));
ExpectEvent(watcher, WatcherChangeTypes.Changed, action, expectedPath: dir.Path);
}
}
/// <summary>
/// Tests the watcher behavior when two events - a Modification and a Creation - happen closely
/// after each other.
/// </summary>
[Fact]
public void FileSystemWatcher_File_NotifyFilter_ModifyAndCreate()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, "*"))
{
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;
string otherFile = Path.Combine(testDirectory.Path, "file2");
Action action = () =>
{
File.Create(otherFile).Dispose();
File.SetLastWriteTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
};
Action cleanup = () => File.Delete(otherFile);
WatcherChangeTypes expected = 0;
expected |= WatcherChangeTypes.Created | WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, cleanup, new string[] { otherFile, file.Path });
}
}
/// <summary>
/// Tests the watcher behavior when two events - a Modification and a Deletion - happen closely
/// after each other.
/// </summary>
[Fact]
public void FileSystemWatcher_File_NotifyFilter_ModifyAndDelete()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, "*"))
{
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;
string otherFile = Path.Combine(testDirectory.Path, "file2");
Action action = () =>
{
File.Delete(otherFile);
File.SetLastWriteTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
};
Action cleanup = () =>
{
File.Create(otherFile).Dispose();
};
cleanup();
WatcherChangeTypes expected = 0;
expected |= WatcherChangeTypes.Deleted | WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, cleanup, new string[] { otherFile, file.Path });
}
}
}
}

View File

@@ -0,0 +1,83 @@
// 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.Threading;
using Xunit;
namespace System.IO.Tests
{
public class InternalBufferSizeTests : FileSystemWatcherTest
{
// FSW works by calling ReadDirectoryChanges asynchronously, processing the changes
// in the callback and invoking event handlers from the callback serially.
// After it processes all events for a particular callback it calls ReadDirectoryChanges
// to queue another overlapped operation.
// PER MSDN:
// When you first call ReadDirectoryChangesW, the system allocates a buffer to store change
// information. This buffer is associated with the directory handle until it is closed and
// its size does not change during its lifetime. Directory changes that occur between calls
// to this function are added to the buffer and then returned with the next call. If the
// buffer overflows, the entire contents of the buffer are discarded, the lpBytesReturned
// parameter contains zero, and the ReadDirectoryChangesW function fails with the error
// code ERROR_NOTIFY_ENUM_DIR.
// We can force the error by increasing the amount of time between calls to ReadDirectoryChangesW
// By blocking in an event handler, we allow the main thread of our test to generate a ton
// of change events and overflow the OS's buffer.
// We could copy the result of the operation and immediately call ReadDirectoryChangesW to
// limit the amount of time where we rely on the OS's buffer. The downside of doing so
// is it can allow memory to grow out of control.
// FSW tries to mitigate this by exposing InternalBufferSize. The OS uses this when allocating
// it's internal buffer (up to some limit). Our docs say that limit is 64KB but testing on Win8.1
// indicates that it is much higher than this: I could grow the buffer up to 128 MB and still see
// that it had an effect. The size needed per operation is determined by the struct layout of
// FILE_NOTIFY_INFORMATION. This works out to 16 + 2 * (Path.GetFileName(file.Path).Length + 1) bytes, where filePath
// is the path to changed file relative to the path passed into ReadDirectoryChanges.
// At some point we might decide to improve how FSW handles this at which point we'll need
// a better test for Error (perhaps just a mock), but for now there is some value in forcing this limit.
[Theory]
[InlineData(true)]
[InlineData(false)]
[PlatformSpecific(TestPlatforms.Windows)]
public void FileSystemWatcher_InternalBufferSize(bool setToHigherCapacity)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
{
int internalBufferOperationCapacity = watcher.InternalBufferSize / (17 + Path.GetFileName(file.Path).Length);
// Set the capacity high to ensure no error events arise.
if (setToHigherCapacity)
watcher.InternalBufferSize = watcher.InternalBufferSize * 12;
// block the handling thread
ManualResetEvent unblockHandler = new ManualResetEvent(false);
watcher.Changed += (o, e) =>
{
unblockHandler.WaitOne();
};
// generate enough file change events to overflow the default buffer
Action action = () =>
{
for (int i = 1; i < internalBufferOperationCapacity * 10; i++)
{
File.SetLastWriteTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(i));
}
unblockHandler.Set();
};
Action cleanup = () => unblockHandler.Reset();
if (setToHigherCapacity)
ExpectNoError(watcher, action, cleanup);
else
ExpectError(watcher, action, cleanup);
}
}
}
}

View File

@@ -0,0 +1,217 @@
// 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.Threading.Tasks;
using Xunit;
namespace System.IO.Tests
{
public partial class WaitForChangedTests : FileSystemWatcherTest
{
private const int BetweenOperationsDelayMilliseconds = 100;
[Fact]
public static void WaitForChangedResult_DefaultValues()
{
var result = new WaitForChangedResult();
Assert.Equal((WatcherChangeTypes)0, result.ChangeType);
Assert.Null(result.Name);
Assert.Null(result.OldName);
Assert.False(result.TimedOut);
}
[Theory]
[InlineData(WatcherChangeTypes.All)]
[InlineData(WatcherChangeTypes.Changed)]
[InlineData(WatcherChangeTypes.Created)]
[InlineData(WatcherChangeTypes.Deleted)]
[InlineData(WatcherChangeTypes.Renamed)]
[InlineData(WatcherChangeTypes.Changed | WatcherChangeTypes.Created)]
[InlineData(WatcherChangeTypes.Deleted | WatcherChangeTypes.Renamed)]
[InlineData((WatcherChangeTypes)0)]
[InlineData((WatcherChangeTypes)int.MinValue)]
[InlineData((WatcherChangeTypes)int.MaxValue)]
[InlineData((WatcherChangeTypes)int.MaxValue)]
public static void WaitForChangedResult_ChangeType_Roundtrip(WatcherChangeTypes changeType)
{
var result = new WaitForChangedResult();
result.ChangeType = changeType;
Assert.Equal(changeType, result.ChangeType);
}
[Theory]
[InlineData("")]
[InlineData("myfile.txt")]
[InlineData(" ")]
[InlineData(" myfile.txt ")]
public static void WaitForChangedResult_Name_Roundtrip(string name)
{
var result = new WaitForChangedResult();
result.Name = name;
Assert.Equal(name, result.Name);
}
[Theory]
[InlineData("")]
[InlineData("myfile.txt")]
[InlineData(" ")]
[InlineData(" myfile.txt ")]
public static void WaitForChangedResult_OldName_Roundtrip(string name)
{
var result = new WaitForChangedResult();
result.OldName = name;
Assert.Equal(name, result.OldName);
}
[Theory]
public static void WaitForChangedResult_TimedOut_Roundtrip()
{
var result = new WaitForChangedResult();
result.TimedOut = true;
Assert.True(result.TimedOut);
result.TimedOut = false;
Assert.False(result.TimedOut);
result.TimedOut = true;
Assert.True(result.TimedOut);
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void ZeroTimeout_TimesOut(bool enabledBeforeWait)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, GetTestFileName())))
using (var fsw = new FileSystemWatcher(testDirectory.Path))
{
if (enabledBeforeWait) fsw.EnableRaisingEvents = true;
AssertTimedOut(fsw.WaitForChanged(WatcherChangeTypes.All, 0));
Assert.Equal(enabledBeforeWait, fsw.EnableRaisingEvents);
}
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void NonZeroTimeout_NoEvents_TimesOut(bool enabledBeforeWait)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, GetTestFileName())))
using (var fsw = new FileSystemWatcher(testDirectory.Path))
{
if (enabledBeforeWait) fsw.EnableRaisingEvents = true;
AssertTimedOut(fsw.WaitForChanged(0, 1));
Assert.Equal(enabledBeforeWait, fsw.EnableRaisingEvents);
}
}
[Theory]
[InlineData(WatcherChangeTypes.Deleted, false)]
[InlineData(WatcherChangeTypes.Created, true)]
[InlineData(WatcherChangeTypes.Changed, false)]
[InlineData(WatcherChangeTypes.Renamed, true)]
[InlineData(WatcherChangeTypes.All, true)]
public void NonZeroTimeout_NoActivity_TimesOut(WatcherChangeTypes changeType, bool enabledBeforeWait)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, GetTestFileName())))
using (var fsw = new FileSystemWatcher(testDirectory.Path))
{
if (enabledBeforeWait) fsw.EnableRaisingEvents = true;
AssertTimedOut(fsw.WaitForChanged(changeType, 1));
Assert.Equal(enabledBeforeWait, fsw.EnableRaisingEvents);
}
}
[Theory]
[OuterLoop("This test has a longer than average timeout and may fail intermittently")]
[InlineData(WatcherChangeTypes.Created)]
[InlineData(WatcherChangeTypes.Deleted)]
public void CreatedDeleted_Success(WatcherChangeTypes changeType)
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var fsw = new FileSystemWatcher(testDirectory.Path))
{
Task<WaitForChangedResult> t = Task.Run(() => fsw.WaitForChanged(changeType, LongWaitTimeout));
while (!t.IsCompleted)
{
string path = Path.Combine(testDirectory.Path, Path.GetRandomFileName());
File.WriteAllText(path, "text");
Task.Delay(BetweenOperationsDelayMilliseconds).Wait();
if ((changeType & WatcherChangeTypes.Deleted) != 0)
{
File.Delete(path);
}
}
Assert.Equal(TaskStatus.RanToCompletion, t.Status);
Assert.Equal(changeType, t.Result.ChangeType);
Assert.NotNull(t.Result.Name);
Assert.Null(t.Result.OldName);
Assert.False(t.Result.TimedOut);
}
}
[Fact]
[OuterLoop("This test has a longer than average timeout and may fail intermittently")]
public void Changed_Success()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var fsw = new FileSystemWatcher(testDirectory.Path))
{
string name = Path.Combine(testDirectory.Path, Path.GetRandomFileName());
File.Create(name).Dispose();
Task<WaitForChangedResult> t = Task.Run(() => fsw.WaitForChanged(WatcherChangeTypes.Changed, LongWaitTimeout));
while (!t.IsCompleted)
{
File.AppendAllText(name, "text");
Task.Delay(BetweenOperationsDelayMilliseconds).Wait();
}
Assert.Equal(TaskStatus.RanToCompletion, t.Status);
Assert.Equal(WatcherChangeTypes.Changed, t.Result.ChangeType);
Assert.NotNull(t.Result.Name);
Assert.Null(t.Result.OldName);
Assert.False(t.Result.TimedOut);
}
}
[Fact]
[OuterLoop("This test has a longer than average timeout and may fail intermittently")]
public void Renamed_Success()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var fsw = new FileSystemWatcher(testDirectory.Path))
{
Task<WaitForChangedResult> t = Task.Run(() =>
fsw.WaitForChanged(WatcherChangeTypes.Renamed | WatcherChangeTypes.Created, LongWaitTimeout)); // on some OSes, the renamed might come through as Deleted/Created
string name = Path.Combine(testDirectory.Path, Path.GetRandomFileName());
File.Create(name).Dispose();
while (!t.IsCompleted)
{
string newName = Path.Combine(testDirectory.Path, Path.GetRandomFileName());
File.Move(name, newName);
name = newName;
Task.Delay(BetweenOperationsDelayMilliseconds).Wait();
}
Assert.Equal(TaskStatus.RanToCompletion, t.Status);
Assert.True(t.Result.ChangeType == WatcherChangeTypes.Created || t.Result.ChangeType == WatcherChangeTypes.Renamed);
Assert.NotNull(t.Result.Name);
Assert.False(t.Result.TimedOut);
}
}
private static void AssertTimedOut(WaitForChangedResult result)
{
Assert.Equal(0, (int)result.ChangeType);
Assert.Null(result.Name);
Assert.Null(result.OldName);
Assert.True(result.TimedOut);
}
}
}

View File

@@ -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);
}
}
/// <summary>
/// When the FSW Site is set to a nonnull Site with DesignMode enabled, Event raising will be set to true
/// </summary>
[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);
}
}
/// <summary>
/// Ensure that the SynchronizeObject is invoked when an event occurs
/// </summary>
[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);
}
}
/// <summary>
/// Ensure that the SynchronizeObject is invoked when an Renamed event occurs
/// </summary>
[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);
}
}
/// <summary>
/// Ensure that the SynchronizeObject is invoked when an Error event occurs
/// </summary>
[Fact]
public void SynchronizingObject_CalledOnError()
{
ErrorEventHandler dele = (sender, e) => { Assert.IsType<FileNotFoundException>(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);
}
}
/// <summary>
/// Calling BeginInit and EndInit in a loop is fine. If events are enabled, they will start and stop in the loop as well.
/// </summary>
[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);
}
}
/// <summary>
/// BeginInit followed by a EnableRaisingEvents=true does not cause the watcher to begin.
/// </summary>
[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);
}
}
/// <summary>
/// EndInit will begin EnableRaisingEvents if we previously set EnableRaisingEvents=true
/// </summary>
[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);
}
}
/// <summary>
/// EndInit will begin EnableRaisingEvents if we previously set EnableRaisingEvents=true
/// </summary>
[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);
}
}
/// <summary>
/// Stopping events during the initialization period will prevent the watcher from restarting after EndInit()
/// </summary>
[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);
}
}
/// <summary>
/// EndInit will not start event raising unless EnableRaisingEvents was set to true.
/// </summary>
[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);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
// 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 Xunit;
using System.Runtime.Serialization.Formatters.Tests;
namespace System.IO.Tests
{
public static class InternalBufferOverflowExceptionTests
{
[Fact]
public static void DefaultConstructor()
{
InternalBufferOverflowException ide = new InternalBufferOverflowException();
Assert.NotNull(ide.Message);
}
[Fact]
public static void MessageConstructor()
{
string message = "MessageConstructor";
InternalBufferOverflowException ide = new InternalBufferOverflowException(message);
Assert.Equal(message, ide.Message);
}
[Fact]
public static void MessageInnerExceptionConstructor()
{
string message = "MessageConstructor";
Exception innerException = new Exception();
InternalBufferOverflowException ide = new InternalBufferOverflowException(message, innerException);
Assert.Equal(message, ide.Message);
Assert.Same(innerException, ide.InnerException);
}
[Fact]
public static void ExceptionRoundtrips()
{
BinaryFormatterHelpers.AssertRoundtrips(new InternalBufferOverflowException());
}
}
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<Project Include="System.IO.FileSystem.Watcher.Tests.csproj">
<OSGroup>Linux</OSGroup>
</Project>
<Project Include="System.IO.FileSystem.Watcher.Tests.csproj">
<OSGroup>OSX</OSGroup>
</Project>
<Project Include="System.IO.FileSystem.Watcher.Tests.csproj">
<OSGroup>Windows_NT</OSGroup>
</Project>
<Project Include="System.IO.FileSystem.Watcher.Tests.csproj">
<TargetGroup>netstandard1.3</TargetGroup>
<OSGroup>Linux</OSGroup>
<TestTFMs>netcoreapp1.0</TestTFMs>
</Project>
<Project Include="System.IO.FileSystem.Watcher.Tests.csproj">
<TargetGroup>netstandard1.3</TargetGroup>
<OSGroup>OSX</OSGroup>
<TestTFMs>netcoreapp1.0</TestTFMs>
</Project>
<Project Include="System.IO.FileSystem.Watcher.Tests.csproj">
<TargetGroup>netstandard1.3</TargetGroup>
<OSGroup>Windows_NT</OSGroup>
<TestTFMs>netcoreapp1.0;net46</TestTFMs>
</Project>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
</Project>

Some files were not shown because too many files have changed in this diff Show More