diff --git a/Tests/Helpers/Testably.Abstractions.TestHelpers/FileSystemTestBase.cs b/Tests/Helpers/Testably.Abstractions.TestHelpers/FileSystemTestBase.cs index d63b3687..3f12f0f2 100644 --- a/Tests/Helpers/Testably.Abstractions.TestHelpers/FileSystemTestBase.cs +++ b/Tests/Helpers/Testably.Abstractions.TestHelpers/FileSystemTestBase.cs @@ -17,13 +17,17 @@ public abstract class FileSystemTestBase where TFileSystem : IFileSystem { public abstract string BasePath { get; } + public Test Test { get; } public TFileSystem FileSystem { get; } public ITimeSystem TimeSystem { get; } // ReSharper disable once UnusedMember.Global - protected FileSystemTestBase(TFileSystem fileSystem, + protected FileSystemTestBase( + Test test, + TFileSystem fileSystem, ITimeSystem timeSystem) { + Test = test; FileSystem = fileSystem; TimeSystem = timeSystem; diff --git a/Tests/Helpers/Testably.Abstractions.TestHelpers/Test.cs b/Tests/Helpers/Testably.Abstractions.TestHelpers/Test.cs index fe2548f7..38f10788 100644 --- a/Tests/Helpers/Testably.Abstractions.TestHelpers/Test.cs +++ b/Tests/Helpers/Testably.Abstractions.TestHelpers/Test.cs @@ -1,72 +1,66 @@ -using System.IO.Abstractions; -using System.Runtime.InteropServices; -using Xunit; - -namespace Testably.Abstractions.TestHelpers; - -public static class Test -{ - private static bool? _isNetFramework; - - public static bool IsNetFramework - { - get - { - _isNetFramework ??= RuntimeInformation - .FrameworkDescription.StartsWith(".NET Framework"); - return _isNetFramework.Value; - } - } - - public static bool RunsOnLinux - => RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - - public static bool RunsOnMac - => RuntimeInformation.IsOSPlatform(OSPlatform.OSX); - - public static bool RunsOnWindows - => RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - - public static bool IsNet7OrGreater +using System.IO.Abstractions; +using System.Runtime.InteropServices; +using Xunit; + +namespace Testably.Abstractions.TestHelpers; + +public class Test +{ + public static bool IsNet7OrGreater #if NET7_0_OR_GREATER - => true; -#else - => false; -#endif - - public static void SkipBrittleTestsOnRealFileSystem( - IFileSystem fileSystem, bool condition = true) - { - Skip.If(fileSystem is RealFileSystem && condition, - "Brittle tests are skipped on the real file system."); - } - - public static void SkipBrittleTestsOnRealTimeSystem( - ITimeSystem timeSystem, bool condition = true) - { - Skip.If(timeSystem is RealTimeSystem && condition, - "Brittle tests are skipped on the real time system."); - } - - public static void SkipIfLongRunningTestsShouldBeSkipped(IFileSystem fileSystem) - { -#if DEBUG && !INCLUDE_LONGRUNNING_TESTS_ALSO_IN_DEBUG_MODE - Skip.If(fileSystem is RealFileSystem, - "Long-Running tests are skipped in DEBUG mode unless the build constant 'INCLUDE_LONG_RUNNING_TESTS_ALSO_IN_DEBUG_MODE' is set."); -#endif - // ReSharper disable once CommentTypo - // Do nothing when in release mode or `INCLUDE_LONGRUNNING_TESTS_ALSO_IN_DEBUG_MODE` is set - } - - public static void SkipIfTestsOnRealFileSystemShouldBeSkipped(IFileSystem fileSystem) - { + => true; +#else + => false; +#endif + public bool IsNetFramework { get; } + + public bool RunsOnLinux { get; } + + public bool RunsOnMac { get; } + + public bool RunsOnWindows { get; } + + public Test() + { + RunsOnLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + RunsOnMac = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + RunsOnWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + IsNetFramework = RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework"); + } + + public static void SkipBrittleTestsOnRealFileSystem( + IFileSystem fileSystem, bool condition = true) + { + Skip.If(fileSystem is RealFileSystem && condition, + "Brittle tests are skipped on the real file system."); + } + + public static void SkipBrittleTestsOnRealTimeSystem( + ITimeSystem timeSystem, bool condition = true) + { + Skip.If(timeSystem is RealTimeSystem && condition, + "Brittle tests are skipped on the real time system."); + } + + public static void SkipIfLongRunningTestsShouldBeSkipped(IFileSystem fileSystem) + { +#if DEBUG && !INCLUDE_LONGRUNNING_TESTS_ALSO_IN_DEBUG_MODE + Skip.If(fileSystem is RealFileSystem, + "Long-Running tests are skipped in DEBUG mode unless the build constant 'INCLUDE_LONG_RUNNING_TESTS_ALSO_IN_DEBUG_MODE' is set."); +#endif + // ReSharper disable once CommentTypo + // Do nothing when in release mode or `INCLUDE_LONGRUNNING_TESTS_ALSO_IN_DEBUG_MODE` is set + } + + public static void SkipIfTestsOnRealFileSystemShouldBeSkipped(IFileSystem fileSystem) + { #if NCRUNCH - Skip.If(fileSystem is RealFileSystem, "NCrunch should not test the real file system."); -#endif + Skip.If(fileSystem is RealFileSystem, "NCrunch should not test the real file system."); +#endif #if DEBUG && SKIP_TESTS_ON_REAL_FILESYSTEM Skip.If(fileSystem is RealFileSystem, - "Tests against real FileSystem are skipped in DEBUG mode with the build constant 'SKIP_TESTS_ON_REAL_FILESYSTEM'."); -#endif - // Do nothing when in release mode or `SKIP_TESTS_ON_REAL_FILESYSTEM` is not set - } + "Tests against real FileSystem are skipped in DEBUG mode with the build constant 'SKIP_TESTS_ON_REAL_FILESYSTEM'."); +#endif + // Do nothing when in release mode or `SKIP_TESTS_ON_REAL_FILESYSTEM` is not set + } } diff --git a/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs b/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs index 1f0c6feb..9a7b394f 100644 --- a/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs +++ b/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs @@ -21,8 +21,8 @@ namespace {@class.Namespace} {{ public abstract partial class {@class.Name} {{ - protected {@class.Name}(TFileSystem fileSystem, ITimeSystem timeSystem) - : base(fileSystem, timeSystem) + protected {@class.Name}(Test test, TFileSystem fileSystem, ITimeSystem timeSystem) + : base(test, fileSystem, timeSystem) {{ }} }} @@ -43,6 +43,7 @@ public MockFileSystemTests() : this(new MockFileSystem()) }} private MockFileSystemTests(MockFileSystem mockFileSystem) : base( + new Test(), mockFileSystem, mockFileSystem.TimeSystem) {{ @@ -70,7 +71,7 @@ public sealed class RealFileSystemTests : {@class.Name}, IDispos private readonly IDirectoryCleaner _directoryCleaner; public RealFileSystemTests(ITestOutputHelper testOutputHelper) - : base(new RealFileSystem(), new RealTimeSystem()) + : base(new Test(), new RealFileSystem(), new RealTimeSystem()) {{ _directoryCleaner = FileSystem .SetCurrentDirectoryToEmptyTemporaryDirectory($""{@class.Namespace}{{FileSystem.Path.DirectorySeparatorChar}}{@class.Name}-"", testOutputHelper.WriteLine); diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/CreateDirectoryTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/CreateDirectoryTests.cs index 42344052..bbff0fb0 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/CreateDirectoryTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/CreateDirectoryTests.cs @@ -69,7 +69,7 @@ public void CreateDirectory_FileWithSameNameAlreadyExists_ShouldThrowIOException [SkippableFact] public void CreateDirectory_Root_ShouldNotThrowException() { - string path = FileTestHelper.RootDrive(); + string path = FileTestHelper.RootDrive(Test); FileSystem.Directory.CreateDirectory(path); Exception? exception = Record.Exception(() => @@ -313,9 +313,8 @@ public void CreateDirectory_TrailingDirectorySeparator_ShouldNotBeTrimmed( result.Name.Should().Be(expectedName.TrimEnd( FileSystem.Path.DirectorySeparatorChar, FileSystem.Path.AltDirectorySeparatorChar)); - result.FullName.Should().Be(System.IO.Path.Combine(BasePath, expectedName - .Replace(FileSystem.Path.AltDirectorySeparatorChar, - FileSystem.Path.DirectorySeparatorChar))); + result.FullName.Should().Be($"{BasePath}{FileSystem.Path.DirectorySeparatorChar}{expectedName}" + .Replace(FileSystem.Path.AltDirectorySeparatorChar, FileSystem.Path.DirectorySeparatorChar)); FileSystem.Should().HaveDirectory(nameWithSuffix); } #endif diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/ExceptionTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/ExceptionTests.cs index 43f91649..71ef1e32 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/ExceptionTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/ExceptionTests.cs @@ -1,247 +1,347 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Linq.Expressions; - -namespace Testably.Abstractions.Tests.FileSystem.Directory; - -// ReSharper disable once PartialTypeWithSinglePart -public abstract partial class ExceptionTests - : FileSystemTestBase - where TFileSystem : IFileSystem -{ - [SkippableTheory] - [MemberData(nameof(GetDirectoryCallbacks), parameters: "")] - public void Operations_WhenValueIsEmpty_ShouldThrowArgumentException( - Expression> callback, string paramName, bool ignoreParamCheck) - { - Exception? exception = Record.Exception(() => - { - callback.Compile().Invoke(FileSystem.Directory); - }); - - exception.Should().BeException( - hResult: -2147024809, - paramName: ignoreParamCheck || Test.IsNetFramework ? null : paramName, - because: - $"\n{callback}\n has empty parameter for '{paramName}' (ignored: {ignoreParamCheck})"); - } - - [SkippableTheory] - [MemberData(nameof(GetDirectoryCallbacks), parameters: " ")] - public void Operations_WhenValueIsWhitespace_ShouldThrowArgumentException( - Expression> callback, string paramName, bool ignoreParamCheck) - { - Skip.IfNot(Test.RunsOnWindows); - - Exception? exception = Record.Exception(() => - { - callback.Compile().Invoke(FileSystem.Directory); - }); - - exception.Should().BeException( - hResult: -2147024809, - paramName: ignoreParamCheck || Test.IsNetFramework ? null : paramName, - because: - $"\n{callback}\n has whitespace parameter for '{paramName}' (ignored: {ignoreParamCheck})"); - } - - [SkippableTheory] - [MemberData(nameof(GetDirectoryCallbacks), parameters: (string?)null)] - public void Operations_WhenValueIsNull_ShouldThrowArgumentNullException( - Expression> callback, string paramName, bool ignoreParamCheck) - { - Exception? exception = Record.Exception(() => - { - callback.Compile().Invoke(FileSystem.Directory); - }); - - exception.Should().BeException( - paramName: ignoreParamCheck ? null : paramName, - because: - $"\n{callback}\n has `null` parameter for '{paramName}' (ignored: {ignoreParamCheck})"); - } - - [SkippableTheory] - [MemberData(nameof(GetDirectoryCallbacks), parameters: "Illegal\tCharacter?InPath")] - public void - Operations_WhenValueContainsIllegalPathCharacters_ShouldThrowCorrectException_OnWindows( - Expression> callback, string paramName, - bool ignoreParamCheck) - { - Exception? exception = Record.Exception(() => - { - callback.Compile().Invoke(FileSystem.Directory); - }); - - if (!Test.RunsOnWindows) - { - if (exception is IOException ioException) - { - ioException.HResult.Should().NotBe(-2147024809, - $"\n{callback}\n contains invalid path characters for '{paramName}' (ignored: {ignoreParamCheck})"); - } - } - else - { - if (Test.IsNetFramework) - { - exception.Should().BeException( - hResult: -2147024809, - because: - $"\n{callback}\n contains invalid path characters for '{paramName}' (ignored: {ignoreParamCheck})"); - } - else - { - exception.Should().BeException( - hResult: -2147024773, - because: - $"\n{callback}\n contains invalid path characters for '{paramName}' (ignored: {ignoreParamCheck})"); - } - } - } - - #region Helpers - - public static TheoryData>, string, bool> GetDirectoryCallbacks(string? path) - { - TheoryData>, string, bool> theoryData = new(); - foreach (var item in GetDirectoryCallbackTestParameters(path!) - .Where(item => item.TestType.HasFlag(path.ToTestType()))) - { - theoryData.Add( - item.Callback, - item.ParamName, - item.TestType.HasFlag(ExceptionTestHelper.TestTypes.IgnoreParamNameCheck)); - } - return theoryData; - } - - private static IEnumerable<(ExceptionTestHelper.TestTypes TestType, string ParamName, - Expression> Callback)> - GetDirectoryCallbackTestParameters(string value) - { - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.CreateDirectory(value)); -#if FEATURE_FILESYSTEM_UNIXFILEMODE - if (!Test.RunsOnWindows) - { - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.CreateDirectory(value, UnixFileMode.None)); - } -#endif -#if FEATURE_FILESYSTEM_LINK - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.CreateSymbolicLink(value, "foo")); - yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "pathToTarget", directory - => directory.CreateSymbolicLink("foo", value)); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.Delete(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.Delete(value, true)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.EnumerateDirectories(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.EnumerateDirectories(value, "foo")); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.EnumerateDirectories(value, "foo", SearchOption.AllDirectories)); -#if FEATURE_FILESYSTEM_ENUMERATION_OPTIONS - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.EnumerateDirectories(value, "foo", new EnumerationOptions())); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.EnumerateFiles(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.EnumerateFiles(value, "foo")); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.EnumerateFiles(value, "foo", SearchOption.AllDirectories)); -#if FEATURE_FILESYSTEM_ENUMERATION_OPTIONS - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.EnumerateFiles(value, "foo", new EnumerationOptions())); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.EnumerateFileSystemEntries(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.EnumerateFileSystemEntries(value, "foo")); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.EnumerateFileSystemEntries(value, "foo", - SearchOption.AllDirectories)); -#if FEATURE_FILESYSTEM_ENUMERATION_OPTIONS - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.EnumerateFileSystemEntries(value, "foo", - new EnumerationOptions())); -#endif - // `Directory.Exists` doesn't throw an exception on `null` - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetCreationTime(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetCreationTimeUtc(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetDirectories(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetDirectories(value, "foo")); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetDirectories(value, "foo", SearchOption.AllDirectories)); -#if FEATURE_FILESYSTEM_ENUMERATION_OPTIONS - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetDirectories(value, "foo", new EnumerationOptions())); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetFiles(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetFiles(value, "foo")); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetFiles(value, "foo", SearchOption.AllDirectories)); -#if FEATURE_FILESYSTEM_ENUMERATION_OPTIONS - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetFiles(value, "foo", new EnumerationOptions())); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetFileSystemEntries(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetFileSystemEntries(value, "foo")); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetFileSystemEntries(value, "foo", SearchOption.AllDirectories)); -#if FEATURE_FILESYSTEM_ENUMERATION_OPTIONS - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetFileSystemEntries(value, "foo", new EnumerationOptions())); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetLastAccessTime(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetLastAccessTimeUtc(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetLastWriteTime(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.GetLastWriteTimeUtc(value)); +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Linq.Expressions; + +namespace Testably.Abstractions.Tests.FileSystem.Directory; + +// ReSharper disable once PartialTypeWithSinglePart +public abstract partial class ExceptionTests + : FileSystemTestBase + where TFileSystem : IFileSystem +{ + [SkippableTheory] + [MemberData(nameof(GetDirectoryCallbacks), parameters: "Illegal\tCharacter?InPath")] + public void + Operations_WhenValueContainsIllegalPathCharacters_ShouldThrowCorrectException_OnWindows( + Expression> callback, string paramName, + bool ignoreParamCheck, Func skipTest) + { + Skip.If(skipTest(Test)); + + Exception? exception = Record.Exception(() => + { + callback.Compile().Invoke(FileSystem.Directory); + }); + + if (!Test.RunsOnWindows) + { + if (exception is IOException ioException) + { + ioException.HResult.Should().NotBe(-2147024809, + $"\n{callback}\n contains invalid path characters for '{paramName}' (ignored: {ignoreParamCheck})"); + } + } + else + { + if (Test.IsNetFramework) + { + exception.Should().BeException( + hResult: -2147024809, + because: + $"\n{callback}\n contains invalid path characters for '{paramName}' (ignored: {ignoreParamCheck})"); + } + else + { + exception.Should().BeException( + hResult: -2147024773, + because: + $"\n{callback}\n contains invalid path characters for '{paramName}' (ignored: {ignoreParamCheck})"); + } + } + } + + [SkippableTheory] + [MemberData(nameof(GetDirectoryCallbacks), parameters: "")] + public void Operations_WhenValueIsEmpty_ShouldThrowArgumentException( + Expression> callback, string paramName, bool ignoreParamCheck, + Func skipTest) + { + Skip.If(skipTest(Test)); + + Exception? exception = Record.Exception(() => + { + callback.Compile().Invoke(FileSystem.Directory); + }); + + exception.Should().BeException( + hResult: -2147024809, + paramName: ignoreParamCheck || Test.IsNetFramework ? null : paramName, + because: + $"\n{callback}\n has empty parameter for '{paramName}' (ignored: {ignoreParamCheck})"); + } + + [SkippableTheory] + [MemberData(nameof(GetDirectoryCallbacks), parameters: (string?)null)] + public void Operations_WhenValueIsNull_ShouldThrowArgumentNullException( + Expression> callback, string paramName, bool ignoreParamCheck, + Func skipTest) + { + Skip.If(skipTest(Test)); + + Exception? exception = Record.Exception(() => + { + callback.Compile().Invoke(FileSystem.Directory); + }); + + exception.Should().BeException( + paramName: ignoreParamCheck ? null : paramName, + because: + $"\n{callback}\n has `null` parameter for '{paramName}' (ignored: {ignoreParamCheck})"); + } + + [SkippableTheory] + [MemberData(nameof(GetDirectoryCallbacks), parameters: " ")] + public void Operations_WhenValueIsWhitespace_ShouldThrowArgumentException( + Expression> callback, string paramName, bool ignoreParamCheck, + Func skipTest) + { + Skip.If(skipTest(Test)); + + Skip.IfNot(Test.RunsOnWindows); + + Exception? exception = Record.Exception(() => + { + callback.Compile().Invoke(FileSystem.Directory); + }); + + exception.Should().BeException( + hResult: -2147024809, + paramName: ignoreParamCheck || Test.IsNetFramework ? null : paramName, + because: + $"\n{callback}\n has whitespace parameter for '{paramName}' (ignored: {ignoreParamCheck})"); + } + + #region Helpers + + public static TheoryData>, string, bool, Func> + GetDirectoryCallbacks(string? path) + { + TheoryData>, string, bool, Func> theoryData = + new(); + foreach ((ExceptionTestHelper.TestTypes TestType, string ParamName, + Expression> Callback, Func? SkipTest) item in + GetDirectoryCallbackTestParameters(path!) + .Where(item => item.TestType.HasFlag(path.ToTestType()))) + { + theoryData.Add( + item.Callback, + item.ParamName, + item.TestType.HasFlag(ExceptionTestHelper.TestTypes.IgnoreParamNameCheck), + item.SkipTest ?? (_ => false)); + } + + return theoryData; + } + + private static IEnumerable<(ExceptionTestHelper.TestTypes TestType, string ParamName, + Expression> Callback, Func? SkipTest)> + GetDirectoryCallbackTestParameters(string value) + { + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.CreateDirectory(value), + null); +#if FEATURE_FILESYSTEM_UNIXFILEMODE + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.CreateDirectory(value, UnixFileMode.None), + test => test.RunsOnWindows); +#endif +#if FEATURE_FILESYSTEM_LINK + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.CreateSymbolicLink(value, "foo"), + null); + yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "pathToTarget", + directory + => directory.CreateSymbolicLink("foo", value), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.Delete(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.Delete(value, true), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.EnumerateDirectories(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.EnumerateDirectories(value, "foo"), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.EnumerateDirectories(value, "foo", SearchOption.AllDirectories), + null); +#if FEATURE_FILESYSTEM_ENUMERATION_OPTIONS + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.EnumerateDirectories(value, "foo", new EnumerationOptions()), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.EnumerateFiles(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.EnumerateFiles(value, "foo"), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.EnumerateFiles(value, "foo", SearchOption.AllDirectories), + null); +#if FEATURE_FILESYSTEM_ENUMERATION_OPTIONS + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.EnumerateFiles(value, "foo", new EnumerationOptions()), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.EnumerateFileSystemEntries(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.EnumerateFileSystemEntries(value, "foo"), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.EnumerateFileSystemEntries(value, "foo", SearchOption.AllDirectories), + null); +#if FEATURE_FILESYSTEM_ENUMERATION_OPTIONS + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.EnumerateFileSystemEntries(value, "foo", new EnumerationOptions()), + null); +#endif + // `Directory.Exists` doesn't throw an exception on `null` + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetCreationTime(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetCreationTimeUtc(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetDirectories(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetDirectories(value, "foo"), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetDirectories(value, "foo", SearchOption.AllDirectories), + null); +#if FEATURE_FILESYSTEM_ENUMERATION_OPTIONS + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetDirectories(value, "foo", new EnumerationOptions()), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetFiles(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetFiles(value, "foo"), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetFiles(value, "foo", SearchOption.AllDirectories), + null); +#if FEATURE_FILESYSTEM_ENUMERATION_OPTIONS + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetFiles(value, "foo", new EnumerationOptions()), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetFileSystemEntries(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetFileSystemEntries(value, "foo"), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetFileSystemEntries(value, "foo", SearchOption.AllDirectories), + null); +#if FEATURE_FILESYSTEM_ENUMERATION_OPTIONS + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetFileSystemEntries(value, "foo", new EnumerationOptions()), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetLastAccessTime(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetLastAccessTimeUtc(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetLastWriteTime(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.GetLastWriteTimeUtc(value), + null); yield return (ExceptionTestHelper.TestTypes.AllExceptInvalidPath, "path", - directory - => directory.GetParent(value)); + directory + => directory.GetParent(value), + null); yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "sourceDirName", - directory - => directory.Move(value, "foo")); + directory + => directory.Move(value, "foo"), + null); yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "destDirName", - directory - => directory.Move("foo", value)); -#if FEATURE_FILESYSTEM_LINK + directory + => directory.Move("foo", value), + null); +#if FEATURE_FILESYSTEM_LINK yield return (ExceptionTestHelper.TestTypes.AllExceptWhitespace, "linkPath", - directory - => directory.ResolveLinkTarget(value, false)); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.SetCreationTime(value, DateTime.Now)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.SetCreationTimeUtc(value, DateTime.Now)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.SetLastAccessTime(value, DateTime.Now)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.SetLastAccessTimeUtc(value, DateTime.Now)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.SetLastWriteTime(value, DateTime.Now)); - yield return (ExceptionTestHelper.TestTypes.All, "path", directory - => directory.SetLastWriteTimeUtc(value, DateTime.Now)); - } - - #endregion -} + directory + => directory.ResolveLinkTarget(value, false), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.SetCreationTime(value, DateTime.Now), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.SetCreationTimeUtc(value, DateTime.Now), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.SetLastAccessTime(value, DateTime.Now), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.SetLastAccessTimeUtc(value, DateTime.Now), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.SetLastWriteTime(value, DateTime.Now), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + directory + => directory.SetLastWriteTimeUtc(value, DateTime.Now), + null); + } + + #endregion +} diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/GetDirectoryRootTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/GetDirectoryRootTests.cs index 9bdb3946..ef6ae78c 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/GetDirectoryRootTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/GetDirectoryRootTests.cs @@ -19,7 +19,7 @@ public void GetDirectoryRoot_Empty_ShouldThrowArgumentException() [SkippableFact] public void GetDirectoryRoot_ShouldReturnDefaultRoot() { - string expectedRoot = FileTestHelper.RootDrive(); + string expectedRoot = FileTestHelper.RootDrive(Test); string result = FileSystem.Directory.GetDirectoryRoot("foo"); @@ -34,7 +34,7 @@ public void GetDirectoryRoot_SpecificDrive_ShouldReturnRootWithCorrectDrive( char drive) { Skip.IfNot(Test.RunsOnWindows, "Linux does not support different drives."); - string expectedRoot = FileTestHelper.RootDrive("", drive); + string expectedRoot = FileTestHelper.RootDrive(Test, "", drive); string path = System.IO.Path.Combine($"{drive}:\\foo", "bar"); string result = FileSystem.Directory.GetDirectoryRoot(path); diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/MoveTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/MoveTests.cs index dd76d904..cf9141af 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/MoveTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/MoveTests.cs @@ -70,7 +70,7 @@ public void Move_DestinationDoesNotExist_ShouldThrowDirectoryNotFoundException( { FileSystem.InitializeIn(source) .WithAFile(); - string destination = FileTestHelper.RootDrive("not-existing/path"); + string destination = FileTestHelper.RootDrive(Test, "not-existing/path"); Exception? exception = Record.Exception(() => { diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/ResolveLinkTargetTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/ResolveLinkTargetTests.cs index fa0f97fc..5f3f720e 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/ResolveLinkTargetTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/ResolveLinkTargetTests.cs @@ -15,7 +15,7 @@ public abstract partial class ResolveLinkTargetTests /// The maximum number of symbolic links that are followed.
/// /// - private static int MaxResolveLinks => + private int MaxResolveLinks => Test.RunsOnWindows ? 63 : 40; #endregion diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/Tests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/Tests.cs index 5074b1c3..d6a0dfa2 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/Directory/Tests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/Directory/Tests.cs @@ -30,14 +30,14 @@ public void GetCurrentDirectory_ShouldNotBeRooted() { string result = FileSystem.Directory.GetCurrentDirectory(); - result.Should().NotBe(FileTestHelper.RootDrive()); + result.Should().NotBe(FileTestHelper.RootDrive(Test)); } [SkippableTheory] [AutoData] public void GetDirectoryRoot_ShouldReturnRoot(string path) { - string root = FileTestHelper.RootDrive(); + string root = FileTestHelper.RootDrive(Test); string rootedPath = root + path; string result = FileSystem.Directory.GetDirectoryRoot(rootedPath); @@ -51,7 +51,7 @@ public void GetLogicalDrives_ShouldNotBeEmpty() string[] result = FileSystem.Directory.GetLogicalDrives(); result.Should().NotBeEmpty(); - result.Should().Contain(FileTestHelper.RootDrive()); + result.Should().Contain(FileTestHelper.RootDrive(Test)); } [SkippableTheory] @@ -73,7 +73,7 @@ public void GetParent_ArbitraryPaths_ShouldNotBeNull(string path1, [SkippableFact] public void GetParent_Root_ShouldReturnNull() { - string path = FileTestHelper.RootDrive(); + string path = FileTestHelper.RootDrive(Test); IDirectoryInfo? result = FileSystem.Directory.GetParent(path); diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/Tests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/Tests.cs index 61b2d8ed..f86c1606 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/Tests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/Tests.cs @@ -283,7 +283,7 @@ public void Parent_ArbitraryPaths_ShouldNotBeNull(string path1, public void Parent_Root_ShouldBeNull() { IDirectoryInfo sut = - FileSystem.DirectoryInfo.New(FileTestHelper.RootDrive()); + FileSystem.DirectoryInfo.New(FileTestHelper.RootDrive(Test)); sut.Parent.Should().BeNull(); } @@ -342,7 +342,7 @@ public void Parent_ToString_ShouldBeDirectoryNameOnNetFramework( [AutoData] public void Root_Name_ShouldBeCorrect() { - string rootName = FileTestHelper.RootDrive(); + string rootName = FileTestHelper.RootDrive(Test); IDirectoryInfo sut = FileSystem.DirectoryInfo.New(rootName); @@ -354,7 +354,7 @@ public void Root_Name_ShouldBeCorrect() [AutoData] public void Root_ShouldExist(string path) { - string expectedRoot = FileTestHelper.RootDrive(); + string expectedRoot = FileTestHelper.RootDrive(Test); IDirectoryInfo result = FileSystem.DirectoryInfo.New(path); result.Root.Should().Exist(); diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/DriveInfo/Tests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/DriveInfo/Tests.cs index 0255c7a3..32d365c3 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/DriveInfo/Tests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/DriveInfo/Tests.cs @@ -11,7 +11,7 @@ public void VolumeLabel_ShouldBeWritable_OnWindows() Test.SkipIfLongRunningTestsShouldBeSkipped(FileSystem); IDriveInfo result = - FileSystem.DriveInfo.New(FileTestHelper.RootDrive()); + FileSystem.DriveInfo.New(FileTestHelper.RootDrive(Test)); string previousVolumeLabel = result.VolumeLabel; try @@ -50,7 +50,7 @@ public void ToString_ShouldReturnDriveName() Skip.IfNot(Test.RunsOnWindows); IDriveInfo result = - FileSystem.DriveInfo.New(FileTestHelper.RootDrive()); + FileSystem.DriveInfo.New(FileTestHelper.RootDrive(Test)); result.ToString().Should().Be("C:\\"); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/DriveInfoFactory/Tests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/DriveInfoFactory/Tests.cs index fde9c004..d718482f 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/DriveInfoFactory/Tests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/DriveInfoFactory/Tests.cs @@ -63,13 +63,13 @@ public void MissingDrive_WriteAllBytes_ShouldThrowDirectoryNotFoundException( public void New_DefaultDrive_ShouldBeFixed() { IDriveInfo result = - FileSystem.DriveInfo.New(FileTestHelper.RootDrive()); + FileSystem.DriveInfo.New(FileTestHelper.RootDrive(Test)); result.AvailableFreeSpace.Should().BeGreaterThan(0); result.DriveFormat.Should().NotBeNull(); result.DriveType.Should().Be(DriveType.Fixed); result.IsReady.Should().BeTrue(); - result.RootDirectory.FullName.Should().Be(FileTestHelper.RootDrive()); + result.RootDirectory.FullName.Should().Be(FileTestHelper.RootDrive(Test)); result.TotalFreeSpace.Should().BeGreaterThan(0); result.TotalSize.Should().BeGreaterThan(0); result.VolumeLabel.Should().NotBeEmpty(); @@ -111,7 +111,7 @@ public void New_WithRootedPath_ShouldReturnDriveInfo(char driveLetter, string pa { Skip.IfNot(Test.RunsOnWindows, "Linux does not support different drives."); - string rootedPath = FileTestHelper.RootDrive(path, driveLetter); + string rootedPath = FileTestHelper.RootDrive(Test, path, driveLetter); IDriveInfo result = FileSystem.DriveInfo.New(rootedPath); diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/CopyTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/CopyTests.cs index 4f74211e..7dc42e91 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/CopyTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/CopyTests.cs @@ -15,7 +15,7 @@ public void { FileSystem.Initialize() .WithFile(source); - string destination = FileTestHelper.RootDrive("not-existing/path/foo.txt"); + string destination = FileTestHelper.RootDrive(Test, "not-existing/path/foo.txt"); Exception? exception = Record.Exception(() => { diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/ExceptionMissingFileTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/ExceptionMissingFileTests.cs index 6a7cf506..e8ea6ac1 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/ExceptionMissingFileTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/ExceptionMissingFileTests.cs @@ -1,397 +1,471 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -#if FEATURE_FILESYSTEM_ASYNC -using System.Threading; -#endif - -namespace Testably.Abstractions.Tests.FileSystem.File; - -// ReSharper disable once PartialTypeWithSinglePart -public abstract partial class ExceptionMissingFileTests - : FileSystemTestBase - where TFileSystem : IFileSystem -{ - [SkippableTheory] - [MemberData(nameof(GetFileCallbacks), parameters: (int)MissingFileTestCase.FileMissing)] - public void Operations_WhenFileIsMissing_ShouldThrowFileNotFoundException( - Expression> callback) - { - string path = "missing-file.txt"; - - Exception? exception = Record.Exception(() => - { - callback.Compile().Invoke(FileSystem.File, path); - }); - - if (Test.RunsOnWindows) - { - exception.Should().BeException( - hResult: -2147024894, - because: $"\n{callback}\n was called with a missing file"); - } - else - { - exception.Should() - .BeFileOrDirectoryNotFoundException( - $"\n{callback}\n was called with a missing file"); - } - } - - [SkippableTheory] - [MemberData(nameof(GetFileCallbacks), parameters: (int)MissingFileTestCase.DirectoryMissing)] - public void Operations_WhenDirectoryIsMissing_ShouldThrowDirectoryNotFoundException( - Expression> callback) - { - string path = FileSystem.Path.Combine("missing-directory", "file.txt"); - - Exception? exception = Record.Exception(() => - { - callback.Compile().Invoke(FileSystem.File, path); - }); - - if (Test.RunsOnWindows) - { - exception.Should().BeException( - hResult: -2147024893, - because: $"\n{callback}\n was called with a missing directory"); - } - else - { - exception.Should() - .BeFileOrDirectoryNotFoundException( - $"\n{callback}\n was called with a missing directory"); - } - } - - #region Helpers - - [Flags] - public enum MissingFileTestCase - { - FileMissing = 1, - DirectoryMissing = 2, - All = FileMissing | DirectoryMissing - } - - public enum ExpectedExceptionType - { - Default, - } - - public static TheoryData>> GetFileCallbacks(int testCases) - => new TheoryData>>( - GetFileCallbackTestParameters() - .Where(item => (item.TestCase & (MissingFileTestCase)testCases) != 0) - .Select(item => item.Callback)); - - private static IEnumerable<(MissingFileTestCase TestCase, ExpectedExceptionType ExceptionType, - Expression> Callback)> - GetFileCallbackTestParameters() - { - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.GetAttributes(path)); - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.SetAttributes(path, FileAttributes.ReadOnly)); - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.Copy(path, "destination.txt")); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.AppendAllLines(path, new[] - { - "foo" - })); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.AppendAllLines(path, new[] - { - "foo" - })); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.AppendAllLines(path, new[] - { - "foo" - }, Encoding.UTF8)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.AppendAllLinesAsync(path, new[] - { - "foo" - }, CancellationToken.None) - .GetAwaiter().GetResult()); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.AppendAllLinesAsync(path, new[] - { - "foo" - }, Encoding.UTF8, - CancellationToken.None) - .GetAwaiter().GetResult()); -#endif - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.AppendAllText(path, "foo")); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.AppendAllText(path, "foo", Encoding.UTF8)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.AppendAllTextAsync(path, "foo", CancellationToken.None) - .GetAwaiter().GetResult()); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.AppendAllTextAsync(path, "foo", Encoding.UTF8, - CancellationToken.None) - .GetAwaiter().GetResult()); -#endif - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.AppendText(path)); - yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, - (file, path) - => file.Copy(path, "foo")); - yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, - (file, path) - => file.Copy("foo", path)); - yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, - (file, path) - => file.Copy(path, "foo", false)); - yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, - (file, path) - => file.Copy("foo", path, false)); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.Create(path)); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.Create(path, 1023)); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.Create(path, 1023, FileOptions.None)); -#if FEATURE_FILESYSTEM_LINK - if (Test.RunsOnWindows) - { - yield return (MissingFileTestCase.DirectoryMissing, - ExpectedExceptionType.Default, - (file, path) - => file.CreateSymbolicLink(path, "foo")); - } -#endif - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.CreateText(path)); - - if (Test.RunsOnWindows) - { - #pragma warning disable CA1416 - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.Decrypt(path)); - #pragma warning restore CA1416 - } - - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.Delete(path)); - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.GetAttributes(path)); - yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, - (file, path) - => file.Move(path, "foo")); - yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, - (file, path) - => file.Move("foo", path)); -#if FEATURE_FILE_MOVETO_OVERWRITE - yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, - (file, path) - => file.Move(path, "foo", false)); - yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, - (file, path) - => file.Move("foo", path, false)); -#endif - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.Open(path, FileMode.Open)); - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.Open(path, FileMode.Open, FileAccess.ReadWrite)); - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None)); -#if FEATURE_FILESYSTEM_STREAM_OPTIONS - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.Open(path, new FileStreamOptions())); -#endif - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.OpenRead(path)); - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.OpenText(path)); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.OpenWrite(path)); - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadAllBytes(path)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadAllBytesAsync(path, CancellationToken.None) - .GetAwaiter().GetResult()); -#endif - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadAllLines(path)); - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadAllLines(path, Encoding.UTF8)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadAllLinesAsync(path, CancellationToken.None) - .GetAwaiter().GetResult()); - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadAllLinesAsync(path, Encoding.UTF8, CancellationToken.None) - .GetAwaiter().GetResult()); -#endif - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadAllText(path)); - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadAllText(path, Encoding.UTF8)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadAllTextAsync(path, CancellationToken.None) - .GetAwaiter().GetResult()); - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadAllTextAsync(path, Encoding.UTF8, CancellationToken.None) - .GetAwaiter().GetResult()); -#endif - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadLines(path)); - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadLines(path, Encoding.UTF8)); -#if FEATURE_FILESYSTEM_NET7 - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadLinesAsync(path, CancellationToken.None)); - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.ReadLinesAsync(path, Encoding.UTF8, CancellationToken.None)); -#endif -#if FEATURE_FILESYSTEM_LINK - yield return (MissingFileTestCase.All, - ExpectedExceptionType.Default, - (file, path) - => file.ResolveLinkTarget(path, false)); -#endif - yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, - (file, path) - => file.SetAttributes(path, FileAttributes.ReadOnly)); - yield return (MissingFileTestCase.All, - ExpectedExceptionType.Default, - (file, path) - => file.SetCreationTime(path, DateTime.Now)); - yield return (MissingFileTestCase.All, - ExpectedExceptionType.Default, - (file, path) - => file.SetCreationTimeUtc(path, DateTime.Now)); - yield return (MissingFileTestCase.All, - ExpectedExceptionType.Default, - (file, path) - => file.SetLastAccessTime(path, DateTime.Now)); - yield return (MissingFileTestCase.All, - ExpectedExceptionType.Default, - (file, path) - => file.SetLastAccessTimeUtc(path, DateTime.Now)); - yield return (MissingFileTestCase.All, - ExpectedExceptionType.Default, - (file, path) - => file.SetLastWriteTime(path, DateTime.Now)); - yield return (MissingFileTestCase.All, - ExpectedExceptionType.Default, - (file, path) - => file.SetLastWriteTimeUtc(path, DateTime.Now)); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.WriteAllBytes(path, new byte[] - { - 0, 1 - })); -#if FEATURE_FILESYSTEM_ASYNC - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.WriteAllBytesAsync(path, new byte[] - { - 0, 1 - }, - CancellationToken.None) - .GetAwaiter().GetResult()); -#endif - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.WriteAllLines(path, new[] - { - "foo" - })); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.WriteAllLines(path, new[] - { - "foo" - }, Encoding.UTF8)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.WriteAllLinesAsync(path, new[] - { - "foo" - }, CancellationToken.None) - .GetAwaiter().GetResult()); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.WriteAllLinesAsync(path, new[] - { - "foo" - }, Encoding.UTF8, - CancellationToken.None) - .GetAwaiter().GetResult()); -#endif - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.WriteAllText(path, "foo")); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.WriteAllText(path, "foo", Encoding.UTF8)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.WriteAllTextAsync(path, "foo", CancellationToken.None) - .GetAwaiter().GetResult()); - yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, - (file, path) - => file.WriteAllTextAsync(path, "foo", Encoding.UTF8, - CancellationToken.None) - .GetAwaiter().GetResult()); -#endif - } - - #endregion +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +#if FEATURE_FILESYSTEM_ASYNC +using System.Threading; +#endif + +namespace Testably.Abstractions.Tests.FileSystem.File; + +// ReSharper disable once PartialTypeWithSinglePart +public abstract partial class ExceptionMissingFileTests + : FileSystemTestBase + where TFileSystem : IFileSystem +{ + [SkippableTheory] + [MemberData(nameof(GetFileCallbacks), parameters: (int)MissingFileTestCase.DirectoryMissing)] + public void Operations_WhenDirectoryIsMissing_ShouldThrowDirectoryNotFoundException( + Expression> callback, Func skipTest) + { + Skip.If(skipTest(Test)); + + string path = FileSystem.Path.Combine("missing-directory", "file.txt"); + + Exception? exception = Record.Exception(() => + { + callback.Compile().Invoke(FileSystem.File, path); + }); + + if (Test.RunsOnWindows) + { + exception.Should().BeException( + hResult: -2147024893, + because: $"\n{callback}\n was called with a missing directory"); + } + else + { + exception.Should() + .BeFileOrDirectoryNotFoundException( + $"\n{callback}\n was called with a missing directory"); + } + } + + [SkippableTheory] + [MemberData(nameof(GetFileCallbacks), parameters: (int)MissingFileTestCase.FileMissing)] + public void Operations_WhenFileIsMissing_ShouldThrowFileNotFoundException( + Expression> callback, Func skipTest) + { + Skip.If(skipTest(Test)); + + string path = "missing-file.txt"; + + Exception? exception = Record.Exception(() => + { + callback.Compile().Invoke(FileSystem.File, path); + }); + + if (Test.RunsOnWindows) + { + exception.Should().BeException( + hResult: -2147024894, + because: $"\n{callback}\n was called with a missing file"); + } + else + { + exception.Should() + .BeFileOrDirectoryNotFoundException( + $"\n{callback}\n was called with a missing file"); + } + } + + #region Helpers + + public static TheoryData>, Func> GetFileCallbacks( + int testCases) + { + TheoryData>, Func> theoryData = new(); + foreach ((MissingFileTestCase TestCase, ExpectedExceptionType ExceptionType, + Expression> Callback, Func? SkipTest) item in + GetFileCallbackTestParameters() + .Where(item => (item.TestCase & (MissingFileTestCase)testCases) != 0)) + { + theoryData.Add(item.Callback, item.SkipTest ?? (_ => false)); + } + + return theoryData; + } + + private static IEnumerable<(MissingFileTestCase TestCase, ExpectedExceptionType ExceptionType, + Expression> Callback, Func? SkipTest)> + GetFileCallbackTestParameters() + { + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.GetAttributes(path), + null); + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.SetAttributes(path, FileAttributes.ReadOnly), + null); + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.Copy(path, "destination.txt"), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.AppendAllLines(path, new[] + { + "foo" + }), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.AppendAllLines(path, new[] + { + "foo" + }), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.AppendAllLines(path, new[] + { + "foo" + }, Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.AppendAllLinesAsync(path, new[] + { + "foo" + }, CancellationToken.None) + .GetAwaiter().GetResult(), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.AppendAllLinesAsync(path, new[] + { + "foo" + }, Encoding.UTF8, + CancellationToken.None) + .GetAwaiter().GetResult(), + null); +#endif + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.AppendAllText(path, "foo"), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.AppendAllText(path, "foo", Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.AppendAllTextAsync(path, "foo", CancellationToken.None) + .GetAwaiter().GetResult(), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.AppendAllTextAsync(path, "foo", Encoding.UTF8, + CancellationToken.None) + .GetAwaiter().GetResult(), + null); +#endif + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.AppendText(path), + null); + yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, + (file, path) + => file.Copy(path, "foo"), + null); + yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, + (file, path) + => file.Copy("foo", path), + null); + yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, + (file, path) + => file.Copy(path, "foo", false), + null); + yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, + (file, path) + => file.Copy("foo", path, false), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.Create(path), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.Create(path, 1023), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.Create(path, 1023, FileOptions.None), + null); +#if FEATURE_FILESYSTEM_LINK + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.CreateSymbolicLink(path, "foo"), + test => !test.RunsOnWindows); +#endif + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.CreateText(path), + null); + + #pragma warning disable CA1416 + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.Decrypt(path), + test => !test.RunsOnWindows); + #pragma warning restore CA1416 + + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.Delete(path), + null); + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.GetAttributes(path), + null); + yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, + (file, path) + => file.Move(path, "foo"), + null); + yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, + (file, path) + => file.Move("foo", path), + null); +#if FEATURE_FILE_MOVETO_OVERWRITE + yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, + (file, path) + => file.Move(path, "foo", false), + null); + yield return (MissingFileTestCase.FileMissing, ExpectedExceptionType.Default, + (file, path) + => file.Move("foo", path, false), + null); +#endif + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.Open(path, FileMode.Open), + null); + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.Open(path, FileMode.Open, FileAccess.ReadWrite), + null); + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None), + null); +#if FEATURE_FILESYSTEM_STREAM_OPTIONS + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.Open(path, new FileStreamOptions()), + null); +#endif + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.OpenRead(path), + null); + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.OpenText(path), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.OpenWrite(path), + null); + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadAllBytes(path), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadAllBytesAsync(path, CancellationToken.None) + .GetAwaiter().GetResult(), + null); +#endif + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadAllLines(path), + null); + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadAllLines(path, Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadAllLinesAsync(path, CancellationToken.None) + .GetAwaiter().GetResult(), + null); + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadAllLinesAsync(path, Encoding.UTF8, CancellationToken.None) + .GetAwaiter().GetResult(), + null); +#endif + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadAllText(path), + null); + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadAllText(path, Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadAllTextAsync(path, CancellationToken.None) + .GetAwaiter().GetResult(), + null); + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadAllTextAsync(path, Encoding.UTF8, CancellationToken.None) + .GetAwaiter().GetResult(), + null); +#endif + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadLines(path), + null); + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadLines(path, Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_NET7 + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadLinesAsync(path, CancellationToken.None), + null); + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.ReadLinesAsync(path, Encoding.UTF8, CancellationToken.None), + null); +#endif +#if FEATURE_FILESYSTEM_LINK + yield return (MissingFileTestCase.All, + ExpectedExceptionType.Default, + (file, path) + => file.ResolveLinkTarget(path, false), + null); +#endif + yield return (MissingFileTestCase.All, ExpectedExceptionType.Default, + (file, path) + => file.SetAttributes(path, FileAttributes.ReadOnly), + null); + yield return (MissingFileTestCase.All, + ExpectedExceptionType.Default, + (file, path) + => file.SetCreationTime(path, DateTime.Now), + null); + yield return (MissingFileTestCase.All, + ExpectedExceptionType.Default, + (file, path) + => file.SetCreationTimeUtc(path, DateTime.Now), + null); + yield return (MissingFileTestCase.All, + ExpectedExceptionType.Default, + (file, path) + => file.SetLastAccessTime(path, DateTime.Now), + null); + yield return (MissingFileTestCase.All, + ExpectedExceptionType.Default, + (file, path) + => file.SetLastAccessTimeUtc(path, DateTime.Now), + null); + yield return (MissingFileTestCase.All, + ExpectedExceptionType.Default, + (file, path) + => file.SetLastWriteTime(path, DateTime.Now), + null); + yield return (MissingFileTestCase.All, + ExpectedExceptionType.Default, + (file, path) + => file.SetLastWriteTimeUtc(path, DateTime.Now), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.WriteAllBytes(path, new byte[] + { + 0, 1 + }), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.WriteAllBytesAsync(path, new byte[] + { + 0, 1 + }, + CancellationToken.None) + .GetAwaiter().GetResult(), + null); +#endif + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.WriteAllLines(path, new[] + { + "foo" + }), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.WriteAllLines(path, new[] + { + "foo" + }, Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.WriteAllLinesAsync(path, new[] + { + "foo" + }, CancellationToken.None) + .GetAwaiter().GetResult(), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.WriteAllLinesAsync(path, new[] + { + "foo" + }, Encoding.UTF8, + CancellationToken.None) + .GetAwaiter().GetResult(), + null); +#endif + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.WriteAllText(path, "foo"), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.WriteAllText(path, "foo", Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.WriteAllTextAsync(path, "foo", CancellationToken.None) + .GetAwaiter().GetResult(), + null); + yield return (MissingFileTestCase.DirectoryMissing, ExpectedExceptionType.Default, + (file, path) + => file.WriteAllTextAsync(path, "foo", Encoding.UTF8, + CancellationToken.None) + .GetAwaiter().GetResult(), + null); +#endif + } + + #endregion + + public enum ExpectedExceptionType + { + Default, + } + + [Flags] + public enum MissingFileTestCase + { + FileMissing = 1, + DirectoryMissing = 2, + All = FileMissing | DirectoryMissing + } } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/ExceptionTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/ExceptionTests.cs index bc9410eb..38f5081c 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/ExceptionTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/ExceptionTests.cs @@ -1,426 +1,592 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -#if FEATURE_FILESYSTEM_ASYNC -using System.Threading; -#endif - -namespace Testably.Abstractions.Tests.FileSystem.File; - -// ReSharper disable once PartialTypeWithSinglePart -public abstract partial class ExceptionTests - : FileSystemTestBase - where TFileSystem : IFileSystem -{ - [SkippableTheory] - [MemberData(nameof(GetFileCallbacks), parameters: "")] - public void Operations_WhenValueIsEmpty_ShouldThrowArgumentException( - Expression> callback, string paramName, bool ignoreParamCheck) - { - Exception? exception = Record.Exception(() => - { - callback.Compile().Invoke(FileSystem.File); - }); - - exception.Should().BeException( - hResult: -2147024809, - paramName: ignoreParamCheck || Test.IsNetFramework ? null : paramName, - because: - $"\n{callback}\n has empty parameter for '{paramName}' (ignored: {ignoreParamCheck})"); - } - - [SkippableTheory] - [MemberData(nameof(GetFileCallbacks), parameters: " ")] - public void Operations_WhenValueIsWhitespace_ShouldThrowArgumentException( - Expression> callback, string paramName, bool ignoreParamCheck) - { - Skip.IfNot(Test.RunsOnWindows); - - Exception? exception = Record.Exception(() => - { - callback.Compile().Invoke(FileSystem.File); - }); - - exception.Should().BeException( - hResult: -2147024809, - paramName: ignoreParamCheck || Test.IsNetFramework ? null : paramName, - because: - $"\n{callback}\n has whitespace parameter for '{paramName}' (ignored: {ignoreParamCheck})"); - } - - [SkippableTheory] - [MemberData(nameof(GetFileCallbacks), parameters: (string?)null)] - public void Operations_WhenValueIsNull_ShouldThrowArgumentNullException( - Expression> callback, string paramName, bool ignoreParamCheck) - { - Exception? exception = Record.Exception(() => - { - callback.Compile().Invoke(FileSystem.File); - }); - - exception.Should().BeException( - paramName: ignoreParamCheck ? null : paramName, - because: - $"\n{callback}\n has `null` parameter for '{paramName}' (ignored: {ignoreParamCheck})"); - } - - [SkippableTheory] - [MemberData(nameof(GetFileCallbacks), parameters: "Illegal\tCharacter?InPath")] - public void - Operations_WhenValueContainsIllegalPathCharacters_ShouldThrowCorrectException_OnWindows( - Expression> callback, string paramName, bool ignoreParamCheck) - { - Exception? exception = Record.Exception(() => - { - callback.Compile().Invoke(FileSystem.File); - }); - - if (!Test.RunsOnWindows) - { - if (exception is IOException ioException) - { - ioException.HResult.Should().NotBe(-2147024809, - $"\n{callback}\n contains invalid path characters for '{paramName}' (ignored: {ignoreParamCheck})"); - } - } - else - { - if (Test.IsNetFramework) - { - exception.Should().BeException( - hResult: -2147024809, - because: - $"\n{callback}\n contains invalid path characters for '{paramName}' (ignored: {ignoreParamCheck})"); - } - else - { - exception.Should().BeException( - hResult: -2147024773, - because: - $"\n{callback}\n contains invalid path characters for '{paramName}' (ignored: {ignoreParamCheck})"); - } - } - } - - #region Helpers - - public static TheoryData>, string, bool> GetFileCallbacks(string? path) - { - TheoryData>, string, bool> theoryData = new(); - foreach (var item in GetFileCallbackTestParameters(path!) - .Where(item => item.TestType.HasFlag(path.ToTestType()))) - { - theoryData.Add( - item.Callback, - item.ParamName, - item.TestType.HasFlag(ExceptionTestHelper.TestTypes.IgnoreParamNameCheck)); - } - return theoryData; - } - - private static IEnumerable<(ExceptionTestHelper.TestTypes TestType, string ParamName, - Expression> Callback)> - GetFileCallbackTestParameters(string value) - { - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.AppendAllLines(value, new[] - { - "foo" - })); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.AppendAllLines(value, new[] - { - "foo" - }, Encoding.UTF8)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.AppendAllLinesAsync(value, new[] - { - "foo" - }, CancellationToken.None) - .GetAwaiter().GetResult()); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.AppendAllLinesAsync(value, new[] - { - "foo" - }, Encoding.UTF8, - CancellationToken.None).GetAwaiter().GetResult()); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.AppendAllText(value, "foo")); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.AppendAllText(value, "foo", Encoding.UTF8)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.AppendAllTextAsync(value, "foo", CancellationToken.None).GetAwaiter() - .GetResult()); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.AppendAllTextAsync(value, "foo", Encoding.UTF8, - CancellationToken.None).GetAwaiter().GetResult()); -#endif - yield return (ExceptionTestHelper.TestTypes.NullOrInvalidPath, "path", file - => file.AppendText(value)); - yield return (ExceptionTestHelper.TestTypes.AllExceptWhitespace, "sourceFileName", - file - => file.Copy(value, "foo")); - yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "destFileName", file - => file.Copy("foo", value)); - yield return (ExceptionTestHelper.TestTypes.AllExceptWhitespace, "sourceFileName", - file - => file.Copy(value, "foo", false)); - yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "destFileName", file - => file.Copy("foo", value, false)); - yield return ( - ExceptionTestHelper.TestTypes.Whitespace | - ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "sourceFileName", file - => file.Copy(value, "foo")); - yield return ( - ExceptionTestHelper.TestTypes.Whitespace | - ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "destFileName", file - => file.Copy("foo", value)); - yield return ( - ExceptionTestHelper.TestTypes.Whitespace | - ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "sourceFileName", file - => file.Copy(value, "foo", false)); - yield return ( - ExceptionTestHelper.TestTypes.Whitespace | - ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "destFileName", file - => file.Copy("foo", value, false)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.Create(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.Create(value, 1023)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.Create(value, 1023, FileOptions.None)); -#if FEATURE_FILESYSTEM_LINK - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.CreateSymbolicLink(value, "foo")); -#endif - yield return (ExceptionTestHelper.TestTypes.NullOrInvalidPath, "path", file - => file.CreateText(value)); - - if (Test.RunsOnWindows) - { - #pragma warning disable CA1416 - yield return (ExceptionTestHelper.TestTypes.AllExceptInvalidPath, "path", file - => file.Decrypt(value)); - #pragma warning restore CA1416 - } - - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.Delete(value)); - if (Test.RunsOnWindows) - { - #pragma warning disable CA1416 - yield return (ExceptionTestHelper.TestTypes.AllExceptInvalidPath, "path", file - => file.Encrypt(value)); - #pragma warning restore CA1416 - } - - // `File.Exists` doesn't throw an exception on `null` - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.GetAttributes(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.GetCreationTime(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.GetCreationTimeUtc(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.GetLastAccessTime(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.GetLastAccessTimeUtc(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.GetLastWriteTime(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.GetLastWriteTimeUtc(value)); -#if FEATURE_FILESYSTEM_UNIXFILEMODE - if (!Test.RunsOnWindows) - { - #pragma warning disable CA1416 - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.GetUnixFileMode(value)); - #pragma warning restore CA1416 - } -#endif - yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "sourceFileName", file - => file.Move(value, "foo")); - yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "destFileName", file - => file.Move("foo", value)); - yield return ( - ExceptionTestHelper.TestTypes.Whitespace | - ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "sourceFileName", file - => file.Move(value, "foo")); - yield return ( - ExceptionTestHelper.TestTypes.Whitespace | - ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "destFileName", file - => file.Move("foo", value)); -#if FEATURE_FILE_MOVETO_OVERWRITE - yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "sourceFileName", file - => file.Move(value, "foo", false)); - yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "destFileName", file - => file.Move("foo", value, false)); - yield return ( - ExceptionTestHelper.TestTypes.Whitespace | - ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "sourceFileName", file - => file.Move(value, "foo", false)); - yield return ( - ExceptionTestHelper.TestTypes.Whitespace | - ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "destFileName", file - => file.Move("foo", value, false)); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.Open(value, FileMode.Open)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.Open(value, FileMode.Open, FileAccess.ReadWrite)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.Open(value, FileMode.Open, FileAccess.ReadWrite, FileShare.None)); -#if FEATURE_FILESYSTEM_STREAM_OPTIONS - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.Open(value, new FileStreamOptions())); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.OpenRead(value)); - yield return (ExceptionTestHelper.TestTypes.NullOrInvalidPath, "path", file - => file.OpenText(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.OpenWrite(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadAllBytes(value)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadAllBytesAsync(value, CancellationToken.None).GetAwaiter() - .GetResult()); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadAllLines(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadAllLines(value, Encoding.UTF8)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadAllLinesAsync(value, CancellationToken.None).GetAwaiter() - .GetResult()); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadAllLinesAsync(value, Encoding.UTF8, CancellationToken.None) - .GetAwaiter().GetResult()); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadAllText(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadAllText(value, Encoding.UTF8)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadAllTextAsync(value, CancellationToken.None).GetAwaiter() - .GetResult()); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadAllTextAsync(value, Encoding.UTF8, CancellationToken.None) - .GetAwaiter().GetResult()); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadLines(value)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadLines(value, Encoding.UTF8)); -#if FEATURE_FILESYSTEM_NET7 - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadLinesAsync(value, CancellationToken.None)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.ReadLinesAsync(value, Encoding.UTF8, CancellationToken.None)); -#endif - yield return ( - ExceptionTestHelper.TestTypes.AllExceptInvalidPath | - ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "sourceFileName", file - => file.Replace(value, "foo", "bar")); - yield return ( - ExceptionTestHelper.TestTypes.All | - ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "destinationFileName", - file - => file.Replace("foo", value, "bar")); - yield return ( - ExceptionTestHelper.TestTypes.AllExceptInvalidPath | - ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "sourceFileName", file - => file.Replace(value, "foo", "bar", false)); - yield return ( - ExceptionTestHelper.TestTypes.All | - ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "destinationFileName", - file - => file.Replace("foo", value, "bar", false)); -#if FEATURE_FILESYSTEM_LINK - yield return (ExceptionTestHelper.TestTypes.AllExceptWhitespace, "linkPath", file - => file.ResolveLinkTarget(value, false)); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.SetAttributes(value, FileAttributes.ReadOnly)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.SetCreationTime(value, DateTime.Now)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.SetCreationTimeUtc(value, DateTime.Now)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.SetLastAccessTime(value, DateTime.Now)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.SetLastAccessTimeUtc(value, DateTime.Now)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.SetLastWriteTime(value, DateTime.Now)); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.SetLastWriteTimeUtc(value, DateTime.Now)); -#if FEATURE_FILESYSTEM_UNIXFILEMODE - if (!Test.RunsOnWindows) - { - #pragma warning disable CA1416 - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.SetUnixFileMode(value, UnixFileMode.None)); - #pragma warning restore CA1416 - } -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.WriteAllBytes(value, new byte[] - { - 0, 1 - })); -#if FEATURE_FILESYSTEM_ASYNC - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.WriteAllBytesAsync(value, new byte[] - { - 0, 1 - }, - CancellationToken.None).GetAwaiter().GetResult()); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.WriteAllLines(value, new[] - { - "foo" - })); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.WriteAllLines(value, new[] - { - "foo" - }, Encoding.UTF8)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.WriteAllLinesAsync(value, new[] - { - "foo" - }, CancellationToken.None) - .GetAwaiter().GetResult()); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.WriteAllLinesAsync(value, new[] - { - "foo" - }, Encoding.UTF8, - CancellationToken.None).GetAwaiter().GetResult()); -#endif - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.WriteAllText(value, "foo")); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.WriteAllText(value, "foo", Encoding.UTF8)); -#if FEATURE_FILESYSTEM_ASYNC - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.WriteAllTextAsync(value, "foo", CancellationToken.None).GetAwaiter() - .GetResult()); - yield return (ExceptionTestHelper.TestTypes.All, "path", file - => file.WriteAllTextAsync(value, "foo", Encoding.UTF8, - CancellationToken.None).GetAwaiter().GetResult()); -#endif - } - - #endregion -} +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +#if FEATURE_FILESYSTEM_ASYNC +using System.Threading; +#endif + +namespace Testably.Abstractions.Tests.FileSystem.File; + +// ReSharper disable once PartialTypeWithSinglePart +public abstract partial class ExceptionTests + : FileSystemTestBase + where TFileSystem : IFileSystem +{ + [SkippableTheory] + [MemberData(nameof(GetFileCallbacks), parameters: "Illegal\tCharacter?InPath")] + public void + Operations_WhenValueContainsIllegalPathCharacters_ShouldThrowCorrectException_OnWindows( + Expression> callback, string paramName, bool ignoreParamCheck, + Func skipTest) + { + Skip.If(skipTest(Test)); + + Exception? exception = Record.Exception(() => + { + callback.Compile().Invoke(FileSystem.File); + }); + + if (!Test.RunsOnWindows) + { + if (exception is IOException ioException) + { + ioException.HResult.Should().NotBe(-2147024809, + $"\n{callback}\n contains invalid path characters for '{paramName}' (ignored: {ignoreParamCheck})"); + } + } + else + { + if (Test.IsNetFramework) + { + exception.Should().BeException( + hResult: -2147024809, + because: + $"\n{callback}\n contains invalid path characters for '{paramName}' (ignored: {ignoreParamCheck})"); + } + else + { + exception.Should().BeException( + hResult: -2147024773, + because: + $"\n{callback}\n contains invalid path characters for '{paramName}' (ignored: {ignoreParamCheck})"); + } + } + } + + [SkippableTheory] + [MemberData(nameof(GetFileCallbacks), parameters: "")] + public void Operations_WhenValueIsEmpty_ShouldThrowArgumentException( + Expression> callback, string paramName, bool ignoreParamCheck, + Func skipTest) + { + Skip.If(skipTest(Test)); + + Exception? exception = Record.Exception(() => + { + callback.Compile().Invoke(FileSystem.File); + }); + + exception.Should().BeException( + hResult: -2147024809, + paramName: ignoreParamCheck || Test.IsNetFramework ? null : paramName, + because: + $"\n{callback}\n has empty parameter for '{paramName}' (ignored: {ignoreParamCheck})"); + } + + [SkippableTheory] + [MemberData(nameof(GetFileCallbacks), parameters: (string?)null)] + public void Operations_WhenValueIsNull_ShouldThrowArgumentNullException( + Expression> callback, string paramName, bool ignoreParamCheck, + Func skipTest) + { + Skip.If(skipTest(Test)); + + Exception? exception = Record.Exception(() => + { + callback.Compile().Invoke(FileSystem.File); + }); + + exception.Should().BeException( + paramName: ignoreParamCheck ? null : paramName, + because: + $"\n{callback}\n has `null` parameter for '{paramName}' (ignored: {ignoreParamCheck})"); + } + + [SkippableTheory] + [MemberData(nameof(GetFileCallbacks), parameters: " ")] + public void Operations_WhenValueIsWhitespace_ShouldThrowArgumentException( + Expression> callback, string paramName, bool ignoreParamCheck, + Func skipTest) + { + Skip.If(skipTest(Test)); + Skip.IfNot(Test.RunsOnWindows); + + Exception? exception = Record.Exception(() => + { + callback.Compile().Invoke(FileSystem.File); + }); + + exception.Should().BeException( + hResult: -2147024809, + paramName: ignoreParamCheck || Test.IsNetFramework ? null : paramName, + because: + $"\n{callback}\n has whitespace parameter for '{paramName}' (ignored: {ignoreParamCheck})"); + } + + #region Helpers + + public static TheoryData>, string, bool, Func> + GetFileCallbacks(string? path) + { + TheoryData>, string, bool, Func> theoryData = new(); + foreach ((ExceptionTestHelper.TestTypes TestType, string ParamName, + Expression> Callback, Func? SkipTest) item in + GetFileCallbackTestParameters(path!) + .Where(item => item.TestType.HasFlag(path.ToTestType()))) + { + theoryData.Add( + item.Callback, + item.ParamName, + item.TestType.HasFlag(ExceptionTestHelper.TestTypes.IgnoreParamNameCheck), + item.SkipTest ?? (_ => false)); + } + + return theoryData; + } + + private static IEnumerable<(ExceptionTestHelper.TestTypes TestType, string ParamName, + Expression> Callback, Func? SkipTest)> + GetFileCallbackTestParameters(string value) + { + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.AppendAllLines(value, new[] + { + "foo" + }), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.AppendAllLines(value, new[] + { + "foo" + }, Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.AppendAllLinesAsync(value, new[] + { + "foo" + }, CancellationToken.None) + .GetAwaiter().GetResult(), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.AppendAllLinesAsync(value, new[] + { + "foo" + }, Encoding.UTF8, + CancellationToken.None).GetAwaiter().GetResult(), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.AppendAllText(value, "foo"), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.AppendAllText(value, "foo", Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.AppendAllTextAsync(value, "foo", CancellationToken.None) + .GetAwaiter().GetResult(), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.AppendAllTextAsync(value, "foo", Encoding.UTF8, CancellationToken.None) + .GetAwaiter().GetResult(), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.NullOrInvalidPath, "path", + file + => file.AppendText(value), + null); + yield return (ExceptionTestHelper.TestTypes.AllExceptWhitespace, "sourceFileName", + file + => file.Copy(value, "foo"), + null); + yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "destFileName", + file + => file.Copy("foo", value), + null); + yield return (ExceptionTestHelper.TestTypes.AllExceptWhitespace, "sourceFileName", + file + => file.Copy(value, "foo", false), + null); + yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "destFileName", + file + => file.Copy("foo", value, false), null); + yield return ( + ExceptionTestHelper.TestTypes.Whitespace | + ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "sourceFileName", + file + => file.Copy(value, "foo"), + null); + yield return ( + ExceptionTestHelper.TestTypes.Whitespace | + ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "destFileName", + file + => file.Copy("foo", value), + null); + yield return ( + ExceptionTestHelper.TestTypes.Whitespace | + ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "sourceFileName", + file + => file.Copy(value, "foo", false), + null); + yield return ( + ExceptionTestHelper.TestTypes.Whitespace | + ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "destFileName", + file + => file.Copy("foo", value, false), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.Create(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.Create(value, 1023), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.Create(value, 1023, FileOptions.None), + null); +#if FEATURE_FILESYSTEM_LINK + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.CreateSymbolicLink(value, "foo"), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.NullOrInvalidPath, "path", + file + => file.CreateText(value), + null); + #pragma warning disable CA1416 + yield return (ExceptionTestHelper.TestTypes.AllExceptInvalidPath, "path", + file + => file.Decrypt(value), + test => !test.RunsOnWindows); + #pragma warning restore CA1416 + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.Delete(value), + null); + #pragma warning disable CA1416 + yield return (ExceptionTestHelper.TestTypes.AllExceptInvalidPath, "path", + file + => file.Encrypt(value), + test => !test.RunsOnWindows); + #pragma warning restore CA1416 + // `File.Exists` doesn't throw an exception on `null` + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.GetAttributes(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.GetCreationTime(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.GetCreationTimeUtc(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.GetLastAccessTime(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.GetLastAccessTimeUtc(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.GetLastWriteTime(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.GetLastWriteTimeUtc(value), + null); +#if FEATURE_FILESYSTEM_UNIXFILEMODE + #pragma warning disable CA1416 + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.GetUnixFileMode(value), + test => test.RunsOnWindows); + #pragma warning restore CA1416 +#endif + yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "sourceFileName", + file + => file.Move(value, "foo"), + null); + yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "destFileName", + file + => file.Move("foo", value), + null); + yield return ( + ExceptionTestHelper.TestTypes.Whitespace | + ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "sourceFileName", + file + => file.Move(value, "foo"), + null); + yield return ( + ExceptionTestHelper.TestTypes.Whitespace | + ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "destFileName", + file + => file.Move("foo", value), + null); +#if FEATURE_FILE_MOVETO_OVERWRITE + yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "sourceFileName", + file + => file.Move(value, "foo", false), + null); + yield return (ExceptionTestHelper.TestTypes.NullOrEmpty, "destFileName", + file + => file.Move("foo", value, false), + null); + yield return ( + ExceptionTestHelper.TestTypes.Whitespace | + ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "sourceFileName", + file + => file.Move(value, "foo", false), + null); + yield return ( + ExceptionTestHelper.TestTypes.Whitespace | + ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "destFileName", + file + => file.Move("foo", value, false), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.Open(value, FileMode.Open), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.Open(value, FileMode.Open, FileAccess.ReadWrite), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.Open(value, FileMode.Open, FileAccess.ReadWrite, FileShare.None), + null); +#if FEATURE_FILESYSTEM_STREAM_OPTIONS + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.Open(value, new FileStreamOptions()), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.OpenRead(value), + null); + yield return (ExceptionTestHelper.TestTypes.NullOrInvalidPath, "path", + file + => file.OpenText(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.OpenWrite(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadAllBytes(value), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadAllBytesAsync(value, CancellationToken.None) + .GetAwaiter().GetResult(), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadAllLines(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadAllLines(value, Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadAllLinesAsync(value, CancellationToken.None) + .GetAwaiter().GetResult(), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadAllLinesAsync(value, Encoding.UTF8, CancellationToken.None) + .GetAwaiter().GetResult(), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadAllText(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadAllText(value, Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadAllTextAsync(value, CancellationToken.None) + .GetAwaiter().GetResult(), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadAllTextAsync(value, Encoding.UTF8, CancellationToken.None) + .GetAwaiter().GetResult(), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadLines(value), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadLines(value, Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_NET7 + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadLinesAsync(value, CancellationToken.None), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.ReadLinesAsync(value, Encoding.UTF8, CancellationToken.None), + null); +#endif + yield return ( + ExceptionTestHelper.TestTypes.AllExceptInvalidPath | + ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "sourceFileName", + file + => file.Replace(value, "foo", "bar"), + null); + yield return ( + ExceptionTestHelper.TestTypes.All | + ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "destinationFileName", + file + => file.Replace("foo", value, "bar"), + null); + yield return ( + ExceptionTestHelper.TestTypes.AllExceptInvalidPath | + ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "sourceFileName", + file + => file.Replace(value, "foo", "bar", false), + null); + yield return ( + ExceptionTestHelper.TestTypes.All | + ExceptionTestHelper.TestTypes.IgnoreParamNameCheck, "destinationFileName", + file + => file.Replace("foo", value, "bar", false), + null); +#if FEATURE_FILESYSTEM_LINK + yield return (ExceptionTestHelper.TestTypes.AllExceptWhitespace, "linkPath", + file + => file.ResolveLinkTarget(value, false), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.SetAttributes(value, FileAttributes.ReadOnly), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.SetCreationTime(value, DateTime.Now), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.SetCreationTimeUtc(value, DateTime.Now), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.SetLastAccessTime(value, DateTime.Now), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.SetLastAccessTimeUtc(value, DateTime.Now), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.SetLastWriteTime(value, DateTime.Now), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.SetLastWriteTimeUtc(value, DateTime.Now), + null); +#if FEATURE_FILESYSTEM_UNIXFILEMODE + #pragma warning disable CA1416 + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.SetUnixFileMode(value, UnixFileMode.None), + test => test.RunsOnWindows); + #pragma warning restore CA1416 +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.WriteAllBytes(value, new byte[] + { + 0, 1 + }), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.WriteAllBytesAsync(value, new byte[] + { + 0, 1 + }, + CancellationToken.None).GetAwaiter().GetResult(), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.WriteAllLines(value, new[] + { + "foo" + }), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.WriteAllLines(value, new[] + { + "foo" + }, Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.WriteAllLinesAsync(value, new[] + { + "foo" + }, CancellationToken.None) + .GetAwaiter().GetResult(), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.WriteAllLinesAsync(value, new[] + { + "foo" + }, Encoding.UTF8, + CancellationToken.None).GetAwaiter().GetResult(), + null); +#endif + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.WriteAllText(value, "foo"), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.WriteAllText(value, "foo", Encoding.UTF8), + null); +#if FEATURE_FILESYSTEM_ASYNC + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.WriteAllTextAsync(value, "foo", CancellationToken.None) + .GetAwaiter().GetResult(), + null); + yield return (ExceptionTestHelper.TestTypes.All, "path", + file + => file.WriteAllTextAsync(value, "foo", Encoding.UTF8, CancellationToken.None) + .GetAwaiter().GetResult(), + null); +#endif + } + + #endregion +} diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/MoveTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/MoveTests.cs index c1e9dd7f..4b85484e 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/MoveTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/MoveTests.cs @@ -36,7 +36,7 @@ public void { FileSystem.Initialize() .WithFile(source); - string destination = FileTestHelper.RootDrive("not-existing/path"); + string destination = FileTestHelper.RootDrive(Test, "not-existing/path"); Exception? exception = Record.Exception(() => { diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/ReplaceTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/ReplaceTests.cs index d543ca68..2609bf0e 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/ReplaceTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/ReplaceTests.cs @@ -15,7 +15,7 @@ public void { FileSystem.Initialize() .WithFile(source); - string destination = FileTestHelper.RootDrive("not-existing/path/foo.txt"); + string destination = FileTestHelper.RootDrive(Test, "not-existing/path/foo.txt"); Exception? exception = Record.Exception(() => { diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/File/ResolveLinkTargetTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/File/ResolveLinkTargetTests.cs index f2e63b8e..18e0480a 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/File/ResolveLinkTargetTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/File/ResolveLinkTargetTests.cs @@ -14,7 +14,7 @@ public abstract partial class ResolveLinkTargetTests /// The maximum number of symbolic links that are followed.
/// /// - private static int MaxResolveLinks => + private int MaxResolveLinks => Test.RunsOnWindows ? 63 : 40; #endregion diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/FileInfoFactory/Tests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/FileInfoFactory/Tests.cs index 5c0af17b..32040872 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/FileInfoFactory/Tests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/FileInfoFactory/Tests.cs @@ -13,7 +13,7 @@ public abstract partial class Tests public void New_PathTooLong_ShouldThrowPathTooLongException_OnNetFramework( int maxLength) { - string rootDrive = FileTestHelper.RootDrive(); + string rootDrive = FileTestHelper.RootDrive(Test); string path = new('a', maxLength - rootDrive.Length); Exception? exception = Record.Exception(() => { diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/FileSystemInfo/ResolveLinkTargetTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/FileSystemInfo/ResolveLinkTargetTests.cs index f5d867e5..2de9d8fa 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/FileSystemInfo/ResolveLinkTargetTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/FileSystemInfo/ResolveLinkTargetTests.cs @@ -14,7 +14,7 @@ public abstract partial class ResolveLinkTargetTests /// The maximum number of symbolic links that are followed.
/// /// - private static int MaxResolveLinks => + private int MaxResolveLinks => Test.RunsOnWindows ? 63 : 40; #endregion diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/Path/GetFullPathTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/Path/GetFullPathTests.cs index 2ffecf0d..81fcaf49 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/Path/GetFullPathTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/Path/GetFullPathTests.cs @@ -54,10 +54,10 @@ public void [InlineData(@"top/../../most/file", @"most/file")] public void GetFullPath_ShouldNormalizeProvidedPath(string input, string expected) { - string expectedRootedPath = FileTestHelper.RootDrive( + string expectedRootedPath = FileTestHelper.RootDrive(Test, expected.Replace('/', FileSystem.Path.DirectorySeparatorChar)); - string result = FileSystem.Path.GetFullPath(FileTestHelper.RootDrive(input)); + string result = FileSystem.Path.GetFullPath(FileTestHelper.RootDrive(Test, input)); result.Should().Be(expectedRootedPath); } @@ -70,10 +70,10 @@ public void GetFullPath_ShouldNormalizeProvidedPath(string input, string expecte public void GetFullPath_Relative_ShouldNormalizeProvidedPath(string input, string basePath, string expected) { - string expectedRootedPath = FileTestHelper.RootDrive( + string expectedRootedPath = FileTestHelper.RootDrive(Test, expected.Replace('/', FileSystem.Path.DirectorySeparatorChar)); - string result = FileSystem.Path.GetFullPath(input, FileTestHelper.RootDrive(basePath)); + string result = FileSystem.Path.GetFullPath(input, FileTestHelper.RootDrive(Test, basePath)); result.Should().Be(expectedRootedPath); } diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/Path/GetRelativePathTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/Path/GetRelativePathTests.cs index e4baa0f9..693c2efb 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/Path/GetRelativePathTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/Path/GetRelativePathTests.cs @@ -27,8 +27,8 @@ public void GetRelativePath_DifferentDrives_ShouldReturnAbsolutePath( { Skip.IfNot(Test.RunsOnWindows, "Different drives are only supported on Windows"); - path1 = FileTestHelper.RootDrive(path1, 'A'); - path2 = FileTestHelper.RootDrive(path2, 'B'); + path1 = FileTestHelper.RootDrive(Test, path1, 'A'); + path2 = FileTestHelper.RootDrive(Test, path2, 'B'); string result = FileSystem.Path.GetRelativePath(path1, path2); result.Should().Be(path2); @@ -51,7 +51,7 @@ public void GetRelativePath_FromAbsolutePathInCurrentDirectory_ShouldReturnRelat public void GetRelativePath_RootedPath_ShouldReturnAbsolutePath( string baseDirectory, string directory1, string directory2) { - baseDirectory = FileTestHelper.RootDrive(baseDirectory); + baseDirectory = FileTestHelper.RootDrive(Test, baseDirectory); string path1 = FileSystem.Path.Combine(baseDirectory, directory1); string path2 = FileSystem.Path.Combine(baseDirectory, directory2); string expectedRelativePath = FileSystem.Path.Combine("..", directory2); diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/Path/IsPathFullyQualifiedTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/Path/IsPathFullyQualifiedTests.cs index 6d6bca3b..b0f756c5 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/Path/IsPathFullyQualifiedTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/Path/IsPathFullyQualifiedTests.cs @@ -11,7 +11,7 @@ public abstract partial class IsPathFullyQualifiedTests public void IsPathFullyQualified_PrefixedRoot_ShouldReturnTrue( string directory) { - string path = FileTestHelper.RootDrive(directory); + string path = FileTestHelper.RootDrive(Test, directory); bool result = FileSystem.Path.IsPathFullyQualified(path); result.Should().BeTrue(); @@ -33,7 +33,7 @@ public void IsPathFullyQualified_WithoutPrefixedRoot_ShouldReturnFalse( public void IsPathFullyQualified_Span_PrefixedRoot_ShouldReturnTrue( string directory) { - string path = FileTestHelper.RootDrive(directory); + string path = FileTestHelper.RootDrive(Test, directory); bool result = FileSystem.Path.IsPathFullyQualified(path.AsSpan()); result.Should().BeTrue(); diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/Path/TrimEndingDirectorySeparatorTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/Path/TrimEndingDirectorySeparatorTests.cs index 8fddb015..04b0a5a5 100644 --- a/Tests/Testably.Abstractions.Tests/FileSystem/Path/TrimEndingDirectorySeparatorTests.cs +++ b/Tests/Testably.Abstractions.Tests/FileSystem/Path/TrimEndingDirectorySeparatorTests.cs @@ -21,7 +21,7 @@ public void TrimEndingDirectorySeparator_DirectoryChar_ShouldTrim( [SkippableFact] public void TrimEndingDirectorySeparator_Root_ShouldReturnUnchanged() { - string path = FileTestHelper.RootDrive(); + string path = FileTestHelper.RootDrive(Test); string result = FileSystem.Path.TrimEndingDirectorySeparator(path); @@ -44,7 +44,7 @@ public void TrimEndingDirectorySeparator_Span_DirectoryChar_ShouldTrim( [SkippableFact] public void TrimEndingDirectorySeparator_Span_Root_ShouldReturnUnchanged() { - string path = FileTestHelper.RootDrive(); + string path = FileTestHelper.RootDrive(Test); ReadOnlySpan result = FileSystem.Path.TrimEndingDirectorySeparator(path.AsSpan()); diff --git a/Tests/Testably.Abstractions.Tests/TestHelpers/FileTestHelper.cs b/Tests/Testably.Abstractions.Tests/TestHelpers/FileTestHelper.cs index 7ee2b2bd..0c94dbbc 100644 --- a/Tests/Testably.Abstractions.Tests/TestHelpers/FileTestHelper.cs +++ b/Tests/Testably.Abstractions.Tests/TestHelpers/FileTestHelper.cs @@ -68,9 +68,9 @@ public static FileShare CheckFileShare(IFileSystem fileSystem, string path) return fileShare; } - public static string RootDrive(string path = "", char driveLetter = 'C') + public static string RootDrive(Test test, string path = "", char driveLetter = 'C') { - if (Test.RunsOnWindows) + if (test.RunsOnWindows) { return $"{driveLetter}:\\{path}"; }