Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using ManagedCode.Storage.FileSystem;
using ManagedCode.Storage.FileSystem.Options;
using ManagedCode.Storage.Tests.VirtualFileSystem.Fixtures;
using ManagedCode.Storage.VirtualFileSystem.Core;
using ManagedCode.Storage.VirtualFileSystem.Options;
using Shouldly;
using Xunit;

namespace ManagedCode.Storage.Tests.VirtualFileSystem;

[Collection(VirtualFileSystemCollection.Name)]
public sealed class FileSystemVirtualFileSystemUnicodeMountTests
{
[Theory]
[MemberData(nameof(UnicodeVfsTestCases.FolderScenarios), MemberType = typeof(UnicodeVfsTestCases))]
public async Task MountingExistingUnicodeDirectories_ShouldExposeFiles(
string directoryName,
string fileName,
string content)
{
var rootFolder = Path.Combine(Directory.GetCurrentDirectory(), "managedcode-vfs-existing", Guid.NewGuid().ToString("N"));
Comment thread
KSemenenko marked this conversation as resolved.
var internationalFolder = Path.Combine(rootFolder, "international", directoryName);
Directory.CreateDirectory(internationalFolder);

var seededFilePath = Path.Combine(internationalFolder, $"{fileName}.txt");
await File.WriteAllTextAsync(seededFilePath, content);

var options = new FileSystemStorageOptions
{
BaseFolder = rootFolder,
CreateContainerIfNotExists = true
};

var storage = new FileSystemStorage(options);

async ValueTask Cleanup()
{
try
{
await storage.RemoveContainerAsync();
}
finally
{
if (Directory.Exists(rootFolder))
{
Directory.Delete(rootFolder, recursive: true);
}
}
}

await using var context = await VirtualFileSystemTestContext.CreateAsync(
storage,
containerName: string.Empty,
ownsStorage: true,
serviceProvider: null,
cleanup: Cleanup);

var vfs = context.FileSystem;
var expectedPath = new VfsPath($"/international/{directoryName}/{fileName}.txt");

(await vfs.FileExistsAsync(expectedPath)).ShouldBeTrue();

var file = await vfs.GetFileAsync(expectedPath);
var actualContent = await file.ReadAllTextAsync();
actualContent.ShouldBe(content);

var entries = new List<IVfsNode>();
await foreach (var entry in vfs.ListAsync(new VfsPath($"/international/{directoryName}"), new ListOptions
{
IncludeDirectories = false,
IncludeFiles = true,
Recursive = false
}))
{
entries.Add(entry);
}

entries.ShouldContain(e => e.Path.Value == expectedPath.Value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace ManagedCode.Storage.Tests.VirtualFileSystem.Fixtures;

public sealed class FileSystemVirtualFileSystemFixture : IVirtualFileSystemFixture, IAsyncLifetime
{
private readonly string _rootPath = Path.Combine(Path.GetTempPath(), "managedcode-vfs-matrix", Guid.NewGuid().ToString("N"));
private readonly string _rootPath = Path.Combine(Directory.GetCurrentDirectory(), "managedcode-vfs-matrix", Guid.NewGuid().ToString("N"));

public VirtualFileSystemCapabilities Capabilities { get; } = new();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Collections.Generic;

namespace ManagedCode.Storage.Tests.VirtualFileSystem;

public static class UnicodeVfsTestCases
{
public static IEnumerable<object[]> FolderScenarios => new[]
{
new object[] { "Українська-папка", "лист-привіт", "Привіт з Києва!" },
new object[] { "中文目錄", "測試文件", "雲端中的內容" },
new object[] { "日本語ディレクトリ", "テストファイル", "東京からこんにちは" },
new object[] { "한국어_폴더", "테스트-파일", "부산에서 안녕하세요" },
Comment thread
KSemenenko marked this conversation as resolved.
new object[] { "emoji📁", "😀-файл", "multi🌐lingual content" }
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace ManagedCode.Storage.Tests.VirtualFileSystem;

public class VirtualFileSystemManagerTests : IAsyncLifetime
{
private readonly string _basePath = Path.Combine(Path.GetTempPath(), "managedcode-vfs-manager", Guid.NewGuid().ToString());
private readonly string _basePath = Path.Combine(Directory.GetCurrentDirectory(), "managedcode-vfs-manager", Guid.NewGuid().ToString());
private ServiceProvider _serviceProvider = null!;
private IStorage _storage = null!;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@ protected VirtualFileSystemTests(TFixture fixture)
[Fact]
public async Task WriteAndReadFile_ShouldRoundtrip()
{
if (!Capabilities.Enabled)
{
return;
}

await using var context = await CreateContextAsync();
var vfs = context.FileSystem;

Expand All @@ -52,11 +47,6 @@ public async Task WriteAndReadFile_ShouldRoundtrip()
[Fact]
public async Task FileExistsAsync_ShouldCacheResults()
{
if (!Capabilities.Enabled)
{
return;
}

await using var context = await CreateContextAsync();
var vfs = context.FileSystem;
var metadataManager = context.MetadataManager;
Expand All @@ -79,7 +69,7 @@ public async Task FileExistsAsync_ShouldCacheResults()
[Fact]
public async Task ListAsync_ShouldEnumerateAllEntries()
{
if (!Capabilities.Enabled || !Capabilities.SupportsListing)
if (!Capabilities.SupportsListing)
{
return;
}
Expand Down Expand Up @@ -116,11 +106,6 @@ public async Task ListAsync_ShouldEnumerateAllEntries()
[Fact]
public async Task DeleteFile_ShouldRemoveFromUnderlyingStorage()
{
if (!Capabilities.Enabled)
{
return;
}

await using var context = await CreateContextAsync();
var vfs = context.FileSystem;
var metadataManager = context.MetadataManager;
Expand Down Expand Up @@ -149,11 +134,6 @@ public async Task DeleteFile_ShouldRemoveFromUnderlyingStorage()
[Fact]
public async Task GetMetadataAsync_ShouldCacheCustomMetadata()
{
if (!Capabilities.Enabled)
{
return;
}

await using var context = await CreateContextAsync();
var vfs = context.FileSystem;
var metadataManager = context.MetadataManager;
Expand All @@ -178,10 +158,54 @@ await file.SetMetadataAsync(new Dictionary<string, string>
metadataManager.CustomMetadataRequests.ShouldBe(0);
}

[Theory]
[MemberData(nameof(UnicodeVfsTestCases.FolderScenarios), MemberType = typeof(UnicodeVfsTestCases))]
public async Task WriteAndReadFile_WithUnicodeDirectories_ShouldRoundtrip(
string directoryName,
string fileName,
string content)
{
await using var context = await CreateContextAsync();
var vfs = context.FileSystem;

var path = new VfsPath($"/international/{directoryName}/{fileName}.txt");
var file = await vfs.GetFileAsync(path);

await file.WriteAllTextAsync(content);

(await file.ReadAllTextAsync()).ShouldBe(content);
file.Path.GetFileName().ShouldBe($"{fileName}.txt");
file.Path.GetFileNameWithoutExtension().ShouldBe(fileName);
file.Path.GetExtension().ShouldBe(".txt");
file.Path.GetParent().Value.ShouldBe($"/international/{directoryName}");
file.Path.ToBlobKey().ShouldBe($"international/{directoryName}/{fileName}.txt");

(await vfs.FileExistsAsync(path)).ShouldBeTrue();

if (Capabilities.SupportsListing)
{
var entries = new List<IVfsNode>();
await foreach (var entry in vfs.ListAsync(new VfsPath($"/international/{directoryName}"), new ListOptions
{
IncludeFiles = true,
IncludeDirectories = false,
Recursive = false
}))
{
entries.Add(entry);
}

entries.ShouldContain(e => e.Path.Value == path.Value);
}

(await file.DeleteAsync()).ShouldBeTrue();
(await vfs.FileExistsAsync(path)).ShouldBeFalse();
}

[Fact]
public async Task DeleteDirectoryAsync_NonRecursive_ShouldPreserveNestedContent()
{
if (!Capabilities.Enabled || !Capabilities.SupportsDirectoryDelete)
if (!Capabilities.SupportsDirectoryDelete)
{
return;
}
Expand All @@ -202,7 +226,7 @@ public async Task DeleteDirectoryAsync_NonRecursive_ShouldPreserveNestedContent(
[Fact]
public async Task DeleteDirectoryAsync_Recursive_ShouldRemoveAllContent()
{
if (!Capabilities.Enabled || !Capabilities.SupportsDirectoryDelete)
if (!Capabilities.SupportsDirectoryDelete)
{
return;
}
Expand All @@ -223,7 +247,7 @@ public async Task DeleteDirectoryAsync_Recursive_ShouldRemoveAllContent()
[Fact]
public async Task MoveAsync_ShouldRelocateFile()
{
if (!Capabilities.Enabled || !Capabilities.SupportsMove)
if (!Capabilities.SupportsMove)
{
return;
}
Expand All @@ -249,7 +273,7 @@ public async Task MoveAsync_ShouldRelocateFile()
[Fact]
public async Task CopyAsync_ShouldCopyDirectoryRecursively()
{
if (!Capabilities.Enabled || !Capabilities.SupportsDirectoryCopy)
if (!Capabilities.SupportsDirectoryCopy)
{
return;
}
Expand Down Expand Up @@ -282,11 +306,6 @@ public async Task CopyAsync_ShouldCopyDirectoryRecursively()
[Fact]
public async Task ReadRangeAsync_ShouldReturnSlice()
{
if (!Capabilities.Enabled)
{
return;
}

await using var context = await CreateContextAsync();
var vfs = context.FileSystem;

Expand All @@ -300,7 +319,7 @@ public async Task ReadRangeAsync_ShouldReturnSlice()
[Fact]
public async Task ListAsync_WithDirectoryFilter_ShouldExcludeDirectoriesWhenRequested()
{
if (!Capabilities.Enabled || !Capabilities.SupportsListing)
if (!Capabilities.SupportsListing)
{
return;
}
Expand Down Expand Up @@ -332,7 +351,7 @@ public async Task ListAsync_WithDirectoryFilter_ShouldExcludeDirectoriesWhenRequ
[Fact]
public async Task DirectoryStats_ShouldAggregateInformation()
{
if (!Capabilities.Enabled || !Capabilities.SupportsDirectoryStats)
if (!Capabilities.SupportsDirectoryStats)
{
return;
}
Expand All @@ -358,11 +377,6 @@ public async Task DirectoryStats_ShouldAggregateInformation()
[InlineData(5)]
public async Task LargeFile_ShouldRoundTripViaStreams(int gigabytes)
{
if (!Capabilities.Enabled)
{
return;
}

var sizeBytes = LargeFileTestHelper.ResolveSizeBytes(gigabytes);

await using var context = await CreateContextAsync();
Expand Down
Loading