diff --git a/src/Foundatio/Storage/ScopedFileStorage.cs b/src/Foundatio/Storage/ScopedFileStorage.cs index e0a7f141..e62a34f6 100644 --- a/src/Foundatio/Storage/ScopedFileStorage.cs +++ b/src/Foundatio/Storage/ScopedFileStorage.cs @@ -2,6 +2,7 @@ using System.IO; using System.Threading; using System.Threading.Tasks; +using Foundatio.Extensions; using Foundatio.Serializer; using Foundatio.Utility; @@ -13,9 +14,13 @@ public class ScopedFileStorage : IFileStorage public ScopedFileStorage(IFileStorage storage, string scope) { - UnscopedStorage = storage; - Scope = !String.IsNullOrWhiteSpace(scope) ? scope.Trim() : null; + UnscopedStorage = storage ?? throw new ArgumentNullException(nameof(storage)); + Scope = !String.IsNullOrWhiteSpace(scope) ? scope.Trim().NormalizePath() : null; _pathPrefix = Scope != null ? String.Concat(Scope, "/") : String.Empty; + + // NOTE: we can't really check reliably using Path.GetInvalidPathChars() because each storage implementation and platform could be different. + if (Scope is not null && Scope.Contains("*")) + throw new ArgumentException("Scope cannot contain a wildcard character", nameof(scope)); } public IFileStorage UnscopedStorage { get; private set; } diff --git a/tests/Foundatio.Tests/Storage/ScopedFolderFileStorageTests.cs b/tests/Foundatio.Tests/Storage/ScopedFolderFileStorageTests.cs index 7ead66db..9de3bd7f 100644 --- a/tests/Foundatio.Tests/Storage/ScopedFolderFileStorageTests.cs +++ b/tests/Foundatio.Tests/Storage/ScopedFolderFileStorageTests.cs @@ -1,5 +1,7 @@ -using System.IO; +using System; +using System.IO; using System.Threading.Tasks; +using Foundatio.Extensions; using Foundatio.Storage; using Xunit; using Xunit.Abstractions; @@ -15,6 +17,46 @@ protected override IFileStorage GetStorage() return new ScopedFileStorage(new FolderFileStorage(o => o.Folder("|DataDirectory|\\temp")), "scoped"); } + [Fact] + public void Constructor_ShouldThrowArgumentNullException_WhenFileStorageIsNull() + { + Assert.Throws(() => new ScopedFileStorage(null, "scope")); + } + + [InlineData("*")] + [Theory] + public void Constructor_ShouldThrowArgumentException_WhenScopeContainsInvalidCharacters(string scope) + { + var storage = GetStorage(); + if (storage == null) + return; + + Assert.Throws(() => new ScopedFileStorage(storage, scope)); + } + + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + [InlineData("test")] + [InlineData(" test ")] + [InlineData("|DataDirectory|\\temp")] + [InlineData("|DataDirectory|/temp")] + [Theory] + public void Constructor_ShouldInitializeProperties_WhenArgumentsAreValid(string scope) + { + var storage = GetStorage(); + if (storage == null) + return; + + var scopedStorage = new ScopedFileStorage(storage, scope); + Assert.Equal(storage, scopedStorage.UnscopedStorage); + + if (String.IsNullOrWhiteSpace(scope)) + Assert.Null(scopedStorage.Scope); + else + Assert.Equal(scope.Trim().NormalizePath(), scopedStorage.Scope); + } + [Fact] public override Task CanGetEmptyFileListOnMissingDirectoryAsync() {