diff --git a/Source/Testably.Abstractions.Testing/FileSystemInitializerExtensions.cs b/Source/Testably.Abstractions.Testing/FileSystemInitializerExtensions.cs index 5113b2a5..ca479543 100644 --- a/Source/Testably.Abstractions.Testing/FileSystemInitializerExtensions.cs +++ b/Source/Testably.Abstractions.Testing/FileSystemInitializerExtensions.cs @@ -108,6 +108,40 @@ public static void InitializeEmbeddedResourcesFromAssembly(this IFileSystem file } #pragma warning restore MA0051 // Method is too long + /// + /// Initializes the from the real into the + /// on the provided file system. + /// + /// The target file system to which the data is copied. + /// + /// The source directory on the real file system that is copied to the + /// . + /// + /// + /// The target directory on the to which the data is copied to.
+ /// If no is set, is used instead. + /// + /// + /// Warning:
+ /// This method will recursively copy the content of all files and directories from the + /// to the . With large files, this can be very + /// resource intensive!
+ ///
+ public static void InitializeFromRealDirectory(this IFileSystem fileSystem, + string sourceDirectory, string? targetDirectory = null) + { + using IDisposable release = fileSystem.IgnoreStatistics(); + targetDirectory ??= sourceDirectory; + if (fileSystem.Path.IsPathRooted(targetDirectory) && + fileSystem is MockFileSystem mockFileSystem) + { + string? drive = fileSystem.Path.GetPathRoot(targetDirectory); + mockFileSystem.WithDrive(drive); + } + + CopyDirectory(fileSystem, sourceDirectory, targetDirectory); + } + /// /// Initializes the in the with test data. /// @@ -158,6 +192,31 @@ public static IDirectoryCleaner SetCurrentDirectoryToEmptyTemporaryDirectory( return new DirectoryCleaner(fileSystem, prefix, logger); } + private static void CopyDirectory( + IFileSystem fileSystem, string sourceDirectory, string targetDirectory) + { + if (!Directory.Exists(sourceDirectory)) + { + throw new DirectoryNotFoundException( + $"The directory '{sourceDirectory}' does not exist."); + } + + fileSystem.Directory.CreateDirectory(targetDirectory); + foreach (string file in Directory.EnumerateFiles(sourceDirectory)) + { + string fileName = Path.GetFileName(file); + fileSystem.File.WriteAllBytes(fileSystem.Path.Combine(targetDirectory, fileName), + File.ReadAllBytes(file)); + } + + foreach (string directory in Directory.EnumerateDirectories(sourceDirectory)) + { + string directoryName = Path.GetFileName(directory); + CopyDirectory(fileSystem, directory, + fileSystem.Path.Combine(targetDirectory, directoryName)); + } + } + private static void InitializeFileFromEmbeddedResource(this IFileSystem fileSystem, string path, Assembly assembly, diff --git a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net10.0.txt b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net10.0.txt index 8219bb8e..921b4f81 100644 --- a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net10.0.txt +++ b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net10.0.txt @@ -18,6 +18,7 @@ namespace Testably.Abstractions.Testing public static Testably.Abstractions.Testing.Initializer.IFileSystemInitializer Initialize(this TFileSystem fileSystem, System.Action? options = null) where TFileSystem : System.IO.Abstractions.IFileSystem { } public static void InitializeEmbeddedResourcesFromAssembly(this System.IO.Abstractions.IFileSystem fileSystem, string directoryPath, System.Reflection.Assembly assembly, string? relativePath = null, string searchPattern = "*", System.IO.SearchOption searchOption = 1) { } + public static void InitializeFromRealDirectory(this System.IO.Abstractions.IFileSystem fileSystem, string sourceDirectory, string? targetDirectory = null) { } public static Testably.Abstractions.Testing.Initializer.IFileSystemInitializer InitializeIn(this TFileSystem fileSystem, string basePath, System.Action? options = null) where TFileSystem : System.IO.Abstractions.IFileSystem { } public static Testably.Abstractions.Testing.Initializer.IDirectoryCleaner SetCurrentDirectoryToEmptyTemporaryDirectory(this System.IO.Abstractions.IFileSystem fileSystem, string? prefix = null, System.Action? logger = null) { } 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 e9819ffe..8891e371 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 @@ -18,6 +18,7 @@ namespace Testably.Abstractions.Testing public static Testably.Abstractions.Testing.Initializer.IFileSystemInitializer Initialize(this TFileSystem fileSystem, System.Action? options = null) where TFileSystem : System.IO.Abstractions.IFileSystem { } public static void InitializeEmbeddedResourcesFromAssembly(this System.IO.Abstractions.IFileSystem fileSystem, string directoryPath, System.Reflection.Assembly assembly, string? relativePath = null, string searchPattern = "*", System.IO.SearchOption searchOption = 1) { } + public static void InitializeFromRealDirectory(this System.IO.Abstractions.IFileSystem fileSystem, string sourceDirectory, string? targetDirectory = null) { } public static Testably.Abstractions.Testing.Initializer.IFileSystemInitializer InitializeIn(this TFileSystem fileSystem, string basePath, System.Action? options = null) where TFileSystem : System.IO.Abstractions.IFileSystem { } public static Testably.Abstractions.Testing.Initializer.IDirectoryCleaner SetCurrentDirectoryToEmptyTemporaryDirectory(this System.IO.Abstractions.IFileSystem fileSystem, string? prefix = null, System.Action? logger = null) { } 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 a8ed9873..7ade5f59 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 @@ -18,6 +18,7 @@ namespace Testably.Abstractions.Testing public static Testably.Abstractions.Testing.Initializer.IFileSystemInitializer Initialize(this TFileSystem fileSystem, System.Action? options = null) where TFileSystem : System.IO.Abstractions.IFileSystem { } public static void InitializeEmbeddedResourcesFromAssembly(this System.IO.Abstractions.IFileSystem fileSystem, string directoryPath, System.Reflection.Assembly assembly, string? relativePath = null, string searchPattern = "*", System.IO.SearchOption searchOption = 1) { } + public static void InitializeFromRealDirectory(this System.IO.Abstractions.IFileSystem fileSystem, string sourceDirectory, string? targetDirectory = null) { } public static Testably.Abstractions.Testing.Initializer.IFileSystemInitializer InitializeIn(this TFileSystem fileSystem, string basePath, System.Action? options = null) where TFileSystem : System.IO.Abstractions.IFileSystem { } public static Testably.Abstractions.Testing.Initializer.IDirectoryCleaner SetCurrentDirectoryToEmptyTemporaryDirectory(this System.IO.Abstractions.IFileSystem fileSystem, string? prefix = null, System.Action? logger = null) { } diff --git a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net9.0.txt b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net9.0.txt index 94c965e1..ff084f74 100644 --- a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net9.0.txt +++ b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net9.0.txt @@ -18,6 +18,7 @@ namespace Testably.Abstractions.Testing public static Testably.Abstractions.Testing.Initializer.IFileSystemInitializer Initialize(this TFileSystem fileSystem, System.Action? options = null) where TFileSystem : System.IO.Abstractions.IFileSystem { } public static void InitializeEmbeddedResourcesFromAssembly(this System.IO.Abstractions.IFileSystem fileSystem, string directoryPath, System.Reflection.Assembly assembly, string? relativePath = null, string searchPattern = "*", System.IO.SearchOption searchOption = 1) { } + public static void InitializeFromRealDirectory(this System.IO.Abstractions.IFileSystem fileSystem, string sourceDirectory, string? targetDirectory = null) { } public static Testably.Abstractions.Testing.Initializer.IFileSystemInitializer InitializeIn(this TFileSystem fileSystem, string basePath, System.Action? options = null) where TFileSystem : System.IO.Abstractions.IFileSystem { } public static Testably.Abstractions.Testing.Initializer.IDirectoryCleaner SetCurrentDirectoryToEmptyTemporaryDirectory(this System.IO.Abstractions.IFileSystem fileSystem, string? prefix = null, System.Action? logger = null) { } 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 1a67f362..e5020493 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 @@ -14,6 +14,7 @@ namespace Testably.Abstractions.Testing public static Testably.Abstractions.Testing.Initializer.IFileSystemInitializer Initialize(this TFileSystem fileSystem, System.Action? options = null) where TFileSystem : System.IO.Abstractions.IFileSystem { } public static void InitializeEmbeddedResourcesFromAssembly(this System.IO.Abstractions.IFileSystem fileSystem, string directoryPath, System.Reflection.Assembly assembly, string? relativePath = null, string searchPattern = "*", System.IO.SearchOption searchOption = 1) { } + public static void InitializeFromRealDirectory(this System.IO.Abstractions.IFileSystem fileSystem, string sourceDirectory, string? targetDirectory = null) { } public static Testably.Abstractions.Testing.Initializer.IFileSystemInitializer InitializeIn(this TFileSystem fileSystem, string basePath, System.Action? options = null) where TFileSystem : System.IO.Abstractions.IFileSystem { } public static Testably.Abstractions.Testing.Initializer.IDirectoryCleaner SetCurrentDirectoryToEmptyTemporaryDirectory(this System.IO.Abstractions.IFileSystem fileSystem, string? prefix = null, System.Action? logger = null) { } 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 95c397d7..ebd68b1f 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 @@ -14,6 +14,7 @@ namespace Testably.Abstractions.Testing public static Testably.Abstractions.Testing.Initializer.IFileSystemInitializer Initialize(this TFileSystem fileSystem, System.Action? options = null) where TFileSystem : System.IO.Abstractions.IFileSystem { } public static void InitializeEmbeddedResourcesFromAssembly(this System.IO.Abstractions.IFileSystem fileSystem, string directoryPath, System.Reflection.Assembly assembly, string? relativePath = null, string searchPattern = "*", System.IO.SearchOption searchOption = 1) { } + public static void InitializeFromRealDirectory(this System.IO.Abstractions.IFileSystem fileSystem, string sourceDirectory, string? targetDirectory = null) { } public static Testably.Abstractions.Testing.Initializer.IFileSystemInitializer InitializeIn(this TFileSystem fileSystem, string basePath, System.Action? options = null) where TFileSystem : System.IO.Abstractions.IFileSystem { } public static Testably.Abstractions.Testing.Initializer.IDirectoryCleaner SetCurrentDirectoryToEmptyTemporaryDirectory(this System.IO.Abstractions.IFileSystem fileSystem, string? prefix = null, System.Action? logger = null) { } diff --git a/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializerExtensionsTests.cs b/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializerExtensionsTests.cs index aaa1cccc..70859a22 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializerExtensionsTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializerExtensionsTests.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using aweXpect.Testably; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; @@ -243,6 +244,108 @@ await That(result) .Contains(x => x.EndsWith("SubResourceFile1.txt", StringComparison.Ordinal)); } + [Theory] + [AutoData] + public async Task InitializeFromRealDirectory_MissingDrive_ShouldCreateDrive( + string directoryName) + { + Skip.IfNot(Test.RunsOnWindows); + + string tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + try + { + Directory.CreateDirectory(tempPath); + MockFileSystem sut = new(); + IDriveInfo[] drives = sut.DriveInfo.GetDrives(); + for (char c = 'D'; c <= 'Z'; c++) + { + if (drives.Any(d => d.Name.StartsWith($"{c}", StringComparison.Ordinal))) + { + continue; + } + + directoryName = Path.Combine($"{c}:\\", directoryName); + break; + } + + sut.InitializeFromRealDirectory(tempPath, directoryName); + + await That(sut.Directory.Exists(directoryName)).IsTrue(); + await That(sut.DriveInfo.GetDrives()).HasCount(drives.Length + 1); + } + finally + { + Directory.Delete(tempPath, true); + } + } + + [Fact] + public async Task InitializeFromRealDirectory_ShouldCopyFileToTargetDirectory() + { + MockFileSystem fileSystem = new(); + string tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + try + { + Directory.CreateDirectory(tempPath); + string filePath = Path.Combine(tempPath, "test.txt"); + File.WriteAllText(filePath, "Hello, World!"); + + fileSystem.InitializeFromRealDirectory(tempPath, "foo"); + + await That(fileSystem).HasDirectory("foo"); + await That(fileSystem).HasFile("foo/test.txt").WithContent("Hello, World!"); + } + finally + { + Directory.Delete(tempPath, true); + } + } + + [Fact] + public async Task + InitializeFromRealDirectory_ShouldRecursivelyCopyDirectoriesToTargetDirectory() + { + MockFileSystem fileSystem = new(); + string tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + try + { + Directory.CreateDirectory(tempPath); + Directory.CreateDirectory(Path.Combine(tempPath, "subdir")); + File.WriteAllText(Path.Combine(tempPath, "subdir", "test1.txt"), "foo"); + File.WriteAllText(Path.Combine(tempPath, "subdir", "test2.txt"), "bar"); + + fileSystem.InitializeFromRealDirectory(tempPath); + + await That(fileSystem).HasDirectory(fileSystem.Path.Combine(tempPath, "subdir")); + await That(fileSystem).HasFile(fileSystem.Path.Combine(tempPath, "subdir", "test1.txt")) + .WithContent("foo"); + await That(fileSystem).HasFile(fileSystem.Path.Combine(tempPath, "subdir", "test2.txt")) + .WithContent("bar"); + } + finally + { + Directory.Delete(tempPath, true); + } + } + + [Fact] + public async Task + InitializeFromRealDirectory_WhenDirectoryDoesNotExist_ShouldThrowDirectoryNotFoundException() + { + MockFileSystem fileSystem = new(); + string tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + while (Directory.Exists(tempPath)) + { + tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + } + + void Act() + => fileSystem.InitializeFromRealDirectory(tempPath, "foo"); + + await That(Act).Throws() + .WithMessage($"The directory '{tempPath}' does not exist."); + } + [Theory] [AutoData] public async Task InitializeIn_MissingDrive_ShouldCreateDrive(string directoryName)