From 97566d745d0848fef0d68b6820229595f977ae1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Sun, 16 Apr 2023 13:26:00 +0200 Subject: [PATCH 1/7] Throw correct exception when creating a directory when a file with the same name already exists. --- .../FileSystem/DirectoryInfoMock.cs | 5 +++++ .../Directory/CreateDirectoryTests.cs | 15 +++++++++++++++ .../DirectoryInfo/CreateSubdirectoryTests.cs | 19 +++++++++++++++++++ .../FileSystem/DirectoryInfo/CreateTests.cs | 18 ++++++++++++++++++ 4 files changed, 57 insertions(+) diff --git a/Source/Testably.Abstractions.Testing/FileSystem/DirectoryInfoMock.cs b/Source/Testably.Abstractions.Testing/FileSystem/DirectoryInfoMock.cs index d0d9cd91a..3f61852c0 100644 --- a/Source/Testably.Abstractions.Testing/FileSystem/DirectoryInfoMock.cs +++ b/Source/Testably.Abstractions.Testing/FileSystem/DirectoryInfoMock.cs @@ -46,6 +46,11 @@ public void Create() InMemoryContainer.NewDirectory, this); + if (Container.Type != FileSystemTypes.Directory) + { + throw ExceptionFactory.CannotCreateFileAsAlreadyExists(FullName); + } + ResetCache(!Execute.IsNetFramework); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/CreateDirectoryTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/CreateDirectoryTests.cs index 9c31d6dc7..018672478 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/CreateDirectoryTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/CreateDirectoryTests.cs @@ -50,6 +50,21 @@ public void CreateDirectory_ReadOnlyParent_ShouldStillCreateDirectory(string par } } + [SkippableTheory] + [AutoData] + public void CreateDirectory_FileWithSameNameAlreadyExists_ShouldThrowIOException(string name) + { + FileSystem.File.WriteAllText(name, ""); + + Exception? exception = Record.Exception(() => + { + FileSystem.Directory.CreateDirectory(name); + }); + + exception.Should().BeException(hResult: -2147024713); + FileSystem.Directory.Exists(name).Should().BeFalse(); + } + [SkippableFact] public void CreateDirectory_Root_ShouldNotThrowException() { diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateSubdirectoryTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateSubdirectoryTests.cs index 37d184e4a..240e7fa18 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateSubdirectoryTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateSubdirectoryTests.cs @@ -1,3 +1,5 @@ +using System.IO; + namespace Testably.Abstractions.Tests.FileSystem.DirectoryInfo; // ReSharper disable once PartialTypeWithSinglePart @@ -5,6 +7,23 @@ public abstract partial class CreateSubdirectoryTests : FileSystemTestBase where TFileSystem : IFileSystem { + [SkippableTheory] + [AutoData] + public void CreateSubdirectory_FileWithSameNameAlreadyExists_ShouldThrowIOException( + string name) + { + FileSystem.File.WriteAllText(name, ""); + IDirectoryInfo sut = FileSystem.DirectoryInfo.New("."); + + Exception? exception = Record.Exception(() => + { + sut.CreateSubdirectory(name); + }); + + exception.Should().BeException(hResult: -2147024713); + FileSystem.Directory.Exists(name).Should().BeFalse(); + } + [SkippableTheory] [AutoData] public void CreateSubdirectory_MissingParent_ShouldCreateDirectory( diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateTests.cs index 537779a61..525bd680f 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateTests.cs @@ -1,3 +1,5 @@ +using System.IO; + namespace Testably.Abstractions.Tests.FileSystem.DirectoryInfo; // ReSharper disable once PartialTypeWithSinglePart @@ -5,6 +7,22 @@ public abstract partial class CreateTests : FileSystemTestBase where TFileSystem : IFileSystem { + [SkippableTheory] + [AutoData] + public void Create_FileWithSameNameAlreadyExists_ShouldThrowIOException(string name) + { + FileSystem.File.WriteAllText(name, ""); + IDirectoryInfo sut = FileSystem.DirectoryInfo.New(name); + + Exception? exception = Record.Exception(() => + { + sut.Create(); + }); + + exception.Should().BeException(hResult: -2147024713); + FileSystem.Directory.Exists(name).Should().BeFalse(); + } + [SkippableTheory] [AutoData] public void Create_ShouldCreateDirectory(string path) From a9950eb76145f0113bd961eaf0c71d768759483c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Sun, 16 Apr 2023 15:20:44 +0200 Subject: [PATCH 2/7] Test for correct hresult --- .../FileSystem/Directory/CreateDirectoryTests.cs | 3 ++- .../FileSystem/DirectoryInfo/CreateSubdirectoryTests.cs | 3 ++- .../FileSystem/DirectoryInfo/CreateTests.cs | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/CreateDirectoryTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/CreateDirectoryTests.cs index 018672478..05c9051e4 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/CreateDirectoryTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/CreateDirectoryTests.cs @@ -61,7 +61,8 @@ public void CreateDirectory_FileWithSameNameAlreadyExists_ShouldThrowIOException FileSystem.Directory.CreateDirectory(name); }); - exception.Should().BeException(hResult: -2147024713); + exception.Should().BeException( + hResult: Test.RunsOnWindows ? -2147024713 : 17); FileSystem.Directory.Exists(name).Should().BeFalse(); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateSubdirectoryTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateSubdirectoryTests.cs index 240e7fa18..adfc8e2a7 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateSubdirectoryTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateSubdirectoryTests.cs @@ -20,7 +20,8 @@ public void CreateSubdirectory_FileWithSameNameAlreadyExists_ShouldThrowIOExcept sut.CreateSubdirectory(name); }); - exception.Should().BeException(hResult: -2147024713); + exception.Should().BeException( + hResult: Test.RunsOnWindows ? -2147024713 : 17); FileSystem.Directory.Exists(name).Should().BeFalse(); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateTests.cs index 525bd680f..eada3313f 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateTests.cs @@ -19,7 +19,8 @@ public void Create_FileWithSameNameAlreadyExists_ShouldThrowIOException(string n sut.Create(); }); - exception.Should().BeException(hResult: -2147024713); + exception.Should().BeException( + hResult: Test.RunsOnWindows ? -2147024713 : 17); FileSystem.Directory.Exists(name).Should().BeFalse(); } From 8d97384c20c1e21585387729ae92e49e0c0f8f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Sun, 16 Apr 2023 15:45:36 +0200 Subject: [PATCH 3/7] Add tests for throwing correct exception when writing a file under a name where a directory already exists. --- .../FileSystem/FileMock.cs | 57 +++++++++++++------ .../File/AppendAllLinesAsyncTests.cs | 19 +++++++ .../FileSystem/File/AppendAllLinesTests.cs | 19 +++++++ .../File/AppendAllTextAsyncTests.cs | 19 +++++++ .../FileSystem/File/AppendAllTextTests.cs | 35 +++++++++--- .../File/WriteAllBytesAsyncTests.cs | 19 +++++++ .../FileSystem/File/WriteAllBytesTests.cs | 27 +++++++-- .../File/WriteAllLinesAsyncTests.cs | 19 +++++++ .../FileSystem/File/WriteAllLinesTests.cs | 29 ++++++++-- .../FileSystem/File/WriteAllTextAsyncTests.cs | 19 +++++++ .../FileSystem/File/WriteAllTextTests.cs | 18 ++++++ 11 files changed, 247 insertions(+), 33 deletions(-) diff --git a/Source/Testably.Abstractions.Testing/FileSystem/FileMock.cs b/Source/Testably.Abstractions.Testing/FileSystem/FileMock.cs index 870d08683..bfdaa0a5b 100644 --- a/Source/Testably.Abstractions.Testing/FileSystem/FileMock.cs +++ b/Source/Testably.Abstractions.Testing/FileSystem/FileMock.cs @@ -12,6 +12,7 @@ #if FEATURE_FILESYSTEM_ASYNC using System.Threading; using System.Threading.Tasks; + #endif namespace Testably.Abstractions.Testing.FileSystem; @@ -73,23 +74,29 @@ public void AppendAllText(string path, string? contents) /// public void AppendAllText(string path, string? contents, Encoding encoding) { - IStorageContainer fileInfo = + IStorageContainer container = _fileSystem.Storage.GetOrCreateContainer( _fileSystem.Storage.GetLocation( path.EnsureValidFormat(FileSystem)), InMemoryContainer.NewFile); + + if (container.Type != FileSystemTypes.File) + { + throw ExceptionFactory.AccessToPathDenied(path); + } + if (contents != null) { - using (fileInfo.RequestAccess( + using (container.RequestAccess( FileAccess.ReadWrite, FileStreamFactoryMock.DefaultShare)) { - if (fileInfo.GetBytes().Length == 0) + if (container.GetBytes().Length == 0) { - fileInfo.WriteBytes(encoding.GetPreamble()); + container.WriteBytes(encoding.GetPreamble()); } - fileInfo.AppendBytes(encoding.GetBytes(contents)); + container.AppendBytes(encoding.GetBytes(contents)); } } } @@ -786,17 +793,25 @@ public void WriteAllBytes(string path, byte[] bytes) _fileSystem.Storage.GetLocation( path.EnsureValidFormat(FileSystem)), InMemoryContainer.NewFile); - if (container is not NullContainer) + + if (container is NullContainer) { - Execute.OnWindowsIf( - container.Attributes.HasFlag(FileAttributes.Hidden), - () => throw ExceptionFactory.AccessToPathDenied()); - using (container.RequestAccess( - FileAccess.Write, - FileStreamFactoryMock.DefaultShare)) - { - container.WriteBytes(bytes); - } + return; + } + + if (container.Type != FileSystemTypes.File) + { + throw ExceptionFactory.AccessToPathDenied(path); + } + + Execute.OnWindowsIf( + container.Attributes.HasFlag(FileAttributes.Hidden), + () => throw ExceptionFactory.AccessToPathDenied()); + using (container.RequestAccess( + FileAccess.Write, + FileStreamFactoryMock.DefaultShare)) + { + container.WriteBytes(bytes); } } @@ -869,7 +884,17 @@ public void WriteAllText(string path, string? contents, Encoding encoding) _fileSystem.Storage.GetLocation( path.EnsureValidFormat(FileSystem)), InMemoryContainer.NewFile); - if (container is not NullContainer && contents != null) + if (container is NullContainer) + { + return; + } + + if (container.Type != FileSystemTypes.File) + { + throw ExceptionFactory.AccessToPathDenied(path); + } + + if (contents != null) { Execute.OnWindowsIf( container.Attributes.HasFlag(FileAttributes.Hidden), diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesAsyncTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesAsyncTests.cs index 7c39092cd..ae5ba5393 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesAsyncTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesAsyncTests.cs @@ -130,6 +130,25 @@ public async Task AppendAllLinesAsync_ShouldEndWithNewline(string path) FileSystem.File.ReadAllText(path).Should().BeEquivalentTo(expectedResult); } + [SkippableTheory] + [AutoData] + public async Task + AppendAllLinesAsync_WhenDirectoryWithSameNameExists_ShouldThrowUnauthorizedAccessException( + string path, string[] contents) + { + FileSystem.Directory.CreateDirectory(path); + + Exception? exception = await Record.ExceptionAsync(async () => + { + await FileSystem.File.AppendAllLinesAsync(path, contents); + }); + + exception.Should().BeException( + hResult: Test.RunsOnWindows ? -2147024891 : 17); + FileSystem.Directory.Exists(path).Should().BeTrue(); + FileSystem.File.Exists(path).Should().BeFalse(); + } + [SkippableTheory] [ClassData(typeof(TestDataGetEncodingDifference))] public async Task diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesTests.cs index 5b10e6b63..48f1d14e5 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesTests.cs @@ -82,6 +82,25 @@ public void AppendAllLines_ShouldEndWithNewline(string path) FileSystem.File.ReadAllText(path).Should().BeEquivalentTo(expectedResult); } + [SkippableTheory] + [AutoData] + public void + AppendAllLines_WhenDirectoryWithSameNameExists_ShouldThrowUnauthorizedAccessException( + string path, string[] contents) + { + FileSystem.Directory.CreateDirectory(path); + + Exception? exception = Record.Exception(() => + { + FileSystem.File.AppendAllLines(path, contents); + }); + + exception.Should().BeException( + hResult: Test.RunsOnWindows ? -2147024891 : 17); + FileSystem.Directory.Exists(path).Should().BeTrue(); + FileSystem.File.Exists(path).Should().BeFalse(); + } + [SkippableTheory] [ClassData(typeof(TestDataGetEncodingDifference))] public void AppendAllLines_WithDifferentEncoding_ShouldNotReturnWrittenText( diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextAsyncTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextAsyncTests.cs index 5aa05c876..5005af481 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextAsyncTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextAsyncTests.cs @@ -92,6 +92,25 @@ public async Task AppendAllTextAsync_ShouldNotEndWithNewline(string path) FileSystem.File.ReadAllText(path).Should().BeEquivalentTo(contents); } + [SkippableTheory] + [AutoData] + public async Task + AppendAllTextAsync_WhenDirectoryWithSameNameExists_ShouldThrowUnauthorizedAccessException( + string path, string contents) + { + FileSystem.Directory.CreateDirectory(path); + + Exception? exception = await Record.ExceptionAsync(async () => + { + await FileSystem.File.AppendAllTextAsync(path, contents); + }); + + exception.Should().BeException( + hResult: Test.RunsOnWindows ? -2147024891 : 17); + FileSystem.Directory.Exists(path).Should().BeTrue(); + FileSystem.File.Exists(path).Should().BeFalse(); + } + [SkippableTheory] [ClassData(typeof(TestDataGetEncodingDifference))] public async Task AppendAllTextAsync_WithDifferentEncoding_ShouldNotReturnWrittenText( diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextTests.cs index fcdf7d5b3..2e51491f0 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextTests.cs @@ -124,17 +124,22 @@ public void AppendAllText_ShouldNotEndWithNewline(string path) } [SkippableTheory] - [ClassData(typeof(TestDataGetEncodingDifference))] - public void AppendAllText_WithDifferentEncoding_ShouldNotReturnWrittenText( - string contents, Encoding writeEncoding, Encoding readEncoding) + [AutoData] + public void + AppendAllText_WhenDirectoryWithSameNameExists_ShouldThrowUnauthorizedAccessException( + string path) { - string path = new Fixture().Create(); - FileSystem.File.AppendAllText(path, contents, writeEncoding); + FileSystem.Directory.CreateDirectory(path); - string[] result = FileSystem.File.ReadAllLines(path, readEncoding); + Exception? exception = Record.Exception(() => + { + FileSystem.File.AppendAllText(path, null); + }); - result.Should().NotBeEquivalentTo(contents, - $"{contents} should be different when encoding from {writeEncoding} to {readEncoding}."); + exception.Should().BeException( + hResult: Test.RunsOnWindows ? -2147024891 : 17); + FileSystem.Directory.Exists(path).Should().BeTrue(); + FileSystem.File.Exists(path).Should().BeFalse(); } [SkippableTheory] @@ -152,4 +157,18 @@ public void AppendAllText_WhenFileIsHidden_ShouldNotThrowException( exception.Should().BeNull(); } + + [SkippableTheory] + [ClassData(typeof(TestDataGetEncodingDifference))] + public void AppendAllText_WithDifferentEncoding_ShouldNotReturnWrittenText( + string contents, Encoding writeEncoding, Encoding readEncoding) + { + string path = new Fixture().Create(); + FileSystem.File.AppendAllText(path, contents, writeEncoding); + + string[] result = FileSystem.File.ReadAllLines(path, readEncoding); + + result.Should().NotBeEquivalentTo(contents, + $"{contents} should be different when encoding from {writeEncoding} to {readEncoding}."); + } } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesAsyncTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesAsyncTests.cs index 7d7352523..bc525ed4a 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesAsyncTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesAsyncTests.cs @@ -63,6 +63,25 @@ public async Task WriteAllBytesAsync_WhenBytesAreNull_ShouldThrowArgumentNullExc exception.Should().BeException(paramName: "bytes"); } + [SkippableTheory] + [AutoData] + public async Task + WriteAllBytesAsync_WhenDirectoryWithSameNameExists_ShouldThrowUnauthorizedAccessException( + string path, byte[] bytes) + { + FileSystem.Directory.CreateDirectory(path); + + Exception? exception = await Record.ExceptionAsync(async () => + { + await FileSystem.File.WriteAllBytesAsync(path, bytes); + }); + + exception.Should().BeException( + hResult: Test.RunsOnWindows ? -2147024891 : 17); + FileSystem.Directory.Exists(path).Should().BeTrue(); + FileSystem.File.Exists(path).Should().BeFalse(); + } + [SkippableTheory] [AutoData] public async Task diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesTests.cs index c1ef63106..c500db34b 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesTests.cs @@ -21,6 +21,16 @@ public void WriteAllBytes_PreviousFile_ShouldOverwriteFileWithBytes( result.Should().BeEquivalentTo(bytes); } + [SkippableTheory] + [AutoData] + public void WriteAllBytes_ShouldCreateFileWithBytes(string path, byte[] bytes) + { + FileSystem.File.WriteAllBytes(path, bytes); + + byte[] result = FileSystem.File.ReadAllBytes(path); + result.Should().BeEquivalentTo(bytes); + } + [SkippableTheory] [AutoData] public void WriteAllBytes_WhenBytesAreNull_ShouldThrowArgumentNullException(string path) @@ -35,12 +45,21 @@ public void WriteAllBytes_WhenBytesAreNull_ShouldThrowArgumentNullException(stri [SkippableTheory] [AutoData] - public void WriteAllBytes_ShouldCreateFileWithBytes(string path, byte[] bytes) + public void + WriteAllBytes_WhenDirectoryWithSameNameExists_ShouldThrowUnauthorizedAccessException( + string path, byte[] bytes) { - FileSystem.File.WriteAllBytes(path, bytes); + FileSystem.Directory.CreateDirectory(path); - byte[] result = FileSystem.File.ReadAllBytes(path); - result.Should().BeEquivalentTo(bytes); + Exception? exception = Record.Exception(() => + { + FileSystem.File.WriteAllBytes(path, bytes); + }); + + exception.Should().BeException( + hResult: Test.RunsOnWindows ? -2147024891 : 17); + FileSystem.Directory.Exists(path).Should().BeTrue(); + FileSystem.File.Exists(path).Should().BeFalse(); } [SkippableTheory] diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesAsyncTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesAsyncTests.cs index 8034a0a6a..178e572a1 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesAsyncTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesAsyncTests.cs @@ -121,6 +121,25 @@ public async Task WriteAllLinesAsync_ShouldCreateFileWithText( result.Should().BeEquivalentTo(contents, o => o.WithStrictOrdering()); } + [SkippableTheory] + [AutoData] + public async Task + WriteAllLinesAsync_WhenDirectoryWithSameNameExists_ShouldThrowUnauthorizedAccessException( + string path, string[] contents) + { + FileSystem.Directory.CreateDirectory(path); + + Exception? exception = await Record.ExceptionAsync(async () => + { + await FileSystem.File.WriteAllLinesAsync(path, contents); + }); + + exception.Should().BeException( + hResult: Test.RunsOnWindows ? -2147024891 : 17); + FileSystem.Directory.Exists(path).Should().BeTrue(); + FileSystem.File.Exists(path).Should().BeFalse(); + } + [SkippableTheory] [AutoData] public async Task diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesTests.cs index 4ddd5a07e..7577cb8e8 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesTests.cs @@ -69,13 +69,21 @@ public void WriteAllLines_ShouldCreateFileWithText(string path, string[] content [SkippableTheory] [AutoData] - public void WriteAllLines_WithEncoding_ShouldCreateFileWithText( - Encoding encoding, string path, string[] contents) + public void + WriteAllLines_WhenDirectoryWithSameNameExists_ShouldThrowUnauthorizedAccessException( + string path, string[] contents) { - FileSystem.File.WriteAllLines(path, contents, encoding); + FileSystem.Directory.CreateDirectory(path); - string[] result = FileSystem.File.ReadAllLines(path, encoding); - result.Should().BeEquivalentTo(contents, o => o.WithStrictOrdering()); + Exception? exception = Record.Exception(() => + { + FileSystem.File.WriteAllLines(path, contents); + }); + + exception.Should().BeException( + hResult: Test.RunsOnWindows ? -2147024891 : 17); + FileSystem.Directory.Exists(path).Should().BeTrue(); + FileSystem.File.Exists(path).Should().BeFalse(); } [SkippableTheory] @@ -95,4 +103,15 @@ public void WriteAllLines_WhenFileIsHidden_ShouldThrowUnauthorizedAccessExceptio exception.Should().BeException(hResult: -2147024891); } + + [SkippableTheory] + [AutoData] + public void WriteAllLines_WithEncoding_ShouldCreateFileWithText( + Encoding encoding, string path, string[] contents) + { + FileSystem.File.WriteAllLines(path, contents, encoding); + + string[] result = FileSystem.File.ReadAllLines(path, encoding); + result.Should().BeEquivalentTo(contents, o => o.WithStrictOrdering()); + } } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextAsyncTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextAsyncTests.cs index e5b790507..50b480801 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextAsyncTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextAsyncTests.cs @@ -104,6 +104,25 @@ public async Task WriteAllTextAsync_WhenContentIsNull_ShouldNotThrowException(st exception.Should().BeNull(); } + [SkippableTheory] + [AutoData] + public async Task + WriteAllTextAsync_WhenDirectoryWithSameNameExists_ShouldThrowUnauthorizedAccessException( + string path, string contents) + { + FileSystem.Directory.CreateDirectory(path); + + Exception? exception = await Record.ExceptionAsync(async () => + { + await FileSystem.File.WriteAllTextAsync(path, contents); + }); + + exception.Should().BeException( + hResult: Test.RunsOnWindows ? -2147024891 : 17); + FileSystem.Directory.Exists(path).Should().BeTrue(); + FileSystem.File.Exists(path).Should().BeFalse(); + } + [SkippableTheory] [AutoData] public async Task diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextTests.cs index a0f3cba38..e1507fcd6 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextTests.cs @@ -149,6 +149,24 @@ public void WriteAllText_WhenContentIsNull_ShouldNotThrowException(string path) exception.Should().BeNull(); } + [SkippableTheory] + [AutoData] + public void WriteAllText_WhenDirectoryWithSameNameExists_ShouldThrowUnauthorizedAccessException( + string path) + { + FileSystem.Directory.CreateDirectory(path); + + Exception? exception = Record.Exception(() => + { + FileSystem.File.WriteAllText(path, null); + }); + + exception.Should().BeException( + hResult: Test.RunsOnWindows ? -2147024891 : 17); + FileSystem.Directory.Exists(path).Should().BeTrue(); + FileSystem.File.Exists(path).Should().BeFalse(); + } + [SkippableTheory] [AutoData] public void WriteAllText_WhenFileIsHidden_ShouldThrowUnauthorizedAccessException_OnWindows( From f2c39649baf6b36b6d1bfd72ce995e32c27a2744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Sun, 16 Apr 2023 16:13:38 +0200 Subject: [PATCH 4/7] Use correct hResult --- .../FileSystem/FileMock.cs | 10 ++++++---- .../Helpers/ExceptionFactory.cs | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Source/Testably.Abstractions.Testing/FileSystem/FileMock.cs b/Source/Testably.Abstractions.Testing/FileSystem/FileMock.cs index bfdaa0a5b..27be58d28 100644 --- a/Source/Testably.Abstractions.Testing/FileSystem/FileMock.cs +++ b/Source/Testably.Abstractions.Testing/FileSystem/FileMock.cs @@ -799,9 +799,10 @@ public void WriteAllBytes(string path, byte[] bytes) return; } - if (container.Type != FileSystemTypes.File) + if (container.Type == FileSystemTypes.Directory) { - throw ExceptionFactory.AccessToPathDenied(path); + throw ExceptionFactory.AccessToPathDenied(path, + hResult: Execute.IsWindows ? -2147024891 : 17); } Execute.OnWindowsIf( @@ -889,9 +890,10 @@ public void WriteAllText(string path, string? contents, Encoding encoding) return; } - if (container.Type != FileSystemTypes.File) + if (container.Type == FileSystemTypes.Directory) { - throw ExceptionFactory.AccessToPathDenied(path); + throw ExceptionFactory.AccessToPathDenied(path, + hResult: Execute.IsWindows ? - 2147024891 : 17); } if (contents != null) diff --git a/Source/Testably.Abstractions.Testing/Helpers/ExceptionFactory.cs b/Source/Testably.Abstractions.Testing/Helpers/ExceptionFactory.cs index 3732aa079..ebcd19102 100644 --- a/Source/Testably.Abstractions.Testing/Helpers/ExceptionFactory.cs +++ b/Source/Testably.Abstractions.Testing/Helpers/ExceptionFactory.cs @@ -31,13 +31,13 @@ public static IOException SeekBackwardNotPossibleInAppendMode() "Unable seek backward to overwrite data that previously existed in a file opened in Append mode.", -2146232800); - internal static UnauthorizedAccessException AccessToPathDenied(string path = "") + internal static UnauthorizedAccessException AccessToPathDenied(string path = "", int hResult = -2147024891) => new(string.IsNullOrEmpty(path) ? "Access to the path is denied." : $"Access to the path '{path}' is denied.") { #if FEATURE_EXCEPTION_HRESULT - HResult = -2147024891 + HResult = hResult #endif }; From 897eeb8ceaf3b9346d62eb392e80ed6548437de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Sun, 16 Apr 2023 17:01:12 +0200 Subject: [PATCH 5/7] Fix failing tests on ubuntu and Mac --- .../FileSystem/File/AppendAllLinesAsyncTests.cs | 2 +- .../FileSystem/File/AppendAllLinesTests.cs | 2 +- .../FileSystem/File/AppendAllTextAsyncTests.cs | 2 +- .../FileSystem/File/AppendAllTextTests.cs | 2 +- .../FileSystem/File/WriteAllBytesAsyncTests.cs | 2 +- .../FileSystem/File/WriteAllBytesTests.cs | 2 +- .../FileSystem/File/WriteAllLinesAsyncTests.cs | 2 +- .../FileSystem/File/WriteAllLinesTests.cs | 2 +- .../FileSystem/File/WriteAllTextAsyncTests.cs | 2 +- .../FileSystem/File/WriteAllTextTests.cs | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesAsyncTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesAsyncTests.cs index ae5ba5393..dbd1742bb 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesAsyncTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesAsyncTests.cs @@ -144,7 +144,7 @@ public async Task }); exception.Should().BeException( - hResult: Test.RunsOnWindows ? -2147024891 : 17); + hResult: -2147024891); FileSystem.Directory.Exists(path).Should().BeTrue(); FileSystem.File.Exists(path).Should().BeFalse(); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesTests.cs index 48f1d14e5..668750435 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllLinesTests.cs @@ -96,7 +96,7 @@ public void }); exception.Should().BeException( - hResult: Test.RunsOnWindows ? -2147024891 : 17); + hResult: -2147024891); FileSystem.Directory.Exists(path).Should().BeTrue(); FileSystem.File.Exists(path).Should().BeFalse(); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextAsyncTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextAsyncTests.cs index 5005af481..1f1b079bc 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextAsyncTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextAsyncTests.cs @@ -106,7 +106,7 @@ public async Task }); exception.Should().BeException( - hResult: Test.RunsOnWindows ? -2147024891 : 17); + hResult: -2147024891); FileSystem.Directory.Exists(path).Should().BeTrue(); FileSystem.File.Exists(path).Should().BeFalse(); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextTests.cs index 2e51491f0..61ba050ed 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/AppendAllTextTests.cs @@ -137,7 +137,7 @@ public void }); exception.Should().BeException( - hResult: Test.RunsOnWindows ? -2147024891 : 17); + hResult: -2147024891); FileSystem.Directory.Exists(path).Should().BeTrue(); FileSystem.File.Exists(path).Should().BeFalse(); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesAsyncTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesAsyncTests.cs index bc525ed4a..746116afa 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesAsyncTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesAsyncTests.cs @@ -77,7 +77,7 @@ public async Task }); exception.Should().BeException( - hResult: Test.RunsOnWindows ? -2147024891 : 17); + hResult: -2147024891); FileSystem.Directory.Exists(path).Should().BeTrue(); FileSystem.File.Exists(path).Should().BeFalse(); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesTests.cs index c500db34b..3d7df9726 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllBytesTests.cs @@ -57,7 +57,7 @@ public void }); exception.Should().BeException( - hResult: Test.RunsOnWindows ? -2147024891 : 17); + hResult: -2147024891); FileSystem.Directory.Exists(path).Should().BeTrue(); FileSystem.File.Exists(path).Should().BeFalse(); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesAsyncTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesAsyncTests.cs index 178e572a1..0f8865146 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesAsyncTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesAsyncTests.cs @@ -135,7 +135,7 @@ public async Task }); exception.Should().BeException( - hResult: Test.RunsOnWindows ? -2147024891 : 17); + hResult: -2147024891); FileSystem.Directory.Exists(path).Should().BeTrue(); FileSystem.File.Exists(path).Should().BeFalse(); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesTests.cs index 7577cb8e8..f1a5f73cf 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllLinesTests.cs @@ -81,7 +81,7 @@ public void }); exception.Should().BeException( - hResult: Test.RunsOnWindows ? -2147024891 : 17); + hResult: -2147024891); FileSystem.Directory.Exists(path).Should().BeTrue(); FileSystem.File.Exists(path).Should().BeFalse(); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextAsyncTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextAsyncTests.cs index 50b480801..0ba36e689 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextAsyncTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextAsyncTests.cs @@ -118,7 +118,7 @@ public async Task }); exception.Should().BeException( - hResult: Test.RunsOnWindows ? -2147024891 : 17); + hResult: -2147024891); FileSystem.Directory.Exists(path).Should().BeTrue(); FileSystem.File.Exists(path).Should().BeFalse(); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextTests.cs index e1507fcd6..6a636002d 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/WriteAllTextTests.cs @@ -162,7 +162,7 @@ public void WriteAllText_WhenDirectoryWithSameNameExists_ShouldThrowUnauthorized }); exception.Should().BeException( - hResult: Test.RunsOnWindows ? -2147024891 : 17); + hResult: -2147024891); FileSystem.Directory.Exists(path).Should().BeTrue(); FileSystem.File.Exists(path).Should().BeFalse(); } From ad193ae62b859498cc907f2a0fe4465f83ba9bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Sun, 16 Apr 2023 17:10:24 +0200 Subject: [PATCH 6/7] Fix directory handling in ZipFile examples --- Examples/ZipFile/ZipFile/ZipFileHelper.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Examples/ZipFile/ZipFile/ZipFileHelper.cs b/Examples/ZipFile/ZipFile/ZipFileHelper.cs index fd390ee60..1dbe52b1a 100644 --- a/Examples/ZipFile/ZipFile/ZipFileHelper.cs +++ b/Examples/ZipFile/ZipFile/ZipFileHelper.cs @@ -54,10 +54,13 @@ public void ExtractZipToDirectory(Stream stream, string directory) { _fileSystem.Directory.CreateDirectory(directoryPath); } - - using MemoryStream ms = new(); - entry.Open().CopyTo(ms); - _fileSystem.File.WriteAllBytes(filePath, ms.ToArray()); + + if (!entry.FullName.EndsWith("/")) + { + using MemoryStream ms = new(); + entry.Open().CopyTo(ms); + _fileSystem.File.WriteAllBytes(filePath, ms.ToArray()); + } } } From 47de8d48f077ba654b0791b521e0d1fdf9877c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Sun, 16 Apr 2023 17:20:29 +0200 Subject: [PATCH 7/7] Fix failing tests --- .../FileSystem/FileMock.cs | 10 ++++------ .../Helpers/ExceptionFactory.cs | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Source/Testably.Abstractions.Testing/FileSystem/FileMock.cs b/Source/Testably.Abstractions.Testing/FileSystem/FileMock.cs index 27be58d28..bfdaa0a5b 100644 --- a/Source/Testably.Abstractions.Testing/FileSystem/FileMock.cs +++ b/Source/Testably.Abstractions.Testing/FileSystem/FileMock.cs @@ -799,10 +799,9 @@ public void WriteAllBytes(string path, byte[] bytes) return; } - if (container.Type == FileSystemTypes.Directory) + if (container.Type != FileSystemTypes.File) { - throw ExceptionFactory.AccessToPathDenied(path, - hResult: Execute.IsWindows ? -2147024891 : 17); + throw ExceptionFactory.AccessToPathDenied(path); } Execute.OnWindowsIf( @@ -890,10 +889,9 @@ public void WriteAllText(string path, string? contents, Encoding encoding) return; } - if (container.Type == FileSystemTypes.Directory) + if (container.Type != FileSystemTypes.File) { - throw ExceptionFactory.AccessToPathDenied(path, - hResult: Execute.IsWindows ? - 2147024891 : 17); + throw ExceptionFactory.AccessToPathDenied(path); } if (contents != null) diff --git a/Source/Testably.Abstractions.Testing/Helpers/ExceptionFactory.cs b/Source/Testably.Abstractions.Testing/Helpers/ExceptionFactory.cs index ebcd19102..3732aa079 100644 --- a/Source/Testably.Abstractions.Testing/Helpers/ExceptionFactory.cs +++ b/Source/Testably.Abstractions.Testing/Helpers/ExceptionFactory.cs @@ -31,13 +31,13 @@ public static IOException SeekBackwardNotPossibleInAppendMode() "Unable seek backward to overwrite data that previously existed in a file opened in Append mode.", -2146232800); - internal static UnauthorizedAccessException AccessToPathDenied(string path = "", int hResult = -2147024891) + internal static UnauthorizedAccessException AccessToPathDenied(string path = "") => new(string.IsNullOrEmpty(path) ? "Access to the path is denied." : $"Access to the path '{path}' is denied.") { #if FEATURE_EXCEPTION_HRESULT - HResult = hResult + HResult = -2147024891 #endif };