Skip to content

Commit

Permalink
Make simulation functionality public and throw a NotSupportedExceptio…
Browse files Browse the repository at this point in the history
…n on .NET Framework
  • Loading branch information
vbreuss committed Apr 21, 2024
1 parent 49ed920 commit 403d614
Show file tree
Hide file tree
Showing 14 changed files with 99 additions and 27 deletions.
1 change: 1 addition & 0 deletions Feature.Flags.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<IS_NET8_OR_HIGHER Condition="'$(TargetFramework)' == 'net8.0'">1</IS_NET8_OR_HIGHER>

<DefineConstants Condition="'$(TargetFramework)' == 'net48' OR '$(TargetFramework)' == 'netstandard2.0'">$(DefineConstants);NETFRAMEWORK</DefineConstants>
<DefineConstants Condition="'$(IS_NET21_OR_HIGHER)' == '1'">$(DefineConstants);CAN_SIMULATE_OTHER_OS</DefineConstants>
<DefineConstants Condition="'$(IS_NET21_OR_HIGHER)' == '1'">$(DefineConstants);FEATURE_FILESYSTEM_ASYNC</DefineConstants>
<DefineConstants Condition="'$(IS_NET21_OR_HIGHER)' == '1'">$(DefineConstants);FEATURE_FILESYSTEM_ENUMERATION_OPTIONS</DefineConstants>
<DefineConstants Condition="'$(IS_NET21_OR_HIGHER)' == '1'">$(DefineConstants);FEATURE_PATH_JOIN</DefineConstants>
Expand Down
3 changes: 3 additions & 0 deletions Source/Testably.Abstractions.Testing/Helpers/Execute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ internal partial class Execute
/// </summary>
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;
Expand Down
33 changes: 26 additions & 7 deletions Source/Testably.Abstractions.Testing/MockFileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,29 @@ public MockFileSystem() : this(_ => { }) { }
/// <summary>
/// Initializes the <see cref="MockFileSystem" /> with the <paramref name="initializationCallback" />.
/// </summary>
internal MockFileSystem(Action<Initialization> initializationCallback)
public MockFileSystem(Action<Initialization> 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);
Expand Down Expand Up @@ -225,7 +236,7 @@ private void InitializeFileSystem(Initialization initialization)
/// <summary>
/// The initialization options for the <see cref="MockFileSystem" />.
/// </summary>
internal class Initialization
public class Initialization
{
/// <summary>
/// The current directory.
Expand All @@ -242,10 +253,18 @@ internal class Initialization
/// </summary>
internal SimulationMode SimulationMode { get; private set; } = SimulationMode.Native;

internal Initialization()
{
// Avoid public constructor
}

/// <summary>
/// Specify the operating system that should be simulated.
/// </summary>
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;
Expand All @@ -254,7 +273,7 @@ internal Initialization SimulatingOperatingSystem(SimulationMode simulationMode)
/// <summary>
/// Use the provided <paramref name="path" /> as current directory.
/// </summary>
internal Initialization UseCurrentDirectory(string path)
public Initialization UseCurrentDirectory(string path)
{
CurrentDirectory = path;
return this;
Expand All @@ -263,7 +282,7 @@ internal Initialization UseCurrentDirectory(string path)
/// <summary>
/// Use <see cref="Directory.GetCurrentDirectory()" /> as current directory.
/// </summary>
internal Initialization UseCurrentDirectory()
public Initialization UseCurrentDirectory()
{
CurrentDirectory = System.IO.Directory.GetCurrentDirectory();
return this;
Expand All @@ -272,7 +291,7 @@ internal Initialization UseCurrentDirectory()
/// <summary>
/// Use the given <paramref name="randomProvider" /> for the <see cref="RandomSystem" />.
/// </summary>
internal Initialization UseRandomProvider(IRandomProvider randomProvider)
public Initialization UseRandomProvider(IRandomProvider randomProvider)
{
RandomProvider = randomProvider;
return this;
Expand Down
3 changes: 2 additions & 1 deletion Source/Testably.Abstractions.Testing/SimulationMode.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Runtime.InteropServices;
using System;
using System.Runtime.InteropServices;

namespace Testably.Abstractions.Testing;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>Testably.Abstractions.Testing.Tests</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>Testably.Abstractions.Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down Expand Up @@ -94,6 +93,7 @@ namespace Testably.Abstractions.Testing
public sealed class MockFileSystem : System.IO.Abstractions.IFileSystem
{
public MockFileSystem() { }
public MockFileSystem(System.Action<Testably.Abstractions.Testing.MockFileSystem.Initialization> initializationCallback) { }
public System.IO.Abstractions.IDirectory Directory { get; }
public System.IO.Abstractions.IDirectoryInfoFactory DirectoryInfo { get; }
public System.IO.Abstractions.IDriveInfoFactory DriveInfo { get; }
Expand All @@ -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<Testably.Abstractions.Testing.Storage.IStorageDrive>? 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
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down Expand Up @@ -94,6 +93,7 @@ namespace Testably.Abstractions.Testing
public sealed class MockFileSystem : System.IO.Abstractions.IFileSystem
{
public MockFileSystem() { }
public MockFileSystem(System.Action<Testably.Abstractions.Testing.MockFileSystem.Initialization> initializationCallback) { }
public System.IO.Abstractions.IDirectory Directory { get; }
public System.IO.Abstractions.IDirectoryInfoFactory DirectoryInfo { get; }
public System.IO.Abstractions.IDriveInfoFactory DriveInfo { get; }
Expand All @@ -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<Testably.Abstractions.Testing.Storage.IStorageDrive>? 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
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down Expand Up @@ -94,6 +93,7 @@ namespace Testably.Abstractions.Testing
public sealed class MockFileSystem : System.IO.Abstractions.IFileSystem
{
public MockFileSystem() { }
public MockFileSystem(System.Action<Testably.Abstractions.Testing.MockFileSystem.Initialization> initializationCallback) { }
public System.IO.Abstractions.IDirectory Directory { get; }
public System.IO.Abstractions.IDirectoryInfoFactory DirectoryInfo { get; }
public System.IO.Abstractions.IDriveInfoFactory DriveInfo { get; }
Expand All @@ -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<Testably.Abstractions.Testing.Storage.IStorageDrive>? 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
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down Expand Up @@ -92,6 +91,7 @@ namespace Testably.Abstractions.Testing
public sealed class MockFileSystem : System.IO.Abstractions.IFileSystem
{
public MockFileSystem() { }
public MockFileSystem(System.Action<Testably.Abstractions.Testing.MockFileSystem.Initialization> initializationCallback) { }
public System.IO.Abstractions.IDirectory Directory { get; }
public System.IO.Abstractions.IDirectoryInfoFactory DirectoryInfo { get; }
public System.IO.Abstractions.IDriveInfoFactory DriveInfo { get; }
Expand All @@ -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<Testably.Abstractions.Testing.Storage.IStorageDrive>? 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
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down Expand Up @@ -92,6 +91,7 @@ namespace Testably.Abstractions.Testing
public sealed class MockFileSystem : System.IO.Abstractions.IFileSystem
{
public MockFileSystem() { }
public MockFileSystem(System.Action<Testably.Abstractions.Testing.MockFileSystem.Initialization> initializationCallback) { }
public System.IO.Abstractions.IDirectory Directory { get; }
public System.IO.Abstractions.IDirectoryInfoFactory DirectoryInfo { get; }
public System.IO.Abstractions.IDriveInfoFactory DriveInfo { get; }
Expand All @@ -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<Testably.Abstractions.Testing.Storage.IStorageDrive>? 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
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,6 @@ public override void SkipIfLongRunningTestsShouldBeSkipped()

private bool IncludeSimulatedTests(ClassModel @class)
{
return @class.Namespace
.StartsWith("Testably.Abstractions.Tests.FileSystem", StringComparison.Ordinal);
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand All @@ -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));

Expand All @@ -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));

Expand All @@ -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()
Expand Down
17 changes: 17 additions & 0 deletions Tests/Testably.Abstractions.Testing.Tests/MockFileSystemTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@ 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(() =>
{
MockFileSystem sut = new(i => i.SimulatingOperatingSystem(simulationMode));

Check warning on line 105 in Tests/Testably.Abstractions.Testing.Tests/MockFileSystemTests.cs

View workflow job for this annotation

GitHub Actions / Test (.NET Framework)

'MockFileSystem.Initialization.SimulatingOperatingSystem(SimulationMode)' is obsolete: 'Simulating other operating systems is not supported on .NET Framework'
});

exception.Should().BeOfType<NotSupportedException>();
}
#endif

[SkippableTheory]
[InlineData("A:\\")]
[InlineData("G:\\")]
Expand Down

0 comments on commit 403d614

Please sign in to comment.