Skip to content

Commit

Permalink
Merge pull request #1932 from Nexus-Mods/fix/1925-clean-directories
Browse files Browse the repository at this point in the history
Add Synchronizer GeneralModManagementTests
  • Loading branch information
Al12rs authored Aug 27, 2024
2 parents 444fbad + 42e48e7 commit 5c946ad
Show file tree
Hide file tree
Showing 7 changed files with 324 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,12 @@ private void CleanDirectories(IEnumerable<GamePath> toDelete, DiskState newState
var seenDirectories = new HashSet<GamePath>();
var directoriesToDelete = new HashSet<GamePath>();

var newStatePaths = newState.SelectMany(e => ((GamePath)e.Path).GetAllParents()).ToHashSet();
var newStatePaths = newState.SelectMany(e =>
{
// We need folder paths, so skip first path as it is the file path itself
return ((GamePath)e.Path).GetAllParents().Skip(1);
}
).ToHashSet();

foreach (var entry in toDelete)
{
Expand Down
5 changes: 5 additions & 0 deletions tests/Games/NexusMods.Games.TestFramework/AGameTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
using NexusMods.Abstractions.IO.StreamFactories;
using NexusMods.Abstractions.Library.Models;
using NexusMods.Abstractions.Loadouts;
using NexusMods.Abstractions.Loadouts.Extensions;
using NexusMods.Abstractions.Loadouts.Synchronizers;
using NexusMods.DataModel;
using NexusMods.Hashing.xxHash64;
using NexusMods.MnemonicDB.Abstractions;
using NexusMods.MnemonicDB.Abstractions.BuiltInEntities;
using NexusMods.MnemonicDB.Abstractions.Models;
using NexusMods.Networking.NexusWebApi;
using NexusMods.Paths;
Expand Down Expand Up @@ -342,6 +344,9 @@ protected async Task<TemporaryPath> CreateTestFile(byte[] contents, Extension? e
protected Task<TemporaryPath> CreateTestFile(string contents, Extension? extension, Encoding? encoding = null)
=> CreateTestFile((encoding ?? Encoding.UTF8).GetBytes(contents), extension);




private AbsolutePath GetArchivePath(Hash hash)
{
if (FileStore is not NxFileStore store)
Expand Down
50 changes: 50 additions & 0 deletions tests/Games/NexusMods.Games.TestFramework/AIsolatedGameTest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.IO.Compression;
using System.Text;
using DynamicData.Kernel;
using FluentAssertions;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -17,13 +18,15 @@
using NexusMods.Abstractions.Library;
using NexusMods.Abstractions.Library.Models;
using NexusMods.Abstractions.Loadouts;
using NexusMods.Abstractions.Loadouts.Extensions;
using NexusMods.Abstractions.Loadouts.Synchronizers;
using NexusMods.Abstractions.Serialization;
using NexusMods.App.BuildInfo;
using NexusMods.DataModel;
using NexusMods.Games.FOMOD;
using NexusMods.Hashing.xxHash64;
using NexusMods.MnemonicDB.Abstractions;
using NexusMods.MnemonicDB.Abstractions.BuiltInEntities;
using NexusMods.MnemonicDB.Abstractions.Models;
using NexusMods.Networking.NexusWebApi;
using NexusMods.Paths;
Expand Down Expand Up @@ -387,6 +390,53 @@ private AbsolutePath GetArchivePath(Hash hash)
store.TryGetLocation(Connection.Db, hash, null, out var archivePath, out _).Should().BeTrue("Archive should exist");
return archivePath;
}

/// <summary>
/// Prints the disk states and the loadout states to the string builder, for verify purposes.
/// </summary>
protected void LogDiskState(StringBuilder sb, string sectionName, string comments = "", Loadout.ReadOnly[]? loadouts = null)
{
Logger.LogInformation("Logging State {SectionName}", sectionName);

var metadata = GameInstallation.GetMetadata(Connection);
sb.AppendLine($"{sectionName}:");
if (!string.IsNullOrEmpty(comments))
sb.AppendLine(comments);

Section("### Initial State", metadata.InitialDiskStateTransaction);
if (metadata.Contains(GameInstallMetadata.LastSyncedLoadoutTransaction))
Section("### Last Synced State", metadata.LastSyncedLoadoutTransaction);
Section("### Current State", metadata.LastScannedDiskStateTransaction);
if (loadouts is not null)
{
foreach (var loadout in loadouts.OrderBy(ld=> ld.ShortName))
{
if (!loadout.Items.Any())
continue;

var files = loadout.Items.OfTypeLoadoutItemWithTargetPath().OfTypeLoadoutFile()
.Where(item=> item.AsLoadoutItemWithTargetPath().AsLoadoutItem().IsEnabled()).ToArray();

sb.AppendLine($"### Loadout {loadout.ShortName} - ({files.Length})");
sb.AppendLine("| Path | Hash | Size | TxId |");
sb.AppendLine("| --- | --- | --- | --- |");
foreach (var entry in files.OrderBy(f=> f.AsLoadoutItemWithTargetPath().TargetPath))
sb.AppendLine($"| {entry.AsLoadoutItemWithTargetPath().TargetPath} | {entry.Hash} | {entry.Size} | {entry.MaxBy(x => x.T)?.T.ToString()} |");
}
}

sb.AppendLine("\n\n");

void Section(string sectionName, Transaction.ReadOnly asOf)
{
var entries = metadata.DiskStateAsOf(asOf);
sb.AppendLine($"{sectionName} - ({entries.Count}) - {TxId.From(asOf.Id.Value)}");
sb.AppendLine("| Path | Hash | Size | TxId |");
sb.AppendLine("| --- | --- | --- | --- |");
foreach (var entry in entries.OrderBy(e=> e.Path))
sb.AppendLine($"| {entry.Path} | {entry.Hash} | {entry.Size} | {entry.MaxBy(x => x.T)?.T.ToString()} |");
}
}

public async Task InitializeAsync()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## 1 - Initial State:
## 1 - Initial State:
The initial state of the game folder should contain the game files as they were created by the game store. No loadout has been created yet.
### Initial State - (1) - Tx:100000000000005
| Path | Hash | Size | TxId |
Expand Down Expand Up @@ -45,8 +45,8 @@ New files have been added to the game folder by the user or the game, but the lo
### Current State - (2) - Tx:100000000000009
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
| (EId:200000000000001, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:100000000000009 |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
### Loadout A - (1)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
Expand All @@ -63,18 +63,18 @@ After the loadout has been synchronized, the new file should be added to the loa
### Last Synced State - (2) - Tx:10000000000000B
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
| (EId:200000000000001, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:10000000000000B |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
### Current State - (2) - Tx:10000000000000B
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
| (EId:200000000000001, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:10000000000000B |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
### Loadout A - (2)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |
| (EId:200000000000005, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:10000000000000B |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |



Expand All @@ -91,8 +91,8 @@ At this point the loadout is deactivated, and all the files in the current state
### Loadout A - (2)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |
| (EId:200000000000005, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:10000000000000B |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |



Expand All @@ -109,8 +109,8 @@ A new loadout is created, but it has not been synchronized yet. So again the 'La
### Loadout A - (2)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |
| (EId:200000000000005, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:10000000000000B |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |
### Loadout B - (1)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
Expand All @@ -136,8 +136,8 @@ loadout are different from the previous loadout due to the new file only being i
### Loadout A - (2)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |
| (EId:200000000000005, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:10000000000000B |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |
### Loadout B - (1)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
Expand All @@ -154,23 +154,23 @@ A new file has been added to the game folder and B loadout has been synchronized
### Last Synced State - (2) - Tx:100000000000012
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
| (EId:200000000000001, Game, bin/newFileInGameFolderB.txt) | 0x3E6AD5D9F57F8D4E | 28 B | Tx:100000000000012 |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
### Current State - (2) - Tx:100000000000012
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
| (EId:200000000000001, Game, bin/newFileInGameFolderB.txt) | 0x3E6AD5D9F57F8D4E | 28 B | Tx:100000000000012 |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
### Loadout A - (2)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |
| (EId:200000000000005, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:10000000000000B |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |
### Loadout B - (2)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:20000000000000C, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:10000000000000E |
| (EId:20000000000000C, Game, bin/newFileInGameFolderB.txt) | 0x3E6AD5D9F57F8D4E | 28 B | Tx:100000000000012 |
| (EId:20000000000000C, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:10000000000000E |



Expand All @@ -183,23 +183,23 @@ Now we switch back to the A loadout, and the new file should be removed from the
### Last Synced State - (2) - Tx:100000000000015
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
| (EId:200000000000001, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:100000000000015 |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
### Current State - (2) - Tx:100000000000015
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
| (EId:200000000000001, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:100000000000015 |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
### Loadout A - (2)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |
| (EId:200000000000005, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:10000000000000B |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |
### Loadout B - (2)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:20000000000000C, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:10000000000000E |
| (EId:20000000000000C, Game, bin/newFileInGameFolderB.txt) | 0x3E6AD5D9F57F8D4E | 28 B | Tx:100000000000012 |
| (EId:20000000000000C, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:10000000000000E |



Expand All @@ -212,28 +212,28 @@ Loadout A has been copied to Loadout C, and the contents should match.
### Last Synced State - (2) - Tx:100000000000015
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
| (EId:200000000000001, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:100000000000015 |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
### Current State - (2) - Tx:100000000000015
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
| (EId:200000000000001, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:100000000000015 |
| (EId:200000000000001, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000005 |
### Loadout A - (2)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |
| (EId:200000000000005, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:10000000000000B |
| (EId:200000000000005, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000007 |
### Loadout B - (2)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:20000000000000C, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:10000000000000E |
| (EId:20000000000000C, Game, bin/newFileInGameFolderB.txt) | 0x3E6AD5D9F57F8D4E | 28 B | Tx:100000000000012 |
| (EId:20000000000000C, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:10000000000000E |
### Loadout C - (2)
| Path | Hash | Size | TxId |
| --- | --- | --- | --- |
| (EId:200000000000013, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000016 |
| (EId:200000000000013, Game, bin/newFileInGameFolderA.txt) | 0x2D489D43D46C8849 | 25 B | Tx:100000000000016 |
| (EId:200000000000013, Game, bin/originalGameFile.txt) | 0xA52B286A3E7F4D91 | 12 B | Tx:100000000000016 |



Expand Down
Loading

0 comments on commit 5c946ad

Please sign in to comment.