Skip to content

Commit

Permalink
Implement MountFolder and test
Browse files Browse the repository at this point in the history
  • Loading branch information
thohng committed May 31, 2024
1 parent 5fbcfca commit bca3dcf
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 9 deletions.
34 changes: 25 additions & 9 deletions src/Hosting/MountFileProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@

namespace NetLah.Extensions.SpaServices.Hosting;

internal class MountFileProvider : IFileProvider
internal class MountFileProvider(IFileProvider fileProvider, MountFileProviderOptions options) : IFileProvider
{
private readonly IFileProvider _fileProvider;
private readonly MountFileProviderOptions _options;
private readonly IFileProvider _fileProvider = fileProvider;
private readonly IDictionary<string, string> _fileMap = options?.Files ?? new Dictionary<string, string>();
private readonly (string path, Entry value)[] _folderMap = options?
.Folders?
.Select(kv => (kv.Key, new Entry(kv.Key.Length - 1, new PhysicalFileProvider(kv.Value))))
.ToArray()
?? [];

public MountFileProvider(IFileProvider fileProvider, MountFileProviderOptions options)
private class Entry(int length, IFileProvider fileProvider)
{
_fileProvider = fileProvider;
_options = options;
public int Length { get; } = length;
public IFileProvider FileProvider { get; } = fileProvider;
}

public IDirectoryContents GetDirectoryContents(string subpath)
Expand All @@ -22,10 +27,21 @@ public IDirectoryContents GetDirectoryContents(string subpath)

public IFileInfo GetFileInfo(string subpath)
{
if (_options.Files.TryGetValue(subpath, out var source))
if (!string.IsNullOrEmpty(subpath))
{
var fileInfo = new FileInfo(source);
return fileInfo.Exists ? new PhysicalFileInfo(fileInfo) : new NotFoundFileInfo(subpath);
if (_fileMap.TryGetValue(subpath, out var source))
{
var fileInfo = new FileInfo(source);
return fileInfo.Exists ? new PhysicalFileInfo(fileInfo) : new NotFoundFileInfo(subpath);
}

foreach (var (path, entry) in _folderMap)
{
if (subpath.StartsWith(path))
{
return entry.FileProvider.GetFileInfo(subpath[entry.Length..]);
}
}
}

var result = _fileProvider.GetFileInfo(subpath);
Expand Down
3 changes: 3 additions & 0 deletions test/Hosting.Test/Hosting.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
</ItemGroup>

<ItemGroup>
<None Update="mount-file-folder/**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="public*/**/*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
119 changes: 119 additions & 0 deletions test/Hosting.Test/MountFileProviderTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
using Microsoft.Extensions.FileProviders;
using Moq;

namespace NetLah.Extensions.SpaServices.Hosting.Test;

public class MountFileProviderTest
{
private static readonly StringComparer _stringComparer = OperatingSystem.IsWindows() ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal;

[Fact]
public void MountFileTest()
{
var service = new MountFileProvider(null!, new MountFileProviderOptions
{
Files = new Dictionary<string, string>(_stringComparer)
{
["/config1/app2.json"] = "mount-file-folder/app.Prd.json",
}
});

var result = service.GetFileInfo("/config1/app2.json");

Assert.NotNull(result);
Assert.True(result.Exists);
}

[Fact]
public void MountFileNotFoundTest()
{
var service = new MountFileProvider(null!, new MountFileProviderOptions
{
Files = new Dictionary<string, string>(_stringComparer)
{
["/config3/app4.json"] = "mount-file-folder/app.not-found.json",
}
});

var result = service.GetFileInfo("/config3/app4.json");

Assert.NotNull(result);
Assert.False(result.Exists);
}

[Fact]
public void MountFileFallbackTest()
{
var mockFileProvider = new Mock<IFileProvider>();
var service = new MountFileProvider(mockFileProvider.Object, new MountFileProviderOptions
{
Files = new Dictionary<string, string>(_stringComparer)
{
["/config/app.json"] = "mount-file-folder/any.json",
}
});

_ = service.GetFileInfo("/config3/app4.json");

mockFileProvider.Verify(x => x.GetFileInfo("/config3/app4.json"), Times.Once());
mockFileProvider.Verify(x => x.GetFileInfo(It.IsAny<string>()), Times.Once());
}

[Fact]
public void MountFolderTest()
{
var service = new MountFileProvider(null!, new MountFileProviderOptions
{
Folders = new Dictionary<string, string>(_stringComparer)
{
["/config1/"] = Path.GetFullPath("mount-file-folder"),
}
});

var result = service.GetFileInfo("/config1/app.Prd.json");

Assert.NotNull(result);
Assert.True(result.Exists);
Assert.Equal("app.Prd.json", result.Name);
}

[Fact]
public void MountFolderNotFoundTest()
{
var service = new MountFileProvider(null!, new MountFileProviderOptions
{
Folders = new Dictionary<string, string>(_stringComparer)
{
["/config2/"] = Path.GetFullPath("mount-file-folder"),
}
});

Assert.True(service.GetFileInfo("/config2/app.Prd.json").Exists);

var result = service.GetFileInfo("/config2/app.not-exists.json");

Assert.NotNull(result);
Assert.False(result.Exists);
Assert.Equal("app.not-exists.json", result.Name);
}

[Fact]
public void MountFolderFallbackTest()
{
var mockFileProvider = new Mock<IFileProvider>();
var service = new MountFileProvider(mockFileProvider.Object, new MountFileProviderOptions
{
Folders = new Dictionary<string, string>(_stringComparer)
{
["/config3/"] = Path.GetFullPath("mount-file-folder"),
}
});

Assert.True(service.GetFileInfo("/config3/app.Prd.json").Exists);

_ = service.GetFileInfo("/config4/app4.json");

mockFileProvider.Verify(x => x.GetFileInfo("/config4/app4.json"), Times.Once());
mockFileProvider.Verify(x => x.GetFileInfo(It.IsAny<string>()), Times.Once());
}
}
3 changes: 3 additions & 0 deletions test/Hosting.Test/mount-file-folder/app.Prd.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Description": "This is test;"
}

0 comments on commit bca3dcf

Please sign in to comment.