LANCommander/LANCommander.SDK.Tests/Install/GameInstallationFileListTests.cs
2026-02-23 19:03:18 -06:00

281 lines
10 KiB
C#

using LANCommander.SDK.Services;
using ManifestGame = LANCommander.SDK.Models.Manifest.Game;
namespace LANCommander.SDK.Tests.Install;
public class GameInstallationFileListTests
{
private static GameInstallationFileList MakeFileList(string installDir, Guid gameId, params string[] filePaths)
{
var list = new GameInstallationFileList(installDir, gameId);
list.BaseGame.AddFiles(filePaths.Select(p => new GameInstallationFileListEntry.FileEntry
{
EntryPath = p,
LocalPath = p
}));
return list;
}
// ── MergeBase ────────────────────────────────────────────────────────────
[Fact]
public void MergeBase_MergesBaseGameFilesIntoTarget()
{
var gameId = Guid.NewGuid();
var target = MakeFileList(@"C:\Games\TestGame", gameId, "game.exe");
var source = MakeFileList(@"C:\Games\TestGame", gameId, "data.pak");
target.MergeBase(source);
Assert.Equal(2, target.BaseGame.Files.Count);
}
[Fact]
public void MergeBase_DoesNotDuplicateExistingFiles()
{
var gameId = Guid.NewGuid();
var target = MakeFileList(@"C:\Games\TestGame", gameId, "game.exe");
var source = MakeFileList(@"C:\Games\TestGame", gameId, "game.exe", "readme.txt");
target.MergeBase(source);
Assert.Equal(2, target.BaseGame.Files.Count);
}
// ── MergeBaseAsDependentGame ──────────────────────────────────────────────
[Fact]
public void MergeBaseAsDependentGame_CreatesDependentGameEntry()
{
var baseGameId = Guid.NewGuid();
var addonId = Guid.NewGuid();
var target = MakeFileList(@"C:\Games\TestGame", baseGameId);
var addonFileList = MakeFileList(@"C:\Games\TestGame", addonId, "addon.pak");
target.MergeBaseAsDependentGame(addonId, addonFileList);
Assert.True(target.DependentGames.ContainsKey(addonId));
}
[Fact]
public void MergeBaseAsDependentGame_CopiesFilesFromSourceBaseGame()
{
var baseGameId = Guid.NewGuid();
var addonId = Guid.NewGuid();
var target = MakeFileList(@"C:\Games\TestGame", baseGameId);
var addonFileList = MakeFileList(@"C:\Games\TestGame", addonId, "addon.pak", "addon_data.pak");
target.MergeBaseAsDependentGame(addonId, addonFileList);
Assert.Equal(2, target.DependentGames[addonId].BaseGame.Files.Count);
}
[Fact]
public void MergeBaseAsDependentGame_SetsManifestOnNewDependentGame()
{
var baseGameId = Guid.NewGuid();
var addonId = Guid.NewGuid();
var manifest = new ManifestGame { Id = addonId, Title = "Test Addon" };
var target = MakeFileList(@"C:\Games\TestGame", baseGameId);
var addonFileList = MakeFileList(@"C:\Games\TestGame", addonId);
addonFileList.BaseGame.Manifest = manifest;
target.MergeBaseAsDependentGame(addonId, addonFileList);
Assert.Equal(manifest, target.DependentGames[addonId].BaseGame.Manifest);
}
[Fact]
public void MergeBaseAsDependentGame_MergesIntoExistingDependentGame()
{
var baseGameId = Guid.NewGuid();
var addonId = Guid.NewGuid();
var target = MakeFileList(@"C:\Games\TestGame", baseGameId);
var firstAddonFiles = MakeFileList(@"C:\Games\TestGame", addonId, "file1.pak");
target.MergeBaseAsDependentGame(addonId, firstAddonFiles);
var secondAddonFiles = MakeFileList(@"C:\Games\TestGame", addonId, "file2.pak");
target.MergeBaseAsDependentGame(addonId, secondAddonFiles);
Assert.Single(target.DependentGames);
Assert.Equal(2, target.DependentGames[addonId].BaseGame.Files.Count);
}
[Fact]
public void MergeBaseAsDependentGame_DoesNotDuplicateFilesOnSecondMerge()
{
var baseGameId = Guid.NewGuid();
var addonId = Guid.NewGuid();
var target = MakeFileList(@"C:\Games\TestGame", baseGameId);
var addonFiles = MakeFileList(@"C:\Games\TestGame", addonId, "shared.pak");
target.MergeBaseAsDependentGame(addonId, addonFiles);
target.MergeBaseAsDependentGame(addonId, addonFiles);
Assert.Single(target.DependentGames[addonId].BaseGame.Files);
}
// ── MergeDependentGames ───────────────────────────────────────────────────
[Fact]
public void MergeDependentGames_CopiesDependentGamesFromSource()
{
var baseGameId = Guid.NewGuid();
var addonId = Guid.NewGuid();
var source = MakeFileList(@"C:\Games\TestGame", baseGameId);
var addonFileList = MakeFileList(@"C:\Games\TestGame", addonId, "addon.pak");
source.MergeBaseAsDependentGame(addonId, addonFileList);
var target = MakeFileList(@"C:\Games\TestGame", baseGameId);
target.MergeDependentGames(source);
Assert.True(target.DependentGames.ContainsKey(addonId));
}
[Fact]
public void MergeDependentGames_WithNullSource_DoesNotThrow()
{
var gameId = Guid.NewGuid();
var target = MakeFileList(@"C:\Games\TestGame", gameId);
target.MergeDependentGames(null);
Assert.Empty(target.DependentGames);
}
[Fact]
public void MergeDependentGames_WithEmptySource_LeavesTargetUnchanged()
{
var gameId = Guid.NewGuid();
var target = MakeFileList(@"C:\Games\TestGame", gameId);
var emptySource = MakeFileList(@"C:\Games\TestGame", gameId);
target.MergeDependentGames(emptySource);
Assert.Empty(target.DependentGames);
}
// ── Merge (combined) ──────────────────────────────────────────────────────
[Fact]
public void Merge_MergesBothBaseGameAndDependentGames()
{
var baseGameId = Guid.NewGuid();
var addonId = Guid.NewGuid();
var source = MakeFileList(@"C:\Games\TestGame", baseGameId, "new_base_file.pak");
var addonFileList = MakeFileList(@"C:\Games\TestGame", addonId, "addon.pak");
source.MergeBaseAsDependentGame(addonId, addonFileList);
var target = MakeFileList(@"C:\Games\TestGame", baseGameId, "existing_base_file.pak");
target.Merge(source);
Assert.Equal(2, target.BaseGame.Files.Count);
Assert.True(target.DependentGames.ContainsKey(addonId));
}
// ── ToFlatDistinctFileEntries ─────────────────────────────────────────────
[Fact]
public void ToFlatDistinctFileEntries_ReturnsBaseGameFiles()
{
var gameId = Guid.NewGuid();
var list = MakeFileList(@"C:\Games\TestGame", gameId, "game.exe", "data.pak");
var entries = list.ToFlatDistinctFileEntries().ToList();
Assert.Equal(2, entries.Count);
}
[Fact]
public void ToFlatDistinctFileEntries_IncludesDependentGameFiles()
{
var baseGameId = Guid.NewGuid();
var addonId = Guid.NewGuid();
var list = MakeFileList(@"C:\Games\TestGame", baseGameId, "game.exe");
var addonFileList = MakeFileList(@"C:\Games\TestGame", addonId, "addon.pak");
list.MergeBaseAsDependentGame(addonId, addonFileList);
var entries = list.ToFlatDistinctFileEntries().ToList();
Assert.Equal(2, entries.Count);
Assert.Contains(entries, e => e.EntryPath == "game.exe");
Assert.Contains(entries, e => e.EntryPath == "addon.pak");
}
[Fact]
public void ToFlatDistinctFileEntries_DeduplicatesFilesAcrossBaseAndDependentGames()
{
var baseGameId = Guid.NewGuid();
var addonId = Guid.NewGuid();
// Same file path in both base game and addon
var list = MakeFileList(@"C:\Games\TestGame", baseGameId, "shared.cfg");
var addonFileList = MakeFileList(@"C:\Games\TestGame", addonId, "shared.cfg", "addon.pak");
list.MergeBaseAsDependentGame(addonId, addonFileList);
var entries = list.ToFlatDistinctFileEntries().ToList();
// shared.cfg should appear only once, addon.pak once
Assert.Equal(2, entries.Count);
Assert.Single(entries.Where(e => e.EntryPath.Equals("shared.cfg", StringComparison.OrdinalIgnoreCase)));
}
[Fact]
public void ToFlatDistinctFileEntries_BaseGameFileWinsOverDependentOnDuplicate()
{
var baseGameId = Guid.NewGuid();
var addonId = Guid.NewGuid();
const string sharedPath = "shared.cfg";
const string baseLocalPath = @"C:\base\shared.cfg";
const string addonLocalPath = @"C:\addon\shared.cfg";
var list = new GameInstallationFileList(@"C:\Games\TestGame", baseGameId);
list.BaseGame.AddFile(new GameInstallationFileListEntry.FileEntry
{
EntryPath = sharedPath,
LocalPath = baseLocalPath
});
var addonFileList = new GameInstallationFileList(@"C:\Games\TestGame", addonId);
addonFileList.BaseGame.AddFile(new GameInstallationFileListEntry.FileEntry
{
EntryPath = sharedPath,
LocalPath = addonLocalPath
});
list.MergeBaseAsDependentGame(addonId, addonFileList);
var entries = list.ToFlatDistinctFileEntries().ToList();
// GroupBy + First means the base game's entry wins
var entry = Assert.Single(entries.Where(e => e.EntryPath == sharedPath));
Assert.Equal(baseLocalPath, entry.LocalPath);
}
[Fact]
public void ToFlatDistinctFileEntries_WithMultipleDependentGames_ReturnsAllFiles()
{
var baseGameId = Guid.NewGuid();
var addon1Id = Guid.NewGuid();
var addon2Id = Guid.NewGuid();
var list = MakeFileList(@"C:\Games\TestGame", baseGameId, "base.exe");
list.MergeBaseAsDependentGame(addon1Id, MakeFileList(@"C:\Games\TestGame", addon1Id, "addon1.pak"));
list.MergeBaseAsDependentGame(addon2Id, MakeFileList(@"C:\Games\TestGame", addon2Id, "addon2.pak"));
var entries = list.ToFlatDistinctFileEntries().ToList();
Assert.Equal(3, entries.Count);
}
[Fact]
public void Empty_ReturnsInstanceWithNullInstallDirectory()
{
var empty = GameInstallationFileList.Empty;
Assert.Null(empty.InstallDirectory);
Assert.Empty(empty.DependentGames);
}
}