mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-10-08 06:05:02 -04:00
126 lines
5.2 KiB
C#
126 lines
5.2 KiB
C#
using allstarr.Core.ManagedFiles;
|
|
using allstarr.Core.Storage;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace allstarr.Tests;
|
|
|
|
public sealed class ManagedFileReferenceStoreTests : IAsyncLifetime
|
|
{
|
|
private readonly string root = Path.Combine(Path.GetTempPath(), $"allstarr-managed-references-{Guid.NewGuid():N}");
|
|
private PostgresTestDatabase database = null!;
|
|
private DbContextOptions<AllstarrDbContext> options = null!;
|
|
private Guid tenantId;
|
|
private Guid userId;
|
|
|
|
public async Task InitializeAsync()
|
|
{
|
|
Directory.CreateDirectory(root);
|
|
database = await PostgresTestDatabase.CreateAsync();
|
|
options = database.Options;
|
|
await using var db = new AllstarrDbContext(options);
|
|
tenantId = Guid.CreateVersion7();
|
|
userId = Guid.CreateVersion7();
|
|
db.Tenants.Add(new TenantRecord
|
|
{
|
|
Id = tenantId,
|
|
Slug = "managed-references",
|
|
Name = "Managed references",
|
|
CreatedAt = DateTimeOffset.UtcNow
|
|
});
|
|
db.Users.Add(new PlatformUserRecord
|
|
{
|
|
Id = userId,
|
|
TenantId = tenantId,
|
|
DisplayName = "Managed reference user",
|
|
Status = PlatformUserStatus.Active,
|
|
CreatedAt = DateTimeOffset.UtcNow,
|
|
UpdatedAt = DateTimeOffset.UtcNow
|
|
});
|
|
await db.SaveChangesAsync();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Store_PersistsIdempotentAcquireAndOneTimeRelease()
|
|
{
|
|
var fileId = Guid.CreateVersion7();
|
|
var record = Record(fileId);
|
|
await using (var db = new AllstarrDbContext(options))
|
|
{
|
|
var store = new EfManagedFileOwnershipStore(db);
|
|
var first = Reference(fileId, "favorite:a");
|
|
Assert.Equal(1, (await store.AddAsync(record, first, default)).ReferenceCount);
|
|
Assert.Equal(1, (await store.AddReferenceAsync(fileId,
|
|
Reference(fileId, "favorite:a"), default)).ReferenceCount);
|
|
Assert.Equal(2, (await store.AddReferenceAsync(fileId,
|
|
Reference(fileId, "playlist:b"), default)).ReferenceCount);
|
|
Assert.Equal(1, (await store.ReleaseReferenceAsync(fileId, "playlist:b", default)).ReferenceCount);
|
|
Assert.Equal(1, (await store.ReleaseReferenceAsync(fileId, "playlist:b", default)).ReferenceCount);
|
|
}
|
|
|
|
await using var verify = new AllstarrDbContext(options);
|
|
Assert.Equal(1, (await verify.ManagedFiles.SingleAsync()).ReferenceCount);
|
|
var references = await verify.ManagedFileReferences.OrderBy(item => item.ReferenceKey).ToListAsync();
|
|
Assert.Equal(2, references.Count);
|
|
Assert.Null(references[0].ReleasedAt);
|
|
Assert.NotNull(references[1].ReleasedAt);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Store_RejectsReferenceOutsideManagedOwnershipScope()
|
|
{
|
|
await using var db = new AllstarrDbContext(options);
|
|
var store = new EfManagedFileOwnershipStore(db);
|
|
var record = Record(Guid.CreateVersion7());
|
|
var reference = Reference(record.Id, "favorite:wrong") with { TenantId = Guid.CreateVersion7() };
|
|
|
|
await Assert.ThrowsAsync<UnauthorizedAccessException>(() => store.AddAsync(record, reference, default));
|
|
Assert.Empty(await db.ManagedFiles.ToListAsync());
|
|
Assert.Empty(await db.ManagedFileReferences.ToListAsync());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ConcurrentAcquireOfSameStableReference_RemainsSingleAndCountedOnce()
|
|
{
|
|
var fileId = Guid.CreateVersion7();
|
|
await using (var seed = new AllstarrDbContext(options))
|
|
{
|
|
var store = new EfManagedFileOwnershipStore(seed);
|
|
await store.AddAsync(Record(fileId), Reference(fileId, "seed"), default);
|
|
}
|
|
|
|
async Task Acquire()
|
|
{
|
|
await using var db = new AllstarrDbContext(options);
|
|
var store = new EfManagedFileOwnershipStore(db);
|
|
await store.AddReferenceAsync(fileId, Reference(fileId, "concurrent"), default);
|
|
}
|
|
|
|
await Task.WhenAll(Acquire(), Acquire());
|
|
await using var verify = new AllstarrDbContext(options);
|
|
Assert.Equal(2, await verify.ManagedFiles.Where(item => item.Id == fileId)
|
|
.Select(item => item.ReferenceCount).SingleAsync());
|
|
Assert.Equal(2, await verify.ManagedFileReferences.CountAsync(item =>
|
|
item.ManagedFileId == fileId && item.ReleasedAt == null));
|
|
}
|
|
|
|
private ManagedFileRecord Record(Guid id) => new(
|
|
id, Guid.CreateVersion7(), Path.Combine(root, $"{id:N}.flac"), new string('a', 64), 10,
|
|
ManagedFilePlacementMethod.Copy, tenantId, userId, "music", null, "tenant:user:music",
|
|
1, true, DateTimeOffset.UtcNow)
|
|
{
|
|
TargetRootPath = root,
|
|
FileSystemDeviceId = "1a",
|
|
FileSystemFileId = id.ToString("N"),
|
|
FileSystemLinkCount = 1
|
|
};
|
|
|
|
private ManagedFileReference Reference(Guid fileId, string key) => new(
|
|
Guid.CreateVersion7(), fileId, tenantId, userId, "tenant:user:music", key, DateTimeOffset.UtcNow);
|
|
|
|
public async Task DisposeAsync()
|
|
{
|
|
if (Directory.Exists(root)) Directory.Delete(root, recursive: true);
|
|
if (database is not null) await database.DisposeAsync();
|
|
}
|
|
}
|