From 25bfed273fb6f42c9cf55a2faea8cff7dd22621f Mon Sep 17 00:00:00 2001 From: rameel Date: Sat, 28 Mar 2026 21:01:53 +0500 Subject: [PATCH 1/3] Fix: ResolvePath returns null for all non-root paths when prefix is "/" Fixes #44 --- .../PrefixedFileProvider.cs | 3 +++ .../PrefixedFileProviderTests.cs | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/Ramstack.FileProviders/PrefixedFileProvider.cs b/src/Ramstack.FileProviders/PrefixedFileProvider.cs index a63280a..9609e46 100644 --- a/src/Ramstack.FileProviders/PrefixedFileProvider.cs +++ b/src/Ramstack.FileProviders/PrefixedFileProvider.cs @@ -98,6 +98,9 @@ public void Dispose() => { Debug.Assert(path == FilePath.Normalize(path)); + if (prefix == "/") + return path; + if (path == prefix) return "/"; diff --git a/tests/Ramstack.FileProviders.Tests/PrefixedFileProviderTests.cs b/tests/Ramstack.FileProviders.Tests/PrefixedFileProviderTests.cs index f18f2f8..00fdce8 100644 --- a/tests/Ramstack.FileProviders.Tests/PrefixedFileProviderTests.cs +++ b/tests/Ramstack.FileProviders.Tests/PrefixedFileProviderTests.cs @@ -12,6 +12,11 @@ public sealed class PrefixedFileProviderTests : AbstractFileProviderTests .GetMethod("ResolveGlobFilter", BindingFlags.Static | BindingFlags.NonPublic)! .CreateDelegate>(); + private static readonly Func s_resolvePath = + typeof(PrefixedFileProvider) + .GetMethod("ResolvePath", BindingFlags.Static | BindingFlags.NonPublic)! + .CreateDelegate>(); + private readonly TempFileStorage _storage = new TempFileStorage(); protected override IFileProvider GetFileProvider() => @@ -37,4 +42,20 @@ protected override DirectoryInfo GetDirectoryInfo() => [TestCase("/modules/profile/assets", "/*.js", ExpectedResult = null)] public string? ResolveGlobFilter(string prefix, string filter) => s_resolveGlobFilter(prefix, filter); + + [TestCase("/", "/", ExpectedResult = "/")] + [TestCase("/", "/foo", ExpectedResult = "/foo")] + [TestCase("/", "/a/b/c", ExpectedResult = "/a/b/c")] + + [TestCase("/a/b", "/a/b", ExpectedResult = "/")] + + [TestCase("/a/b", "/a/b/c", ExpectedResult = "/c")] + [TestCase("/a/b", "/a/b/c/d", ExpectedResult = "/c/d")] + + [TestCase("/a/b", "/a/bc", ExpectedResult = null)] + + [TestCase("/a/b", "/a/c", ExpectedResult = null)] + [TestCase("/a/b", "/a", ExpectedResult = null)] + public string? ResolvePath(string prefix, string path) => + s_resolvePath(prefix, path); } From 1dc71cdb523bde658a392cc09cca4b7bbd65e62b Mon Sep 17 00:00:00 2001 From: rameel Date: Sat, 28 Mar 2026 21:21:58 +0500 Subject: [PATCH 2/3] Add tests --- .../PrefixedFileProviderTests.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/Ramstack.FileProviders.Tests/PrefixedFileProviderTests.cs b/tests/Ramstack.FileProviders.Tests/PrefixedFileProviderTests.cs index 00fdce8..66f6773 100644 --- a/tests/Ramstack.FileProviders.Tests/PrefixedFileProviderTests.cs +++ b/tests/Ramstack.FileProviders.Tests/PrefixedFileProviderTests.cs @@ -58,4 +58,36 @@ protected override DirectoryInfo GetDirectoryInfo() => [TestCase("/a/b", "/a", ExpectedResult = null)] public string? ResolvePath(string prefix, string path) => s_resolvePath(prefix, path); + + [Test] + public void RootPrefix_GetFileInfo_DelegatesToInnerProvider() + { + using var provider = new PrefixedFileProvider("/", + new PhysicalFileProvider(_storage.Root, ExclusionFilters.None)); + + var file = provider.GetFileInfo("/project/README.md"); + Assert.That(file.Exists, Is.True); + Assert.That(file.IsDirectory, Is.False); + } + + [Test] + public void RootPrefix_GetDirectoryContents_DelegatesToInnerProvider() + { + using var provider = new PrefixedFileProvider("/", + new PhysicalFileProvider(_storage.Root, ExclusionFilters.None)); + + var contents = provider.GetDirectoryContents("/project/docs"); + Assert.That(contents.Exists, Is.True); + Assert.That(contents.Any(), Is.True); + } + + [Test] + public void RootPrefix_GetFileInfo_ReturnsNotFound_ForMissingFile() + { + using var provider = new PrefixedFileProvider("/", + new PhysicalFileProvider(_storage.Root, ExclusionFilters.None)); + + var file = provider.GetFileInfo("/project/nonexistent.txt"); + Assert.That(file.Exists, Is.False); + } } From da172f8b19364faa350bc38e93b360dccc2563be Mon Sep 17 00:00:00 2001 From: rameel Date: Sat, 28 Mar 2026 21:24:37 +0500 Subject: [PATCH 3/3] Update tests --- .../PrefixedFileProviderTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Ramstack.FileProviders.Tests/PrefixedFileProviderTests.cs b/tests/Ramstack.FileProviders.Tests/PrefixedFileProviderTests.cs index 66f6773..a88668b 100644 --- a/tests/Ramstack.FileProviders.Tests/PrefixedFileProviderTests.cs +++ b/tests/Ramstack.FileProviders.Tests/PrefixedFileProviderTests.cs @@ -60,7 +60,7 @@ protected override DirectoryInfo GetDirectoryInfo() => s_resolvePath(prefix, path); [Test] - public void RootPrefix_GetFileInfo_DelegatesToInnerProvider() + public void GetFileInfo_RootPrefix_DelegatesToInnerProvider() { using var provider = new PrefixedFileProvider("/", new PhysicalFileProvider(_storage.Root, ExclusionFilters.None)); @@ -71,7 +71,7 @@ public void RootPrefix_GetFileInfo_DelegatesToInnerProvider() } [Test] - public void RootPrefix_GetDirectoryContents_DelegatesToInnerProvider() + public void GetDirectoryContents_RootPrefix_DelegatesToInnerProvider() { using var provider = new PrefixedFileProvider("/", new PhysicalFileProvider(_storage.Root, ExclusionFilters.None)); @@ -82,7 +82,7 @@ public void RootPrefix_GetDirectoryContents_DelegatesToInnerProvider() } [Test] - public void RootPrefix_GetFileInfo_ReturnsNotFound_ForMissingFile() + public void GetFileInfo_RootPrefix_MissingFile_ReturnsNotFound() { using var provider = new PrefixedFileProvider("/", new PhysicalFileProvider(_storage.Root, ExclusionFilters.None));