From 2d5bb5b1d204ae3972fbd06f13b3d3d59a668ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Sun, 21 Apr 2024 08:53:22 +0200 Subject: [PATCH 1/5] Enable simulated tests for all file system methods --- .../FileSystemClassGenerator.cs | 26 +------------------ 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs b/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs index 1e1ea7684..266d4e614 100644 --- a/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs +++ b/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Text; using Testably.Abstractions.Tests.SourceGenerator.Model; // ReSharper disable StringLiteralTypo @@ -260,30 +259,7 @@ public override void SkipIfLongRunningTestsShouldBeSkipped() private bool IncludeSimulatedTests(ClassModel @class) { - string[] supportedPathTests = - [ - "ChangeExtensionTests", - "CombineTests", - "EndsInDirectorySeparatorTests", - "GetDirectoryNameTests", - "GetExtensionTests", - "GetFileNameTests", - "GetFileNameWithoutExtensionTests", - "GetFullPathTests", - "GetPathRootTests", - "GetRandomFileNameTests", - "GetRelativePathTests", - "GetTempFileNameTests", - "GetTempPathTests", - "HasExtensionTests", - "IsPathRootedTests", - "JoinTests", - "Tests", - "TrimEndingDirectorySeparatorTests", - "TryJoinTests" - ]; return @class.Namespace - .StartsWith("Testably.Abstractions.Tests.FileSystem.Path", StringComparison.Ordinal) - && supportedPathTests.Contains(@class.Name); + .StartsWith("Testably.Abstractions.Tests.FileSystem", StringComparison.Ordinal); } } From abbe0244656fcf52ceb52e505b74c06ef016fc2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Sun, 21 Apr 2024 08:57:16 +0200 Subject: [PATCH 2/5] Make simulation functionality public and throw a NotSupportedException on .NET Framework --- Feature.Flags.props | 1 + .../Helpers/Execute.cs | 3 ++ .../MockFileSystem.cs | 33 +++++++++++++++---- .../Testably.Abstractions.Testing.csproj | 3 -- .../Testably.Abstractions.Testing_net6.0.txt | 9 ++++- .../Testably.Abstractions.Testing_net7.0.txt | 9 ++++- .../Testably.Abstractions.Testing_net8.0.txt | 9 ++++- ...ly.Abstractions.Testing_netstandard2.0.txt | 10 +++++- ...ly.Abstractions.Testing_netstandard2.1.txt | 9 ++++- .../FileSystemClassGenerator.cs | 20 ++++------- .../FileSystem/PathMockTests.cs | 2 ++ .../MockFileSystemInitializationTests.cs | 15 ++++----- .../MockFileSystemTests.cs | 19 +++++++++++ 13 files changed, 104 insertions(+), 38 deletions(-) diff --git a/Feature.Flags.props b/Feature.Flags.props index 45e5226ad..1aa72f401 100644 --- a/Feature.Flags.props +++ b/Feature.Flags.props @@ -7,6 +7,7 @@ 1 $(DefineConstants);NETFRAMEWORK + $(DefineConstants);CAN_SIMULATE_OTHER_OS $(DefineConstants);FEATURE_FILESYSTEM_ASYNC $(DefineConstants);FEATURE_FILESYSTEM_ENUMERATION_OPTIONS $(DefineConstants);FEATURE_PATH_JOIN diff --git a/Source/Testably.Abstractions.Testing/Helpers/Execute.cs b/Source/Testably.Abstractions.Testing/Helpers/Execute.cs index 3bedf516b..c0b479a5c 100644 --- a/Source/Testably.Abstractions.Testing/Helpers/Execute.cs +++ b/Source/Testably.Abstractions.Testing/Helpers/Execute.cs @@ -40,6 +40,9 @@ internal partial class Execute /// public StringComparison StringComparisonMode { get; } +#if !CAN_SIMULATE_OTHER_OS + [Obsolete("Simulating other operating systems is not supported on .NET Framework")] +#endif internal Execute(MockFileSystem fileSystem, SimulationMode simulationMode) { IsLinux = simulationMode == SimulationMode.Linux; diff --git a/Source/Testably.Abstractions.Testing/MockFileSystem.cs b/Source/Testably.Abstractions.Testing/MockFileSystem.cs index a33520a48..7eee1c2e0 100644 --- a/Source/Testably.Abstractions.Testing/MockFileSystem.cs +++ b/Source/Testably.Abstractions.Testing/MockFileSystem.cs @@ -97,18 +97,29 @@ public MockFileSystem() : this(_ => { }) { } /// /// Initializes the with the . /// - internal MockFileSystem(Action initializationCallback) + public MockFileSystem(Action initializationCallback) { Initialization initialization = new(); initializationCallback(initialization); SimulationMode = initialization.SimulationMode; +#if CAN_SIMULATE_OTHER_OS Execute = SimulationMode == SimulationMode.Native ? new Execute(this) : new Execute(this, SimulationMode); +#else + if (SimulationMode != SimulationMode.Native) + { + throw new NotSupportedException( + "Simulating other operating systems is not supported on .NET Framework"); + } + + Execute = new Execute(this); +#endif StatisticsRegistration = new FileSystemStatistics(this); using IDisposable release = StatisticsRegistration.Ignore(); - RandomSystem = new MockRandomSystem(initialization.RandomProvider ?? RandomProvider.Default()); + RandomSystem = + new MockRandomSystem(initialization.RandomProvider ?? RandomProvider.Default()); TimeSystem = new MockTimeSystem(TimeProvider.Now()); _pathMock = new PathMock(this); _storage = new InMemoryStorage(this); @@ -225,7 +236,7 @@ private void InitializeFileSystem(Initialization initialization) /// /// The initialization options for the . /// - internal class Initialization + public class Initialization { /// /// The current directory. @@ -242,10 +253,18 @@ internal class Initialization /// internal SimulationMode SimulationMode { get; private set; } = SimulationMode.Native; + internal Initialization() + { + // Avoid public constructor + } + /// /// Specify the operating system that should be simulated. /// - internal Initialization SimulatingOperatingSystem(SimulationMode simulationMode) +#if !CAN_SIMULATE_OTHER_OS + [Obsolete("Simulating other operating systems is not supported on .NET Framework")] +#endif + public Initialization SimulatingOperatingSystem(SimulationMode simulationMode) { SimulationMode = simulationMode; return this; @@ -254,7 +273,7 @@ internal Initialization SimulatingOperatingSystem(SimulationMode simulationMode) /// /// Use the provided as current directory. /// - internal Initialization UseCurrentDirectory(string path) + public Initialization UseCurrentDirectory(string path) { CurrentDirectory = path; return this; @@ -263,7 +282,7 @@ internal Initialization UseCurrentDirectory(string path) /// /// Use as current directory. /// - internal Initialization UseCurrentDirectory() + public Initialization UseCurrentDirectory() { CurrentDirectory = System.IO.Directory.GetCurrentDirectory(); return this; @@ -272,7 +291,7 @@ internal Initialization UseCurrentDirectory() /// /// Use the given for the . /// - internal Initialization UseRandomProvider(IRandomProvider randomProvider) + public Initialization UseRandomProvider(IRandomProvider randomProvider) { RandomProvider = randomProvider; return this; diff --git a/Source/Testably.Abstractions.Testing/Testably.Abstractions.Testing.csproj b/Source/Testably.Abstractions.Testing/Testably.Abstractions.Testing.csproj index be82c2609..aa8035b73 100644 --- a/Source/Testably.Abstractions.Testing/Testably.Abstractions.Testing.csproj +++ b/Source/Testably.Abstractions.Testing/Testably.Abstractions.Testing.csproj @@ -21,9 +21,6 @@ <_Parameter1>Testably.Abstractions.Testing.Tests - - <_Parameter1>Testably.Abstractions.Tests - diff --git a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net6.0.txt b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net6.0.txt index 2c6aaeeca..d4eeb7311 100644 --- a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net6.0.txt +++ b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net6.0.txt @@ -1,7 +1,6 @@ [assembly: System.CLSCompliant(true)] [assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/Testably/Testably.Abstractions.git")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Testably.Abstractions.Testing.Tests")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Testably.Abstractions.Tests")] [assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName=".NET 6.0")] namespace Testably.Abstractions.Testing.FileSystem { @@ -94,6 +93,7 @@ namespace Testably.Abstractions.Testing public sealed class MockFileSystem : System.IO.Abstractions.IFileSystem { public MockFileSystem() { } + public MockFileSystem(System.Action initializationCallback) { } public System.IO.Abstractions.IDirectory Directory { get; } public System.IO.Abstractions.IDirectoryInfoFactory DirectoryInfo { get; } public System.IO.Abstractions.IDriveInfoFactory DriveInfo { get; } @@ -112,6 +112,13 @@ namespace Testably.Abstractions.Testing public Testably.Abstractions.Testing.MockFileSystem WithAccessControlStrategy(Testably.Abstractions.Testing.FileSystem.IAccessControlStrategy accessControlStrategy) { } public Testably.Abstractions.Testing.MockFileSystem WithDrive(string? drive, System.Action? driveCallback = null) { } public Testably.Abstractions.Testing.MockFileSystem WithSafeFileHandleStrategy(Testably.Abstractions.Testing.FileSystem.ISafeFileHandleStrategy safeFileHandleStrategy) { } + public class Initialization + { + public Testably.Abstractions.Testing.MockFileSystem.Initialization SimulatingOperatingSystem(Testably.Abstractions.Testing.SimulationMode simulationMode) { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseCurrentDirectory() { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseCurrentDirectory(string path) { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseRandomProvider(Testably.Abstractions.Testing.RandomSystem.IRandomProvider randomProvider) { } + } } public static class MockFileSystemExtensions { diff --git a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net7.0.txt b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net7.0.txt index cf20f78ea..c4538ac9d 100644 --- a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net7.0.txt +++ b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net7.0.txt @@ -1,7 +1,6 @@ [assembly: System.CLSCompliant(true)] [assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/Testably/Testably.Abstractions.git")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Testably.Abstractions.Testing.Tests")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Testably.Abstractions.Tests")] [assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v7.0", FrameworkDisplayName=".NET 7.0")] namespace Testably.Abstractions.Testing.FileSystem { @@ -94,6 +93,7 @@ namespace Testably.Abstractions.Testing public sealed class MockFileSystem : System.IO.Abstractions.IFileSystem { public MockFileSystem() { } + public MockFileSystem(System.Action initializationCallback) { } public System.IO.Abstractions.IDirectory Directory { get; } public System.IO.Abstractions.IDirectoryInfoFactory DirectoryInfo { get; } public System.IO.Abstractions.IDriveInfoFactory DriveInfo { get; } @@ -112,6 +112,13 @@ namespace Testably.Abstractions.Testing public Testably.Abstractions.Testing.MockFileSystem WithAccessControlStrategy(Testably.Abstractions.Testing.FileSystem.IAccessControlStrategy accessControlStrategy) { } public Testably.Abstractions.Testing.MockFileSystem WithDrive(string? drive, System.Action? driveCallback = null) { } public Testably.Abstractions.Testing.MockFileSystem WithSafeFileHandleStrategy(Testably.Abstractions.Testing.FileSystem.ISafeFileHandleStrategy safeFileHandleStrategy) { } + public class Initialization + { + public Testably.Abstractions.Testing.MockFileSystem.Initialization SimulatingOperatingSystem(Testably.Abstractions.Testing.SimulationMode simulationMode) { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseCurrentDirectory() { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseCurrentDirectory(string path) { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseRandomProvider(Testably.Abstractions.Testing.RandomSystem.IRandomProvider randomProvider) { } + } } public static class MockFileSystemExtensions { diff --git a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net8.0.txt b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net8.0.txt index d7c837710..58aea17eb 100644 --- a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net8.0.txt +++ b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net8.0.txt @@ -1,7 +1,6 @@ [assembly: System.CLSCompliant(true)] [assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/Testably/Testably.Abstractions.git")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Testably.Abstractions.Testing.Tests")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Testably.Abstractions.Tests")] [assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName=".NET 8.0")] namespace Testably.Abstractions.Testing.FileSystem { @@ -94,6 +93,7 @@ namespace Testably.Abstractions.Testing public sealed class MockFileSystem : System.IO.Abstractions.IFileSystem { public MockFileSystem() { } + public MockFileSystem(System.Action initializationCallback) { } public System.IO.Abstractions.IDirectory Directory { get; } public System.IO.Abstractions.IDirectoryInfoFactory DirectoryInfo { get; } public System.IO.Abstractions.IDriveInfoFactory DriveInfo { get; } @@ -112,6 +112,13 @@ namespace Testably.Abstractions.Testing public Testably.Abstractions.Testing.MockFileSystem WithAccessControlStrategy(Testably.Abstractions.Testing.FileSystem.IAccessControlStrategy accessControlStrategy) { } public Testably.Abstractions.Testing.MockFileSystem WithDrive(string? drive, System.Action? driveCallback = null) { } public Testably.Abstractions.Testing.MockFileSystem WithSafeFileHandleStrategy(Testably.Abstractions.Testing.FileSystem.ISafeFileHandleStrategy safeFileHandleStrategy) { } + public class Initialization + { + public Testably.Abstractions.Testing.MockFileSystem.Initialization SimulatingOperatingSystem(Testably.Abstractions.Testing.SimulationMode simulationMode) { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseCurrentDirectory() { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseCurrentDirectory(string path) { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseRandomProvider(Testably.Abstractions.Testing.RandomSystem.IRandomProvider randomProvider) { } + } } public static class MockFileSystemExtensions { diff --git a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_netstandard2.0.txt b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_netstandard2.0.txt index 48435f5b5..4fb5737ce 100644 --- a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_netstandard2.0.txt +++ b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_netstandard2.0.txt @@ -1,7 +1,6 @@ [assembly: System.CLSCompliant(true)] [assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/Testably/Testably.Abstractions.git")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Testably.Abstractions.Testing.Tests")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Testably.Abstractions.Tests")] [assembly: System.Runtime.Versioning.TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName=".NET Standard 2.0")] namespace Testably.Abstractions.Testing.FileSystem { @@ -92,6 +91,7 @@ namespace Testably.Abstractions.Testing public sealed class MockFileSystem : System.IO.Abstractions.IFileSystem { public MockFileSystem() { } + public MockFileSystem(System.Action initializationCallback) { } public System.IO.Abstractions.IDirectory Directory { get; } public System.IO.Abstractions.IDirectoryInfoFactory DirectoryInfo { get; } public System.IO.Abstractions.IDriveInfoFactory DriveInfo { get; } @@ -110,6 +110,14 @@ namespace Testably.Abstractions.Testing public Testably.Abstractions.Testing.MockFileSystem WithAccessControlStrategy(Testably.Abstractions.Testing.FileSystem.IAccessControlStrategy accessControlStrategy) { } public Testably.Abstractions.Testing.MockFileSystem WithDrive(string? drive, System.Action? driveCallback = null) { } public Testably.Abstractions.Testing.MockFileSystem WithSafeFileHandleStrategy(Testably.Abstractions.Testing.FileSystem.ISafeFileHandleStrategy safeFileHandleStrategy) { } + public class Initialization + { + [System.Obsolete("Simulating other operating systems is not supported on .NET Framework")] + public Testably.Abstractions.Testing.MockFileSystem.Initialization SimulatingOperatingSystem(Testably.Abstractions.Testing.SimulationMode simulationMode) { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseCurrentDirectory() { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseCurrentDirectory(string path) { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseRandomProvider(Testably.Abstractions.Testing.RandomSystem.IRandomProvider randomProvider) { } + } } public static class MockFileSystemExtensions { diff --git a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_netstandard2.1.txt b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_netstandard2.1.txt index c3e4957dd..1102e677b 100644 --- a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_netstandard2.1.txt +++ b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_netstandard2.1.txt @@ -1,7 +1,6 @@ [assembly: System.CLSCompliant(true)] [assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/Testably/Testably.Abstractions.git")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Testably.Abstractions.Testing.Tests")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Testably.Abstractions.Tests")] [assembly: System.Runtime.Versioning.TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName=".NET Standard 2.1")] namespace Testably.Abstractions.Testing.FileSystem { @@ -92,6 +91,7 @@ namespace Testably.Abstractions.Testing public sealed class MockFileSystem : System.IO.Abstractions.IFileSystem { public MockFileSystem() { } + public MockFileSystem(System.Action initializationCallback) { } public System.IO.Abstractions.IDirectory Directory { get; } public System.IO.Abstractions.IDirectoryInfoFactory DirectoryInfo { get; } public System.IO.Abstractions.IDriveInfoFactory DriveInfo { get; } @@ -110,6 +110,13 @@ namespace Testably.Abstractions.Testing public Testably.Abstractions.Testing.MockFileSystem WithAccessControlStrategy(Testably.Abstractions.Testing.FileSystem.IAccessControlStrategy accessControlStrategy) { } public Testably.Abstractions.Testing.MockFileSystem WithDrive(string? drive, System.Action? driveCallback = null) { } public Testably.Abstractions.Testing.MockFileSystem WithSafeFileHandleStrategy(Testably.Abstractions.Testing.FileSystem.ISafeFileHandleStrategy safeFileHandleStrategy) { } + public class Initialization + { + public Testably.Abstractions.Testing.MockFileSystem.Initialization SimulatingOperatingSystem(Testably.Abstractions.Testing.SimulationMode simulationMode) { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseCurrentDirectory() { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseCurrentDirectory(string path) { } + public Testably.Abstractions.Testing.MockFileSystem.Initialization UseRandomProvider(Testably.Abstractions.Testing.RandomSystem.IRandomProvider randomProvider) { } + } } public static class MockFileSystemExtensions { diff --git a/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs b/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs index 266d4e614..51fd2b402 100644 --- a/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs +++ b/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs @@ -1,10 +1,9 @@ -using System; -using System.Text; +using System.Text; using Testably.Abstractions.Tests.SourceGenerator.Model; -// ReSharper disable StringLiteralTypo namespace Testably.Abstractions.Tests.SourceGenerator.ClassGenerators; +// ReSharper disable StringLiteralTypo internal class FileSystemClassGenerator : ClassGeneratorBase { /// @@ -132,10 +131,8 @@ public override void SkipIfLongRunningTestsShouldBeSkipped() $""Long-running tests are {{_fixture.LongRunningTests}}. You can enable them by executing the corresponding tests in Testably.Abstractions.TestSettings.LongRunningTests.""); #endif }} -}}"); - if (IncludeSimulatedTests(@class)) - { - sourceBuilder.Append(@$" +}} + #if !NETFRAMEWORK namespace {@class.Namespace}.{@class.Name} {{ @@ -177,6 +174,7 @@ public override void SkipIfLongRunningTestsShouldBeSkipped() }} }} #endif + #if !NETFRAMEWORK // ReSharper disable once UnusedMember.Global public sealed class MacFileSystemTests : {@class.Name}, IDisposable @@ -215,6 +213,7 @@ public override void SkipIfLongRunningTestsShouldBeSkipped() }} }} #endif + #if !NETFRAMEWORK // ReSharper disable once UnusedMember.Global public sealed class WindowsFileSystemTests : {@class.Name}, IDisposable @@ -254,12 +253,5 @@ public override void SkipIfLongRunningTestsShouldBeSkipped() }} }} #endif"); - } - } - - private bool IncludeSimulatedTests(ClassModel @class) - { - return @class.Namespace - .StartsWith("Testably.Abstractions.Tests.FileSystem", StringComparison.Ordinal); } } diff --git a/Tests/Testably.Abstractions.Testing.Tests/FileSystem/PathMockTests.cs b/Tests/Testably.Abstractions.Testing.Tests/FileSystem/PathMockTests.cs index 0b261da4f..24adf42b7 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/FileSystem/PathMockTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/FileSystem/PathMockTests.cs @@ -6,9 +6,11 @@ public sealed class PathMockTests { [Theory] [InlineAutoData(SimulationMode.Native)] +#if !NETFRAMEWORK [InlineAutoData(SimulationMode.Linux)] [InlineAutoData(SimulationMode.MacOS)] [InlineAutoData(SimulationMode.Windows)] +#endif public void GetTempFileName_WithCollisions_ShouldThrowIOException( SimulationMode simulationMode, int fixedRandomValue) { diff --git a/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemInitializationTests.cs b/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemInitializationTests.cs index 9de14321c..4cd00a67d 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemInitializationTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemInitializationTests.cs @@ -9,12 +9,10 @@ namespace Testably.Abstractions.Testing.Tests; public class MockFileSystemInitializationTests { +#if !NETFRAMEWORK [SkippableFact] public void MockFileSystem_WhenSimulatingLinux_ShouldBeLinux() { - Skip.IfNot(Test.RunsOnLinux, - "TODO: Enable again, once the Path implementation is sufficiently complete!"); - MockFileSystem sut = new(o => o .SimulatingOperatingSystem(SimulationMode.Linux)); @@ -23,13 +21,12 @@ public void MockFileSystem_WhenSimulatingLinux_ShouldBeLinux() sut.Execute.IsWindows.Should().BeFalse(); sut.Execute.IsNetFramework.Should().BeFalse(); } +#endif +#if !NETFRAMEWORK [SkippableFact] public void MockFileSystem_WhenSimulatingMacOS_ShouldBeMac() { - Skip.IfNot(Test.RunsOnMac, - "TODO: Enable again, once the Path implementation is sufficiently complete!"); - MockFileSystem sut = new(o => o .SimulatingOperatingSystem(SimulationMode.MacOS)); @@ -38,13 +35,12 @@ public void MockFileSystem_WhenSimulatingMacOS_ShouldBeMac() sut.Execute.IsWindows.Should().BeFalse(); sut.Execute.IsNetFramework.Should().BeFalse(); } +#endif +#if !NETFRAMEWORK [SkippableFact] public void MockFileSystem_WhenSimulatingWindows_ShouldBeWindows() { - Skip.IfNot(Test.RunsOnWindows, - "TODO: Enable again, once the Path implementation is sufficiently complete!"); - MockFileSystem sut = new(o => o .SimulatingOperatingSystem(SimulationMode.Windows)); @@ -53,6 +49,7 @@ public void MockFileSystem_WhenSimulatingWindows_ShouldBeWindows() sut.Execute.IsWindows.Should().BeTrue(); sut.Execute.IsNetFramework.Should().BeFalse(); } +#endif [Fact] public void MockFileSystem_WithCurrentDirectory_ShouldInitializeCurrentDirectory() diff --git a/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemTests.cs b/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemTests.cs index 1f891bdd3..083929438 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemTests.cs @@ -92,6 +92,25 @@ public void FileSystemMock_ShouldBeInitializedWithADefaultDrive() drive.VolumeLabel.Should().NotBeNullOrEmpty(); } +#if NETFRAMEWORK + [SkippableTheory] + [InlineData(SimulationMode.Linux)] + [InlineData(SimulationMode.MacOS)] + [InlineData(SimulationMode.Windows)] + public void FileSystemMock_ShouldNotSupportSimulatingOtherOperatingSystemsOnNetFramework( + SimulationMode simulationMode) + { + Exception? exception = Record.Exception(() => + { + _ = new MockFileSystem(i => i.SimulatingOperatingSystem(simulationMode)); + }); + + exception.Should().BeOfType() + .Which.Message.Should() + .Contain("Simulating other operating systems is not supported on .NET Framework"); + } +#endif + [SkippableTheory] [InlineData("A:\\")] [InlineData("G:\\")] From 1e6b35b2a385d273b59d836fce35477a1e8afc8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Sun, 21 Apr 2024 10:43:51 +0200 Subject: [PATCH 3/5] Skip simulated tests for AccessControl, as this feature is only supported on Windows. --- .../ClassGenerators/FileSystemClassGenerator.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs b/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs index 51fd2b402..c8ea2c314 100644 --- a/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs +++ b/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs @@ -1,4 +1,5 @@ -using System.Text; +using System; +using System.Text; using Testably.Abstractions.Tests.SourceGenerator.Model; namespace Testably.Abstractions.Tests.SourceGenerator.ClassGenerators; @@ -131,8 +132,10 @@ public override void SkipIfLongRunningTestsShouldBeSkipped() $""Long-running tests are {{_fixture.LongRunningTests}}. You can enable them by executing the corresponding tests in Testably.Abstractions.TestSettings.LongRunningTests.""); #endif }} -}} - +}}"); + if (!@class.Namespace.Equals("Testably.Abstractions.AccessControl.Tests", StringComparison.Ordinal)) + { + sourceBuilder.Append(@$" #if !NETFRAMEWORK namespace {@class.Namespace}.{@class.Name} {{ @@ -253,5 +256,6 @@ public override void SkipIfLongRunningTestsShouldBeSkipped() }} }} #endif"); + } } } From 669b1ca28aafb4b940338338437a8299e1e7be08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Mon, 22 Apr 2024 07:52:44 +0200 Subject: [PATCH 4/5] Disable obsolete warnings in tests --- .../ClassGenerators/FileSystemClassGenerator.cs | 8 +++++++- .../FileSystem/PathMockTests.cs | 2 ++ .../Helpers/ExecuteExtensionsTests.cs | 2 ++ .../Helpers/ExecuteTests.cs | 6 ++++++ .../Helpers/PathHelperTests.cs | 10 ++-------- .../MockFileSystemInitializationTests.cs | 4 ++-- .../MockFileSystemTests.cs | 2 ++ 7 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs b/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs index c8ea2c314..5569f7be6 100644 --- a/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs +++ b/Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs @@ -133,7 +133,7 @@ public override void SkipIfLongRunningTestsShouldBeSkipped() #endif }} }}"); - if (!@class.Namespace.Equals("Testably.Abstractions.AccessControl.Tests", StringComparison.Ordinal)) + if (IncludeSimulatedTests(@class)) { sourceBuilder.Append(@$" #if !NETFRAMEWORK @@ -258,4 +258,10 @@ public override void SkipIfLongRunningTestsShouldBeSkipped() #endif"); } } + + private bool IncludeSimulatedTests(ClassModel @class) + { + return !@class.Namespace.Equals( + "Testably.Abstractions.AccessControl.Tests", StringComparison.Ordinal); + } } diff --git a/Tests/Testably.Abstractions.Testing.Tests/FileSystem/PathMockTests.cs b/Tests/Testably.Abstractions.Testing.Tests/FileSystem/PathMockTests.cs index 24adf42b7..611ad26cc 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/FileSystem/PathMockTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/FileSystem/PathMockTests.cs @@ -14,10 +14,12 @@ public sealed class PathMockTests public void GetTempFileName_WithCollisions_ShouldThrowIOException( SimulationMode simulationMode, int fixedRandomValue) { + #pragma warning disable CS0618 MockFileSystem fileSystem = new(i => i .SimulatingOperatingSystem(simulationMode) .UseRandomProvider(RandomProvider.Generate( intGenerator: new RandomProvider.Generator(() => fixedRandomValue)))); + #pragma warning restore CS0618 string result = fileSystem.Path.GetTempFileName(); Exception? exception = Record.Exception(() => diff --git a/Tests/Testably.Abstractions.Testing.Tests/Helpers/ExecuteExtensionsTests.cs b/Tests/Testably.Abstractions.Testing.Tests/Helpers/ExecuteExtensionsTests.cs index f0533a736..41ebad319 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/Helpers/ExecuteExtensionsTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/Helpers/ExecuteExtensionsTests.cs @@ -192,8 +192,10 @@ public void OnWindowsIf_ShouldExecuteDependingOnOperatingSystem( #region Helpers + #pragma warning disable CS0618 private static Execute FromType(SimulationMode type) => new(new MockFileSystem(), type); + #pragma warning restore CS0618 #endregion } diff --git a/Tests/Testably.Abstractions.Testing.Tests/Helpers/ExecuteTests.cs b/Tests/Testably.Abstractions.Testing.Tests/Helpers/ExecuteTests.cs index 9b39fff2f..dac7bae73 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/Helpers/ExecuteTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/Helpers/ExecuteTests.cs @@ -7,7 +7,9 @@ public sealed class ExecuteTests [Fact] public void Constructor_ForLinux_ShouldInitializeAccordingly() { + #pragma warning disable CS0618 Execute sut = new(new MockFileSystem(), SimulationMode.Linux); + #pragma warning restore CS0618 sut.IsLinux.Should().BeTrue(); sut.IsMac.Should().BeFalse(); @@ -19,7 +21,9 @@ public void Constructor_ForLinux_ShouldInitializeAccordingly() [Fact] public void Constructor_ForMacOS_ShouldInitializeAccordingly() { + #pragma warning disable CS0618 Execute sut = new(new MockFileSystem(), SimulationMode.MacOS); + #pragma warning restore CS0618 sut.IsLinux.Should().BeFalse(); sut.IsMac.Should().BeTrue(); @@ -31,7 +35,9 @@ public void Constructor_ForMacOS_ShouldInitializeAccordingly() [Fact] public void Constructor_ForWindows_ShouldInitializeAccordingly() { + #pragma warning disable CS0618 Execute sut = new(new MockFileSystem(), SimulationMode.Windows); + #pragma warning restore CS0618 sut.IsLinux.Should().BeFalse(); sut.IsMac.Should().BeFalse(); diff --git a/Tests/Testably.Abstractions.Testing.Tests/Helpers/PathHelperTests.cs b/Tests/Testably.Abstractions.Testing.Tests/Helpers/PathHelperTests.cs index 2d351c9a4..9e59c3028 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/Helpers/PathHelperTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/Helpers/PathHelperTests.cs @@ -120,6 +120,7 @@ public void .Which.Message.Should().Contain($"'{path}'"); } +#if !NETFRAMEWORK [SkippableTheory] [InlineData('|')] [InlineData((char)1)] @@ -127,8 +128,6 @@ public void public void ThrowCommonExceptionsIfPathIsInvalid_WithInvalidCharacters( char invalidChar) { - Skip.If(Test.IsNetFramework); - MockFileSystem fileSystem = new(i => i .SimulatingOperatingSystem(SimulationMode.Windows)); string path = invalidChar + "path"; @@ -137,15 +136,10 @@ public void ThrowCommonExceptionsIfPathIsInvalid_WithInvalidCharacters( { path.EnsureValidFormat(fileSystem); }); - -#if NETFRAMEWORK - exception.Should().BeOfType() - .Which.Message.Should().Contain("path"); -#else exception.Should().BeOfType() .Which.Message.Should().Contain(path); -#endif } +#endif [Fact] public void diff --git a/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemInitializationTests.cs b/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemInitializationTests.cs index 4cd00a67d..75a26b864 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemInitializationTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemInitializationTests.cs @@ -2,8 +2,6 @@ using System.IO; using System.Linq; using Testably.Abstractions.Testing.Tests.TestHelpers; -#if NET6_0_OR_GREATER -#endif namespace Testably.Abstractions.Testing.Tests; @@ -93,7 +91,9 @@ public void SimulatingOperatingSystem_ValidOSPlatform_ShouldSetOperatingSystem( { MockFileSystem.Initialization sut = new(); + #pragma warning disable CS0618 MockFileSystem.Initialization result = sut.SimulatingOperatingSystem(simulationMode); + #pragma warning restore CS0618 result.SimulationMode.Should().Be(simulationMode); sut.SimulationMode.Should().Be(simulationMode); diff --git a/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemTests.cs b/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemTests.cs index 083929438..03aa6ce20 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/MockFileSystemTests.cs @@ -102,7 +102,9 @@ public void FileSystemMock_ShouldNotSupportSimulatingOtherOperatingSystemsOnNetF { Exception? exception = Record.Exception(() => { + #pragma warning disable CS0618 _ = new MockFileSystem(i => i.SimulatingOperatingSystem(simulationMode)); + #pragma warning restore CS0618 }); exception.Should().BeOfType() From 1b2d8f8f6a7245ec1b3dbd6ddce50c9a08c0c77f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Mon, 29 Apr 2024 10:51:51 +0200 Subject: [PATCH 5/5] Mention the simulation functionality in README.md --- README.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 42437cf3c..55dbf35c8 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ The testing helper also supports advanced scenarios like The companion projects [Testably.Abstractions.Compression](https://www.nuget.org/packages/Testably.Abstractions.Compression) and [Testably.Abstractions.AccessControl](https://www.nuget.org/packages/Testably.Abstractions.AccessControl) allow working with [Zip-Files](Examples/ZipFile/README.md) and [Access Control Lists](Examples/AccessControlLists/README.md) respectively. -As the test suite runs both against the mocked and the real file system, the behaviour between the two is identical. +As the test suite runs both against the mocked and the real file system, the behaviour between the two is identical and it also allows [simulating the file system on other operating systems](#simulating-other-operating-systems) (Linux, MacOS and Windows). In addition, the following interfaces are defined: - The `ITimeSystem` interface abstracts away time-related functionality: @@ -111,6 +111,25 @@ fileSystem.Initialize() .WithFile("foo.txt").Which(f => f.HasStringContent("some file content")); ``` +### Simulating other operating systems + +The `MockFileSystem` can also simulate other operating systems than the one it is currently running on. This can be achieved, by providing the corresponding `SimulationMode` in the constructor: + +```csharp +var linuxFileSystem = new MockFileSystem(o => o.SimulatingOperatingSystem(SimulationMode.Linux)); +// The `linuxFileSystem` now behaves like a Linux file system even under Windows: +// - case-sensitive +// - slash as directory separator + +var windowsFileSystem = new MockFileSystem(o => o.SimulatingOperatingSystem(SimulationMode.Windows)); +// The `windowsFileSystem` now behaves like a Windows file system even under Linux or MacOS: +// - multiple drives +// - case-insensitive +// - backslash as directory separator +``` + +By running all tests against the real file system and the simulated under Linux, MacOS and Windows, the behaviour is consistent between the native and simulated mock file systems. + ### Drive management ```csharp var fileSystem = new MockFileSystem();