diff --git a/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj b/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj index c813f682fa406d..591fd42da884b0 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj +++ b/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj @@ -25,10 +25,12 @@ - - + + + Combines a directory path and a relative file name into a single path. - /// The directory path. - /// The file name. - /// The combined name. - /// - /// This is like Path.Combine, except without argument validation, - /// and a separator is used even if the name argument is empty. - /// - internal static string Combine(string directoryPath, string? name) - { - bool hasSeparator = false; - if (directoryPath.Length > 0) + if (string.IsNullOrWhiteSpace(name)) { - char c = directoryPath[directoryPath.Length - 1]; - hasSeparator = c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar; + _fullPath = PathInternal.EnsureTrailingSeparator(_fullPath); } - - return hasSeparator ? - directoryPath + name : - directoryPath + Path.DirectorySeparatorChar + name; } /// diff --git a/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/RenamedEventArgs.cs b/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/RenamedEventArgs.cs index 9d254e0c1f5760..72dc9765f05fb4 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/RenamedEventArgs.cs +++ b/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/RenamedEventArgs.cs @@ -18,7 +18,12 @@ public RenamedEventArgs(WatcherChangeTypes changeType, string directory, string? : base(changeType, directory, name) { _oldName = oldName; - _oldFullPath = Combine(directory, oldName); + _oldFullPath = Path.Join(Path.GetFullPath(directory), oldName); + + if (string.IsNullOrWhiteSpace(oldName)) + { + _oldFullPath = PathInternal.EnsureTrailingSeparator(_oldFullPath); + } } /// diff --git a/src/libraries/System.IO.FileSystem.Watcher/tests/Args.FileSystemEventArgs.cs b/src/libraries/System.IO.FileSystem.Watcher/tests/Args.FileSystemEventArgs.cs index 7a6bf743653e12..16c731a9489085 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/tests/Args.FileSystemEventArgs.cs +++ b/src/libraries/System.IO.FileSystem.Watcher/tests/Args.FileSystemEventArgs.cs @@ -8,28 +8,89 @@ namespace System.IO.Tests public class FileSystemEventArgsTests { [Theory] - [InlineData(WatcherChangeTypes.Changed, "C:", "foo.txt")] - [InlineData(WatcherChangeTypes.All, "C:", "foo.txt")] - [InlineData((WatcherChangeTypes)0, "", "")] - [InlineData((WatcherChangeTypes)0, "", null)] - public static void FileSystemEventArgs_ctor(WatcherChangeTypes changeType, string directory, string name) + [InlineData(WatcherChangeTypes.Changed, "bar", "foo.txt")] + [InlineData(WatcherChangeTypes.All, "bar", "foo.txt")] + [InlineData((WatcherChangeTypes)0, "bar", "")] + [InlineData((WatcherChangeTypes)0, "bar", null)] + public static void FileSystemEventArgs_ctor_NonPathPropertiesAreSetCorrectly(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); } + [Theory] + [PlatformSpecific(TestPlatforms.Windows)] + [InlineData("D:\\", "foo.txt", "D:\\foo.txt")] + [InlineData("E:\\bar", "foo.txt", "E:\\bar\\foo.txt")] + public static void FileSystemEventArgs_ctor_DirectoryIsAbsolutePath_Windows(string directory, string name, string expectedFullPath) + { + FileSystemEventArgs args = new FileSystemEventArgs(WatcherChangeTypes.All, directory, name); + + Assert.Equal(expectedFullPath, args.FullPath); + } + + [Theory] + [PlatformSpecific(TestPlatforms.AnyUnix)] + [InlineData("/", "foo.txt", "/foo.txt")] + [InlineData("/bar", "foo.txt", "/bar/foo.txt")] + public static void FileSystemEventArgs_ctor_DirectoryIsAbsolutePath_Unix(string directory, string name, string expectedFullPath) + { + FileSystemEventArgs args = new FileSystemEventArgs(WatcherChangeTypes.All, directory, name); + + Assert.Equal(expectedFullPath, args.FullPath); + } + + [Theory] + [PlatformSpecific(TestPlatforms.Windows)] + [InlineData("bar", "foo.txt")] + [InlineData("bar\\baz", "foo.txt")] + public static void FileSystemEventArgs_ctor_DirectoryIsRelativePath_Windows(string directory, string name) + { + FileSystemEventArgs args = new FileSystemEventArgs(WatcherChangeTypes.All, directory, name); + + Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), directory, name), args.FullPath); + } + + [Theory] + [PlatformSpecific(TestPlatforms.AnyUnix)] + [InlineData("bar", "foo.txt")] + [InlineData("bar/baz", "foo.txt")] + public static void FileSystemEventArgs_ctor_DirectoryIsRelativePath_Unix(string directory, string name) + { + FileSystemEventArgs args = new FileSystemEventArgs(WatcherChangeTypes.All, directory, name); + + Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), directory, name), args.FullPath); + } + + [Theory] + [PlatformSpecific(TestPlatforms.Windows)] + [InlineData("C:", "foo.txt")] + public static void FileSystemEventArgs_ctor_RelativePathFromCurrentDirectoryInGivenDrive(string directory, string name) + { + FileSystemEventArgs args = new FileSystemEventArgs(WatcherChangeTypes.All, directory, name); + + Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), name), args.FullPath); + } + + [Theory] + [InlineData("bar", "")] + [InlineData("bar", null)] + public static void FileSystemEventArgs_ctor_When_EmptyFileName_Then_FullPathReturnsTheDirectoryFullPath_WithTrailingSeparator(string directory, string name) + { + FileSystemEventArgs args = new FileSystemEventArgs(WatcherChangeTypes.All, directory, name); + + directory = PathInternal.EnsureTrailingSeparator(directory); + + Assert.Equal(PathInternal.EnsureTrailingSeparator(Directory.GetCurrentDirectory()) + directory, args.FullPath); + } + [Fact] public static void FileSystemEventArgs_ctor_Invalid() { - Assert.Throws(() => new FileSystemEventArgs((WatcherChangeTypes)0, null, string.Empty)); + Assert.Throws(() => new FileSystemEventArgs((WatcherChangeTypes)0, null, "foo.txt")); + Assert.Throws(() => new FileSystemEventArgs((WatcherChangeTypes)0, "", "foo.txt")); } } } diff --git a/src/libraries/System.IO.FileSystem.Watcher/tests/Args.RenamedEventArgs.cs b/src/libraries/System.IO.FileSystem.Watcher/tests/Args.RenamedEventArgs.cs index 392c22cf1abe2f..d15ec08d7e9376 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/tests/Args.RenamedEventArgs.cs +++ b/src/libraries/System.IO.FileSystem.Watcher/tests/Args.RenamedEventArgs.cs @@ -8,34 +8,93 @@ 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((WatcherChangeTypes)0, "", "", "")] - [InlineData((WatcherChangeTypes)0, "", null, null)] - public static void RenamedEventArgs_ctor(WatcherChangeTypes changeType, string directory, string name, string oldName) + [InlineData(WatcherChangeTypes.Changed, "bar", "foo.txt", "bar.txt")] + [InlineData(WatcherChangeTypes.All, "bar", "foo.txt", "bar.txt")] + [InlineData((WatcherChangeTypes)0, "bar", "", "")] + [InlineData((WatcherChangeTypes)0, "bar", null, null)] + public static void RenamedEventArgs_ctor_NonPathPropertiesAreSetCorrectly(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); + + // FullPath is tested as part of the base class FileSystemEventArgs tests } [Theory] - [InlineData(WatcherChangeTypes.Changed, "C:", "foo.txt", "bar.txt")] - [InlineData(WatcherChangeTypes.All, "C:", "foo.txt", "bar.txt")] - [InlineData((WatcherChangeTypes)0, "", "", "")] - [InlineData((WatcherChangeTypes)0, "", null, null)] - public static void RenamedEventArgs_ctor_OldFullPath(WatcherChangeTypes changeType, string directory, string name, string oldName) + [PlatformSpecific(TestPlatforms.Windows)] + [InlineData("D:\\", "foo.txt", "bar.txt", "D:\\bar.txt")] + [InlineData("E:\\bar", "foo.txt", "bar.txt", "E:\\bar\\bar.txt")] + public static void RenamedEventArgs_ctor_OldFullPath_DirectoryIsAnAbsolutePath_Windows(string directory, string name, string oldName, string expectedOldFullPath) { - RenamedEventArgs args = new RenamedEventArgs(changeType, directory, name, oldName); - Assert.Equal(directory + Path.DirectorySeparatorChar + oldName, args.OldFullPath); + RenamedEventArgs args = new RenamedEventArgs(WatcherChangeTypes.All, directory, name, oldName); + + Assert.Equal(expectedOldFullPath, args.OldFullPath); + } + + [Theory] + [PlatformSpecific(TestPlatforms.AnyUnix)] + [InlineData("/", "foo.txt", "bar.txt", "/bar.txt")] + [InlineData("/bar", "foo.txt", "bar.txt", "/bar/bar.txt")] + public static void RenamedEventArgs_ctor_OldFullPath_DirectoryIsAnAbsolutePath_Unix(string directory, string name, string oldName, string expectedOldFullPath) + { + RenamedEventArgs args = new RenamedEventArgs(WatcherChangeTypes.All, directory, name, oldName); + + Assert.Equal(expectedOldFullPath, args.OldFullPath); + } + + [Theory] + [PlatformSpecific(TestPlatforms.Windows)] + [InlineData("bar", "foo.txt", "bar.txt")] + [InlineData("bar\\baz", "foo.txt", "bar.txt")] + public static void RenamedEventArgs_ctor_OldFullPath_DirectoryIsRelativePath_Windows(string directory, string name, string oldName) + { + RenamedEventArgs args = new RenamedEventArgs(WatcherChangeTypes.All, directory, name, oldName); + + Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), directory, oldName), args.OldFullPath); + } + + [Theory] + [PlatformSpecific(TestPlatforms.AnyUnix)] + [InlineData("bar", "foo.txt", "bar.txt")] + [InlineData("bar/baz", "foo.txt", "bar.txt")] + public static void RenamedEventArgs_ctor_OldFullPath_DirectoryIsRelativePath_Unix(string directory, string name, string oldName) + { + RenamedEventArgs args = new RenamedEventArgs(WatcherChangeTypes.All, directory, name, oldName); + + Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), directory, oldName), args.OldFullPath); + } + + [Theory] + [PlatformSpecific(TestPlatforms.Windows)] + [InlineData("C:", "foo.txt", "bar.txt")] + public static void RenamedEventArgs_ctor_OldFullPath_DirectoryIsRelativePathFromCurrentDirectoryInGivenDrive(string directory, string name, string oldName) + { + RenamedEventArgs args = new RenamedEventArgs(WatcherChangeTypes.All, directory, name, oldName); + + Assert.Equal(Path.Combine(Directory.GetCurrentDirectory(), oldName), args.OldFullPath); + } + + [Theory] + [InlineData("bar", "", "")] + [InlineData("bar", null, null)] + [InlineData("bar", "foo.txt", null)] + public static void RenamedEventArgs_ctor_When_EmptyOldFileName_Then_OldFullPathReturnsTheDirectoryFullPath_WithTrailingSeparator(string directory, string name, string oldName) + { + RenamedEventArgs args = new RenamedEventArgs(WatcherChangeTypes.All, directory, name, oldName); + + directory = PathInternal.EnsureTrailingSeparator(directory); + + Assert.Equal(PathInternal.EnsureTrailingSeparator(Directory.GetCurrentDirectory()) + directory, args.OldFullPath); } [Fact] public static void RenamedEventArgs_ctor_Invalid() { - Assert.Throws(() => new RenamedEventArgs((WatcherChangeTypes)0, null, string.Empty, string.Empty)); + Assert.Throws(() => new RenamedEventArgs((WatcherChangeTypes)0, "", "foo.txt", "bar.txt")); + Assert.Throws(() => new RenamedEventArgs((WatcherChangeTypes)0, null, "foo.txt", "bar.txt")); } } } diff --git a/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj b/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj index f7185093a21c14..9ebfaa1af53961 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj +++ b/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj @@ -1,4 +1,4 @@ - + true true @@ -39,6 +39,18 @@ Link="Common\System\IO\ReparsePointUtilities.cs" /> + + + + + + + +