a1ea34bc01
Consolidate data and config into separate folders that will be expected to be mapped in the container Reviewed-on: #1 Co-authored-by: Huy Nguyen <ecenshu@gmail.com> Co-committed-by: Huy Nguyen <ecenshu@gmail.com>
147 lines
5.3 KiB
C#
147 lines
5.3 KiB
C#
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Threading.Tasks;
|
||
using LibHac.Ncm;
|
||
using Microsoft.Extensions.Caching.Memory;
|
||
using Microsoft.Extensions.Hosting.Internal;
|
||
using Microsoft.Extensions.Logging;
|
||
using Microsoft.Extensions.Options;
|
||
using Moq;
|
||
using NUnit.Framework;
|
||
using TinfoilVibeServer.Models;
|
||
using TinfoilVibeServer.Services;
|
||
using TinfoilVibeServer.Utilities;
|
||
|
||
namespace TinfoilVibeServerTest.Tests
|
||
{
|
||
[TestFixture]
|
||
public class SnapshotServiceTests
|
||
{
|
||
private Mock<ILogger<SnapshotService>> _loggerMock;
|
||
private SnapshotService _service;
|
||
private Mock<INSPExtractor> _nspExtractorMock;
|
||
private Mock<IArchiveHandler> _archiveHander;
|
||
private Mock<IOptionsMonitor<SnapshotOptions>> _mockOptions;
|
||
private SnapshotOptions _options;
|
||
private MemoryCache _memoryCache;
|
||
|
||
[SetUp]
|
||
public void SetUp()
|
||
{
|
||
_mockOptions = new Mock<IOptionsMonitor<SnapshotOptions>>();
|
||
_options = new SnapshotOptions()
|
||
{
|
||
RomExtensions = [".nsp"],
|
||
RootDirectories = ["TestData/ROMS"],
|
||
SnapshotFile = "TestData/snapshot.json",
|
||
SnapshotBackupFile = "TestData/snapshot.bak"
|
||
};
|
||
/*// ensure ROM test directory has test files removed
|
||
foreach (var file in Directory.GetFiles("TestData/ROMS"))
|
||
{
|
||
File.Delete(file);
|
||
}*/
|
||
_mockOptions.Setup(m => m.CurrentValue).Returns(_options);
|
||
_loggerMock = new Mock<ILogger<SnapshotService>>();
|
||
_archiveHander = new Mock<IArchiveHandler>();
|
||
_nspExtractorMock = new Mock<INSPExtractor>();
|
||
var hostEnv = new Mock<HostingEnvironment>();
|
||
var memoryCacheOptions = Options.Create(new MemoryCacheOptions());
|
||
_memoryCache = new MemoryCache(memoryCacheOptions);
|
||
|
||
|
||
_nspExtractorMock.Setup(extractor => extractor.ExtractHashFromStream(It.IsAny<Stream>())).Returns("HASH");
|
||
_nspExtractorMock.Setup(extractor => extractor.ExtractFromStream(It.IsAny<Stream>())).Returns(
|
||
new NcaMetadataWithHash(titleId: "0000000000000000","0000000000000000", version: 1, ContentMetaType.Application, "HASH"));
|
||
//Settings.RootDirs = new List<string> { "TestData/Root1", "TestData/Root2" };
|
||
|
||
_service = new SnapshotService(_memoryCache, _mockOptions.Object, _nspExtractorMock.Object, _archiveHander.Object, _loggerMock.Object, hostEnv.Object);
|
||
}
|
||
|
||
[TearDown]
|
||
public void TearDown()
|
||
{
|
||
_service.Dispose();
|
||
_memoryCache.Dispose();
|
||
}
|
||
|
||
[Test]
|
||
public async Task BuildSnapshot_WhenFilesChanged_ShouldPersist()
|
||
{
|
||
// Arrange
|
||
var initialHash = _service.GetSnapshot()?.Hash;
|
||
var rebuilding = false;
|
||
var rebuilt = false;
|
||
CancellationTokenSource snapshotRebuilding = new();
|
||
_service.SnapshotRebuilding += (sender, args) =>
|
||
{
|
||
rebuilding = true;
|
||
snapshotRebuilding.Cancel();
|
||
};
|
||
CancellationTokenSource snapshotPersisting = new();
|
||
_service.SnapshotRebuilt+= (sender, args) =>
|
||
{
|
||
rebuilt = true;
|
||
snapshotPersisting.Cancel();
|
||
// Assert
|
||
var newHash = _service.GetSnapshot()?.Hash;
|
||
Assert.That(newHash, Is.Not.EqualTo(initialHash));
|
||
};
|
||
Timer timer = new(state =>
|
||
{
|
||
snapshotPersisting.Cancel();
|
||
snapshotRebuilding.Cancel();
|
||
}, null, 20*1000, 0);
|
||
await File.WriteAllTextAsync(_options.SnapshotFile, "[]", snapshotPersisting.Token);
|
||
// Add a file to Root1
|
||
var newFile = Path.Combine(_options.RootDirectories.First(), "new.nsp");
|
||
|
||
// Act
|
||
await File.WriteAllTextAsync(newFile,"TEST");
|
||
|
||
Task.Delay(4000).Wait();
|
||
try
|
||
{
|
||
while (_memoryCache.Count > 0)
|
||
{
|
||
Task.Delay(200).Wait(snapshotRebuilding.Token);
|
||
}
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
Assert.That(rebuilding, Is.True);
|
||
}
|
||
|
||
try
|
||
{
|
||
while (_memoryCache.Count > 0)
|
||
{
|
||
Task.Delay(200).Wait(snapshotPersisting.Token);
|
||
}
|
||
}
|
||
catch (OperationCanceledException e)
|
||
{
|
||
Assert.That(rebuilt, Is.True);
|
||
}
|
||
}
|
||
|
||
[Test]
|
||
public async Task BuildSnapshot_NoChange_ShouldNotPersist()
|
||
{
|
||
// Act
|
||
_service.BuildSnapshotAsync();
|
||
|
||
// Act again – snapshot should be identical
|
||
_service.BuildSnapshotAsync();
|
||
|
||
// Assert
|
||
_loggerMock.Verify(
|
||
l => l.Log(
|
||
LogLevel.Information,
|
||
It.IsAny<EventId>(),
|
||
It.Is<It.IsAnyType>((v, t) => v.ToString().Contains("persisting new snapshot")),
|
||
null,
|
||
It.IsAny<Func<It.IsAnyType, Exception, string>>()), Times.Never);
|
||
}
|
||
}
|
||
} |