Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.IO;
using System.Reflection;
using Testably.Abstractions.Testing.FileSystemInitializer;
using Testably.Abstractions.Testing.Helpers;

namespace Testably.Abstractions.Testing;

Expand Down Expand Up @@ -56,4 +58,113 @@ public static IDirectoryCleaner SetCurrentDirectoryToEmptyTemporaryDirectory(
{
return new DirectoryCleaner(fileSystem, prefix, logger);
}

/// <summary>
/// </summary>
/// <param name="fileSystem">The file system.</param>
/// <param name="assembly">The assembly in which the embedded resource files are located.</param>
/// <param name="directoryPath">The directory path in which the found resource files are created.</param>
/// <param name="relativePath">The relative path of the embedded resources in the <paramref name="assembly" />.</param>
/// <param name="searchPattern">
/// The search string to match against the names of embedded resources in the <paramref name="assembly" /> under
/// <paramref name="relativePath" />.<br />
/// This parameter can contain a combination of valid literal path and wildcard (* and ?) characters, but it doesn't
/// support regular expressions.
/// </param>
/// <param name="searchOption">
/// One of the enumeration values that specifies whether the search operation should include only the
/// <paramref name="relativePath" /> or should include all subdirectories.<br />
/// The default value is <see cref="SearchOption.AllDirectories" />.
/// </param>
public static void InitializeEmbeddedResourcesFromAssembly(this IFileSystem fileSystem,
string directoryPath,
Assembly assembly,
string? relativePath = null,
string searchPattern = "*",
SearchOption searchOption = SearchOption.AllDirectories)
{
EnumerationOptions enumerationOptions =
EnumerationOptionsHelper.FromSearchOption(searchOption);

string[] resourcePaths = assembly.GetManifestResourceNames();
string assemblyNamePrefix = $"{assembly.GetName().Name ?? ""}.";

if (relativePath != null)
{
relativePath = relativePath.Replace(
Path.AltDirectorySeparatorChar,
Path.DirectorySeparatorChar);
relativePath = relativePath.TrimEnd(Path.DirectorySeparatorChar);
relativePath += Path.DirectorySeparatorChar;
}

foreach (string resourcePath in resourcePaths)
{
string fileName = resourcePath;
if (fileName.StartsWith(assemblyNamePrefix))
{
fileName = fileName.Substring(assemblyNamePrefix.Length);
}

fileName = fileName.Replace('.', Path.DirectorySeparatorChar);
int lastSeparator = fileName.LastIndexOf(Path.DirectorySeparatorChar);
if (lastSeparator > 0)
{
fileName = fileName.Substring(0, lastSeparator) + "." +
fileName.Substring(lastSeparator + 1);
}

if (relativePath != null)
{
if (!fileName.StartsWith(relativePath))
{
continue;
}

fileName = fileName.Substring(relativePath.Length);
}

if (!enumerationOptions.RecurseSubdirectories &&
fileName.IndexOf(Path.DirectorySeparatorChar) >= 0)
{
continue;
}

if (EnumerationOptionsHelper.MatchesPattern(enumerationOptions,
fileName, searchPattern))
{
string filePath = fileSystem.Path.Combine(directoryPath, fileName);
fileSystem.InitializeFileFromEmbeddedResource(filePath, assembly, resourcePath);
}
}
}

private static void InitializeFileFromEmbeddedResource(this IFileSystem fileSystem,
string path,
Assembly assembly,
string embeddedResourcePath)
{
using (Stream? embeddedResourceStream = assembly
.GetManifestResourceStream(embeddedResourcePath))
{
if (embeddedResourceStream == null)
{
throw new ArgumentException(
$"Resource '{embeddedResourcePath}' not found in assembly '{assembly.FullName}'",
nameof(embeddedResourcePath));
}

using (BinaryReader streamReader = new(embeddedResourceStream))
{
byte[] fileData = streamReader.ReadBytes((int)embeddedResourceStream.Length);
string? directoryPath = fileSystem.Path.GetDirectoryName(path);
if (!string.IsNullOrEmpty(directoryPath))
{
fileSystem.Directory.CreateDirectory(directoryPath);
}

fileSystem.File.WriteAllBytes(path, fileData);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Testably.Abstractions.Testing.FileSystemInitializer;
using Testably.Abstractions.Testing.Tests.TestHelpers;

Expand Down Expand Up @@ -149,6 +150,73 @@ public void Initialize_WithSubdirectory_ShouldExist(string directoryName)
result.Directory.Exists.Should().BeTrue();
}

[Theory]
[AutoData]
public void
InitializeEmbeddedResourcesFromAssembly_ShouldCopyAllMatchingResourceFilesInDirectory(
string path)
{
MockFileSystem fileSystem = new();
fileSystem.InitializeIn("foo");

fileSystem.InitializeEmbeddedResourcesFromAssembly(
path,
Assembly.GetExecutingAssembly(),
searchPattern: "*.txt");

string[] result = fileSystem.Directory.GetFiles(Path.Combine(path, "TestResources"));
string[] result2 =
fileSystem.Directory.GetFiles(Path.Combine(path, "TestResources", "SubResource"));
result.Length.Should().Be(2);
result.Should().Contain(x => x.EndsWith("TestFile1.txt"));
result.Should().Contain(x => x.EndsWith("TestFile2.txt"));
result2.Length.Should().Be(1);
result2.Should().Contain(x => x.EndsWith("SubResourceFile1.txt"));
}

[Theory]
[AutoData]
public void
InitializeEmbeddedResourcesFromAssembly_WithoutRecurseSubdirectories_ShouldOnlyCopyTopmostFilesInRelativePath(
string path)
{
MockFileSystem fileSystem = new();
fileSystem.InitializeIn("foo");

fileSystem.InitializeEmbeddedResourcesFromAssembly(
path,
Assembly.GetExecutingAssembly(),
"TestResources",
searchPattern: "*.txt",
SearchOption.TopDirectoryOnly);

string[] result = fileSystem.Directory.GetFiles(path);
result.Length.Should().Be(2);
result.Should().Contain(x => x.EndsWith("TestFile1.txt"));
result.Should().Contain(x => x.EndsWith("TestFile2.txt"));
fileSystem.Directory.Exists(Path.Combine(path, "SubResource")).Should().BeFalse();
}

[Theory]
[AutoData]
public void
InitializeEmbeddedResourcesFromAssembly_WithRelativePath_ShouldCopyAllResourceInMatchingPathInDirectory(
string path)
{
MockFileSystem fileSystem = new();
fileSystem.InitializeIn("foo");

fileSystem.InitializeEmbeddedResourcesFromAssembly(
path,
Assembly.GetExecutingAssembly(),
"TestResources/SubResource",
searchPattern: "*.txt");

string[] result = fileSystem.Directory.GetFiles(path);
result.Length.Should().Be(1);
result.Should().Contain(x => x.EndsWith("SubResourceFile1.txt"));
}

[SkippableTheory]
[AutoData]
public void InitializeIn_MissingDrive_ShouldCreateDrive(string directoryName)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading