using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using LibHac.Ncm; 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> _loggerMock; private SnapshotService _service; private Mock _nspExtractorMock; private Mock _archiveHander; private Mock> _mockOptions; private SnapshotOptions _options; [SetUp] public void SetUp() { _mockOptions = new Mock>(); _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>(); _archiveHander = new Mock(); _nspExtractorMock = new Mock(); _nspExtractorMock.Setup(extractor => extractor.ExtractHashFromStream(It.IsAny())).Returns("HASH"); _nspExtractorMock.Setup(extractor => extractor.ExtractFromStream(It.IsAny())).Returns( new NcaMetadataWithHash(titleId: "0000000000000000","0000000000000000", version: 1, ContentMetaType.Application, "HASH")); //Settings.RootDirs = new List { "TestData/Root1", "TestData/Root2" }; _service = new SnapshotService(_mockOptions.Object, _nspExtractorMock.Object, _archiveHander.Object, _loggerMock.Object); } [TearDown] public void TearDown() { _service.Dispose(); } [Test] public async Task BuildSnapshot_WhenFilesChanged_ShouldPersist() { // Arrange await File.WriteAllTextAsync(_options.SnapshotFile, "[]"); var initialHash = _service.GetSnapshot()?.Hash; // Add a file to Root1 var newFile = Path.Combine(_options.RootDirectories.First(), "new.nsp"); FileSystemExtensions.EnsureDirectoryExists(Path.GetDirectoryName(newFile)); // Create a new valid NSP file // copy to temp to touch modified date foreach (var file in Directory.GetFiles("../../../Data/")) { var filename = Path.GetFileName(file); var destFilename = Path.Combine(Path.GetTempPath(), filename); File.Copy(file, destFilename, true); var info = new FileInfo(destFilename) { LastWriteTimeUtc = DateTime.UtcNow }; info.CopyTo(Path.Combine(_options.RootDirectories.First(),filename), true); } // Act _service.SnapshotRebuilt+= (sender, args) => { // Assert var newHash = _service.GetSnapshot()?.Hash; Assert.That(newHash, Is.Not.EqualTo(initialHash)); }; Task.Delay(300).Wait(); _loggerMock.Verify( l => l.Log( LogLevel.Information, It.IsAny(), It.Is((v, t) => v.ToString().Contains("Snapshot rebuilt")), null, It.IsAny>()), Times.Once); } [Test] public async Task BuildSnapshot_NoChange_ShouldNotPersist() { // Act _service.BuildSnapshot(); // Act again – snapshot should be identical _service.BuildSnapshot(); // Assert _loggerMock.Verify( l => l.Log( LogLevel.Information, It.IsAny(), It.Is((v, t) => v.ToString().Contains("persisting new snapshot")), null, It.IsAny>()), Times.Never); } } }