164 lines
4.6 KiB
C#
164 lines
4.6 KiB
C#
using FluentAssertions;
|
|
using Jellyfin.Plugin.SRFPlay.Api.Models;
|
|
using Jellyfin.Plugin.SRFPlay.Services;
|
|
using Microsoft.Extensions.Logging;
|
|
using Moq;
|
|
using Xunit;
|
|
|
|
namespace Jellyfin.Plugin.SRFPlay.Tests.UnitTests;
|
|
|
|
/// <summary>
|
|
/// Unit tests for MetadataCache.
|
|
/// </summary>
|
|
public class MetadataCacheTests : IDisposable
|
|
{
|
|
private readonly Mock<ILogger<MetadataCache>> _loggerMock;
|
|
private readonly MetadataCache _cache;
|
|
|
|
public MetadataCacheTests()
|
|
{
|
|
_loggerMock = new Mock<ILogger<MetadataCache>>();
|
|
_cache = new MetadataCache(_loggerMock.Object);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetMediaComposition_And_GetMediaComposition_ReturnsCorrectValue()
|
|
{
|
|
// Arrange
|
|
const string urn = "urn:srf:video:test-id";
|
|
var mediaComposition = new MediaComposition
|
|
{
|
|
Episode = new Episode { Id = "test-episode", Title = "Test" }
|
|
};
|
|
const int cacheDurationMinutes = 10;
|
|
|
|
// Act
|
|
_cache.SetMediaComposition(urn, mediaComposition);
|
|
var result = _cache.GetMediaComposition(urn, cacheDurationMinutes);
|
|
|
|
// Assert
|
|
result.Should().NotBeNull();
|
|
result.Should().Be(mediaComposition);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetMediaComposition_NonExistentKey_ReturnsNull()
|
|
{
|
|
// Act
|
|
var result = _cache.GetMediaComposition("non-existent-urn", 10);
|
|
|
|
// Assert
|
|
result.Should().BeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void GetMediaComposition_ExpiredEntry_ReturnsNull()
|
|
{
|
|
// Arrange
|
|
const string urn = "urn:srf:video:test-id";
|
|
var mediaComposition = new MediaComposition
|
|
{
|
|
Episode = new Episode { Id = "test-episode" }
|
|
};
|
|
|
|
// Set with cache
|
|
_cache.SetMediaComposition(urn, mediaComposition);
|
|
|
|
// Wait a tiny bit to ensure expiration
|
|
System.Threading.Thread.Sleep(10);
|
|
|
|
// Act - Try to get with 0 minute cache duration (immediate expiration)
|
|
var result = _cache.GetMediaComposition(urn, 0);
|
|
|
|
// Assert - Should be null because it's expired
|
|
result.Should().BeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveMediaComposition_ExistingUrn_RemovesValue()
|
|
{
|
|
// Arrange
|
|
const string urn = "urn:srf:video:test-id";
|
|
var mediaComposition = new MediaComposition
|
|
{
|
|
Episode = new Episode { Id = "test-episode" }
|
|
};
|
|
_cache.SetMediaComposition(urn, mediaComposition);
|
|
|
|
// Act
|
|
_cache.RemoveMediaComposition(urn);
|
|
var result = _cache.GetMediaComposition(urn, 10);
|
|
|
|
// Assert
|
|
result.Should().BeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void Clear_RemovesAllValues()
|
|
{
|
|
// Arrange
|
|
var mc1 = new MediaComposition { Episode = new Episode { Id = "episode1" } };
|
|
var mc2 = new MediaComposition { Episode = new Episode { Id = "episode2" } };
|
|
_cache.SetMediaComposition("urn1", mc1);
|
|
_cache.SetMediaComposition("urn2", mc2);
|
|
|
|
// Act
|
|
_cache.Clear();
|
|
var result1 = _cache.GetMediaComposition("urn1", 10);
|
|
var result2 = _cache.GetMediaComposition("urn2", 10);
|
|
|
|
// Assert
|
|
result1.Should().BeNull();
|
|
result2.Should().BeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void GetStatistics_ReturnsCorrectCount()
|
|
{
|
|
// Arrange
|
|
var mc1 = new MediaComposition { Episode = new Episode { Id = "episode1" } };
|
|
var mc2 = new MediaComposition { Episode = new Episode { Id = "episode2" } };
|
|
_cache.SetMediaComposition("urn1", mc1);
|
|
_cache.SetMediaComposition("urn2", mc2);
|
|
|
|
// Act
|
|
var (count, sizeEstimate) = _cache.GetStatistics();
|
|
|
|
// Assert
|
|
count.Should().Be(2);
|
|
sizeEstimate.Should().BeGreaterThan(0);
|
|
}
|
|
|
|
[Fact]
|
|
public void ConcurrentAccess_DoesNotThrow()
|
|
{
|
|
// Arrange
|
|
var tasks = new List<Task>();
|
|
|
|
// Act - Perform concurrent operations
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
var index = i;
|
|
tasks.Add(Task.Run(() =>
|
|
{
|
|
var mc = new MediaComposition { Episode = new Episode { Id = $"episode-{index}" } };
|
|
_cache.SetMediaComposition($"urn-{index}", mc);
|
|
_cache.GetMediaComposition($"urn-{index}", 10);
|
|
if (index % 2 == 0)
|
|
{
|
|
_cache.RemoveMediaComposition($"urn-{index}");
|
|
}
|
|
}));
|
|
}
|
|
|
|
// Assert - Should not throw
|
|
var action = async () => await Task.WhenAll(tasks);
|
|
action.Should().NotThrowAsync();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_cache?.Dispose();
|
|
}
|
|
}
|