Most santiy tests pass

This commit is contained in:
Timothy Baldridge 2020-03-27 20:54:14 -06:00
parent 54a7bc36d5
commit 21189fd8e8
16 changed files with 173 additions and 152 deletions

View File

@ -100,6 +100,12 @@ namespace Wabbajack.Common
{ {
public void Serialize(ref MessagePackWriter writer, RelativePath value, MessagePackSerializerOptions options) public void Serialize(ref MessagePackWriter writer, RelativePath value, MessagePackSerializerOptions options)
{ {
if (value == default)
{
writer.WriteString(new byte[0]);
return;
}
var encoded = Encoding.UTF8.GetBytes((string)value); var encoded = Encoding.UTF8.GetBytes((string)value);
writer.WriteString(encoded); writer.WriteString(encoded);
} }

View File

@ -291,7 +291,7 @@ namespace Wabbajack.Common
{ {
if (useMove) if (useMove)
{ {
File.Move(_path, dest._path); File.Move(_path, dest._path, MoveOptions.ReplaceExisting);
} }
else else
{ {
@ -329,10 +329,10 @@ namespace Wabbajack.Common
public async Task WriteAllLinesAsync(params string[] strings) public async Task WriteAllLinesAsync(params string[] strings)
{ {
await WriteAllTextAsync(string.Join("\n",strings)); await WriteAllTextAsync(string.Join("\r\n",strings));
} }
public void WriteAllLines(string[] strings) public void WriteAllLines(params string[] strings)
{ {
WriteAllText(string.Join("\n",strings)); WriteAllText(string.Join("\n",strings));
} }
@ -551,6 +551,11 @@ namespace Wabbajack.Common
return Equals((Extension)obj); return Equals((Extension)obj);
} }
public override string ToString()
{
return _extension;
}
public override int GetHashCode() public override int GetHashCode()
{ {
return _extension != null ? _extension.GetHashCode() : 0; return _extension != null ? _extension.GetHashCode() : 0;
@ -727,6 +732,7 @@ namespace Wabbajack.Common
public static bool operator ==(FullPath a, FullPath b) public static bool operator ==(FullPath a, FullPath b)
{ {
if (a.Paths == null || b.Paths == null) return false;
if (a.Base != b.Base || a.Paths.Length != b.Paths.Length) if (a.Base != b.Base || a.Paths.Length != b.Paths.Length)
{ {
return false; return false;

View File

@ -17,6 +17,8 @@ using System.Threading.Tasks;
using Alphaleonis.Win32.Filesystem; using Alphaleonis.Win32.Filesystem;
using ICSharpCode.SharpZipLib.BZip2; using ICSharpCode.SharpZipLib.BZip2;
using IniParser; using IniParser;
using IniParser.Model.Configuration;
using IniParser.Parser;
using Newtonsoft.Json; using Newtonsoft.Json;
using ReactiveUI; using ReactiveUI;
using Wabbajack.Common.StatusFeed; using Wabbajack.Common.StatusFeed;
@ -50,13 +52,12 @@ namespace Wabbajack.Common
static Utils() static Utils()
{ {
MessagePackInit(); LogFolder = Consts.LogsFolder;
LogFile = Consts.LogFile;
Consts.LocalAppDataPath.CreateDirectory(); Consts.LocalAppDataPath.CreateDirectory();
Consts.LogsFolder.CreateDirectory(); Consts.LogsFolder.CreateDirectory();
LogFolder = Consts.LogsFolder; MessagePackInit();
LogFile = Consts.LogFile;
_startTime = DateTime.Now; _startTime = DateTime.Now;
if (LogFile.Exists) if (LogFile.Exists)
@ -65,7 +66,7 @@ namespace Wabbajack.Common
LogFile.MoveTo(newPath, true); LogFile.MoveTo(newPath, true);
} }
var logFiles = Consts.LogsFolder.EnumerateFiles(false).ToList(); var logFiles = LogFolder.EnumerateFiles(false).ToList();
if (logFiles.Count >= Consts.MaxOldLogs) if (logFiles.Count >= Consts.MaxOldLogs)
{ {
Log($"Maximum amount of old logs reached ({logFiles.Count} >= {Consts.MaxOldLogs})"); Log($"Maximum amount of old logs reached ({logFiles.Count} >= {Consts.MaxOldLogs})");
@ -156,6 +157,7 @@ namespace Wabbajack.Common
public static void LogStraightToFile(string msg) public static void LogStraightToFile(string msg)
{ {
if (LogFile == default) return;
lock (_lock) lock (_lock)
{ {
LogFile.AppendAllText($"{(DateTime.Now - _startTime).TotalSeconds:0.##} - {msg}\r\n"); LogFile.AppendAllText($"{(DateTime.Now - _startTime).TotalSeconds:0.##} - {msg}\r\n");
@ -315,6 +317,13 @@ namespace Wabbajack.Common
} }
private static IniDataParser IniParser()
{
var config = new IniParserConfiguration {AllowDuplicateKeys = true, AllowDuplicateSections = true};
var parser = new IniDataParser(config);
return parser;
}
/// <summary> /// <summary>
/// Loads INI data from the given filename and returns a dynamic type that /// Loads INI data from the given filename and returns a dynamic type that
@ -324,7 +333,7 @@ namespace Wabbajack.Common
/// <returns></returns> /// <returns></returns>
public static dynamic LoadIniFile(this AbsolutePath file) public static dynamic LoadIniFile(this AbsolutePath file)
{ {
return new DynamicIniData(new FileIniDataParser().ReadFile((string)file)); return new DynamicIniData(new FileIniDataParser(IniParser()).ReadFile((string)file));
} }
/// <summary> /// <summary>
@ -334,7 +343,7 @@ namespace Wabbajack.Common
/// <returns></returns> /// <returns></returns>
public static dynamic LoadIniString(this string file) public static dynamic LoadIniString(this string file)
{ {
return new DynamicIniData(new FileIniDataParser().ReadData(new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(file))))); return new DynamicIniData(new FileIniDataParser(IniParser()).ReadData(new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(file)))));
} }

View File

@ -93,8 +93,10 @@ namespace Wabbajack.Common
private async Task AddNewThreadsIfNeeded(int desired) private async Task AddNewThreadsIfNeeded(int desired)
{ {
var started = DateTime.Now;
using (await _lock.Wait()) using (await _lock.Wait())
{ {
var end = DateTime.Now - started;
DesiredNumWorkers = desired; DesiredNumWorkers = desired;
while (DesiredNumWorkers > _tasks.Count) while (DesiredNumWorkers > _tasks.Count)
{ {
@ -141,8 +143,10 @@ namespace Wabbajack.Common
if (DesiredNumWorkers >= _tasks.Count) continue; if (DesiredNumWorkers >= _tasks.Count) continue;
// Noticed that we may need to shut down, lock and check again // Noticed that we may need to shut down, lock and check again
var start = DateTime.Now;
using (await _lock.Wait()) using (await _lock.Wait())
{ {
var end = DateTime.Now - start;
// Check if another thread shut down before this one and got us back to the desired amount already // Check if another thread shut down before this one and got us back to the desired amount already
if (DesiredNumWorkers >= _tasks.Count) continue; if (DesiredNumWorkers >= _tasks.Count) continue;

View File

@ -206,7 +206,7 @@ namespace Wabbajack.Lib
Info("Building a list of archives based on the files required"); Info("Building a list of archives based on the files required");
var hashes = InstallDirectives.OfType<FromArchive>() var hashes = InstallDirectives.OfType<FromArchive>()
.Select(a => a.Hash) .Select(a => a.ArchiveHashPath.BaseHash)
.Distinct(); .Distinct();
var archives = IndexedArchives.OrderByDescending(f => f.File.LastModified) var archives = IndexedArchives.OrderByDescending(f => f.File.LastModified)

View File

@ -101,7 +101,7 @@ namespace Wabbajack.Lib
ModList.Directives ModList.Directives
.Select(d => OutputFolder.Combine(d.To.Parent)) .Select(d => OutputFolder.Combine(d.To.Parent))
.Distinct() .Distinct()
.Do(f => OutputFolder.CreateDirectory()); .Do(f => f.CreateDirectory());
} }
public async Task InstallArchives() public async Task InstallArchives()
@ -336,12 +336,12 @@ namespace Wabbajack.Lib
await OutputFolder.EnumerateFiles() await OutputFolder.EnumerateFiles()
.PMap(Queue, UpdateTracker, f => .PMap(Queue, UpdateTracker, f =>
{ {
var relative_to = f.RelativeTo(OutputFolder); var relativeTo = f.RelativeTo(OutputFolder);
Utils.Status($"Checking if ModList file {relative_to}"); Utils.Status($"Checking if ModList file {relativeTo}");
if (indexed.ContainsKey(relative_to) || f.InFolder(DownloadFolder)) if (indexed.ContainsKey(relativeTo) || f.InFolder(DownloadFolder))
return; return;
Utils.Log($"Deleting {relative_to} it's not part of this ModList"); Utils.Log($"Deleting {relativeTo} it's not part of this ModList");
f.Delete(); f.Delete();
}); });
@ -350,6 +350,7 @@ namespace Wabbajack.Lib
.Select(f => f.RelativeTo(OutputFolder)) .Select(f => f.RelativeTo(OutputFolder))
// We ignore the last part of the path, so we need a dummy file name // We ignore the last part of the path, so we need a dummy file name
.Append(DownloadFolder.Combine("_")) .Append(DownloadFolder.Combine("_"))
.Where(f => f.InFolder(OutputFolder))
.SelectMany(path => .SelectMany(path =>
{ {
// Get all the folders and all the folder parents // Get all the folders and all the folder parents

View File

@ -27,7 +27,8 @@ namespace Wabbajack.Lib.CompilationSteps
public override async ValueTask<Directive> Run(RawSourceFile source) public override async ValueTask<Directive> Run(RawSourceFile source)
{ {
if (!_allEnabledMods.Any(mod => source.AbsolutePath.InFolder(mod))) if (!source.AbsolutePath.InFolder(_mo2Compiler.MO2ModsFolder)) return null;
if (_allEnabledMods.Any(mod => source.AbsolutePath.InFolder(mod)))
return null; return null;
var r = source.EvolveTo<IgnoredDirectly>(); var r = source.EvolveTo<IgnoredDirectly>();
r.Reason = "Disabled Mod"; r.Reason = "Disabled Mod";

View File

@ -140,6 +140,7 @@ namespace Wabbajack.Lib
[Union(4, typeof(InlineFile))] [Union(4, typeof(InlineFile))]
[Union(5, typeof(PatchedFromArchive))] [Union(5, typeof(PatchedFromArchive))]
[Union(6, typeof(RemappedInlineFile))] [Union(6, typeof(RemappedInlineFile))]
[Union(7, typeof(CleanedESM))]
public abstract class Directive public abstract class Directive
{ {
[Key(0)] [Key(0)]
@ -185,13 +186,17 @@ namespace Wabbajack.Lib
/// <summary> /// <summary>
/// File meant to be extracted before the installation /// File meant to be extracted before the installation
/// </summary> /// </summary>
[MessagePackObject]
public class PropertyFile : InlineFile public class PropertyFile : InlineFile
{ {
[Key(4)]
public PropertyType Type; public PropertyType Type;
} }
[MessagePackObject]
public class CleanedESM : InlineFile public class CleanedESM : InlineFile
{ {
[Key(4)]
public Hash SourceESMHash; public Hash SourceESMHash;
} }

View File

@ -66,7 +66,7 @@ namespace Wabbajack.Lib
{ {
get get
{ {
if (_mo2DownloadsFolder != null) return _mo2DownloadsFolder; if (_mo2DownloadsFolder != default) return _mo2DownloadsFolder;
if (MO2Ini != null) if (MO2Ini != null)
if (MO2Ini.Settings != null) if (MO2Ini.Settings != null)
if (MO2Ini.Settings.download_directory != null) if (MO2Ini.Settings.download_directory != null)
@ -105,7 +105,7 @@ namespace Wabbajack.Lib
if (cancel.IsCancellationRequested) return false; if (cancel.IsCancellationRequested) return false;
await VFS.IntegrateFromFile(VFSCacheName); await VFS.IntegrateFromFile(VFSCacheName);
var roots = new List<AbsolutePath>() var roots = new List<AbsolutePath>
{ {
MO2Folder, GamePath, MO2DownloadsFolder MO2Folder, GamePath, MO2DownloadsFolder
}; };
@ -312,7 +312,7 @@ namespace Wabbajack.Lib
Author = ModListAuthor ?? "", Author = ModListAuthor ?? "",
Description = ModListDescription ?? "", Description = ModListDescription ?? "",
Readme = (string)ModListReadme, Readme = (string)ModListReadme,
Image = ModListImage.FileName, Image = ModListImage != default ? ModListImage.FileName : default,
Website = ModListWebsite != null ? new Uri(ModListWebsite) : null Website = ModListWebsite != null ? new Uri(ModListWebsite) : null
}; };
@ -362,7 +362,7 @@ namespace Wabbajack.Lib
async Task<bool> HasInvalidMeta(AbsolutePath filename) async Task<bool> HasInvalidMeta(AbsolutePath filename)
{ {
var metaname = filename.WithExtension(Consts.MetaFileExtension); var metaname = filename.WithExtension(Consts.MetaFileExtension);
if (metaname.Exists) return true; if (!metaname.Exists) return true;
return await DownloadDispatcher.ResolveArchive(metaname.LoadIniFile()) == null; return await DownloadDispatcher.ResolveArchive(metaname.LoadIniFile()) == null;
} }
@ -443,7 +443,7 @@ namespace Wabbajack.Lib
}); });
var groups = InstallDirectives.OfType<PatchedFromArchive>() var groups = InstallDirectives.OfType<PatchedFromArchive>()
.Where(p => p.PatchID == null) .Where(p => p.PatchID == default)
.GroupBy(p => p.ArchiveHashPath.BaseHash) .GroupBy(p => p.ArchiveHashPath.BaseHash)
.ToList(); .ToList();

View File

@ -330,7 +330,7 @@ namespace Wabbajack.Lib
{ {
var config = new IniParserConfiguration {AllowDuplicateKeys = true, AllowDuplicateSections = true}; var config = new IniParserConfiguration {AllowDuplicateKeys = true, AllowDuplicateSections = true};
foreach (var file in OutputFolder.Combine("profiles").EnumerateFiles() foreach (var file in OutputFolder.Combine("profiles").EnumerateFiles()
.Where(f => ((string)f.FileName).EndsWith("*refs.ini"))) .Where(f => ((string)f.FileName).EndsWith("refs.ini")))
{ {
try try
{ {

View File

@ -13,15 +13,17 @@ namespace Wabbajack.Test
public ITestOutputHelper TestContext { get; set; } public ITestOutputHelper TestContext { get; set; }
protected TestUtils utils { get; set; } protected TestUtils utils { get; set; }
public ACompilerTest() public ACompilerTest(ITestOutputHelper helper)
{ {
TestContext = helper;
Helpers.Init(); Helpers.Init();
Consts.TestMode = true; Consts.TestMode = true;
utils = new TestUtils(); utils = new TestUtils();
utils.Game = Game.SkyrimSpecialEdition; utils.Game = Game.SkyrimSpecialEdition;
Utils.LogMessages.Subscribe(f => TestContext.WriteLine(f.ShortDescription)); DateTime startTime = DateTime.Now;
Utils.LogMessages.Subscribe(f => TestContext.WriteLine($"{DateTime.Now - startTime} - {f.ShortDescription}"));
} }
@ -43,6 +45,7 @@ namespace Wabbajack.Test
protected async Task<ModList> CompileAndInstall(string profile) protected async Task<ModList> CompileAndInstall(string profile)
{ {
var compiler = await ConfigureAndRunCompiler(profile); var compiler = await ConfigureAndRunCompiler(profile);
Utils.Log("Finished Compiling");
await Install(compiler); await Install(compiler);
return compiler.ModList; return compiler.ModList;
} }
@ -66,7 +69,7 @@ namespace Wabbajack.Test
await installer.Begin(); await installer.Begin();
} }
private SystemParameters CreateDummySystemParameters() protected SystemParameters CreateDummySystemParameters()
{ {
return new SystemParameters return new SystemParameters
{ {

View File

@ -1,92 +1,96 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Compression.BSA;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Wabbajack.Common; using Wabbajack.Common;
using Wabbajack.Lib; using Wabbajack.Lib;
using Wabbajack.Lib.CompilationSteps.CompilationErrors; using Wabbajack.Lib.CompilationSteps.CompilationErrors;
using Xunit;
using Xunit.Abstractions;
using File = Alphaleonis.Win32.Filesystem.File; using File = Alphaleonis.Win32.Filesystem.File;
using Path = Alphaleonis.Win32.Filesystem.Path; using Path = Alphaleonis.Win32.Filesystem.Path;
namespace Wabbajack.Test namespace Wabbajack.Test
{ {
[TestClass]
public class SanityTests : ACompilerTest public class SanityTests : ACompilerTest
{ {
[TestMethod]
public SanityTests(ITestOutputHelper helper) : base(helper)
{
}
[Fact]
public async Task TestDirectMatch() public async Task TestDirectMatch()
{ {
var profile = utils.AddProfile(); var profile = utils.AddProfile();
var mod = utils.AddMod(); var mod = utils.AddMod();
var test_pex = utils.AddModFile(mod, @"Data\scripts\test.pex", 10); var testPex = utils.AddModFile(mod, @"Data\scripts\test.pex", 10);
utils.Configure(); await utils.Configure();
utils.AddManualDownload( utils.AddManualDownload(
new Dictionary<string, byte[]> {{"/baz/biz.pex", File.ReadAllBytes(test_pex)}}); new Dictionary<string, byte[]> {{"/baz/biz.pex", await testPex.ReadAllBytesAsync()}});
await CompileAndInstall(profile); await CompileAndInstall(profile);
utils.VerifyInstalledFile(mod, @"Data\scripts\test.pex"); utils.VerifyInstalledFile(mod, @"Data\scripts\test.pex");
} }
[TestMethod] [Fact]
public async Task TestDirectMatchFromGameFolder() public async Task TestDirectMatchFromGameFolder()
{ {
var profile = utils.AddProfile(); var profile = utils.AddProfile();
var mod = utils.AddMod(); var mod = utils.AddMod();
var test_pex = utils.AddGameFile(@"enbstuff\test.pex", 10); var testPex = utils.AddGameFile(@"enbstuff\test.pex", 10);
utils.Configure(); await utils.Configure();
utils.AddManualDownload( utils.AddManualDownload(
new Dictionary<string, byte[]> {{"/baz/biz.pex", File.ReadAllBytes(test_pex)}}); new Dictionary<string, byte[]> {{"/baz/biz.pex", await testPex.ReadAllBytesAsync()}});
await CompileAndInstall(profile); await CompileAndInstall(profile);
utils.VerifyInstalledGameFile(@"enbstuff\test.pex"); utils.VerifyInstalledGameFile(@"enbstuff\test.pex");
} }
[TestMethod] [Fact]
public async Task TestDirectMatchIsIgnoredWhenGameFolderFilesOverrideExists() public async Task TestDirectMatchIsIgnoredWhenGameFolderFilesOverrideExists()
{ {
var profile = utils.AddProfile(); var profile = utils.AddProfile();
var mod = utils.AddMod(); var mod = utils.AddMod();
var test_pex = utils.AddGameFile(@"enbstuff\test.pex", 10); var testPex = utils.AddGameFile(@"enbstuff\test.pex", 10);
utils.Configure(); await utils.Configure();
Directory.CreateDirectory(Path.Combine(utils.MO2Folder, Consts.GameFolderFilesDir)); utils.MO2Folder.Combine(Consts.GameFolderFilesDir).CreateDirectory();
utils.AddManualDownload( utils.AddManualDownload(
new Dictionary<string, byte[]> {{"/baz/biz.pex", File.ReadAllBytes(test_pex)}}); new Dictionary<string, byte[]> {{"/baz/biz.pex", await testPex.ReadAllBytesAsync()}});
await CompileAndInstall(profile); await CompileAndInstall(profile);
Assert.IsFalse(File.Exists(Path.Combine(utils.InstallFolder, Consts.GameFolderFilesDir, @"enbstuff\test.pex"))); Assert.False(utils.InstallFolder.Combine(Consts.GameFolderFilesDir, (RelativePath)@"enbstuff\test.pex").IsFile);
} }
[TestMethod] [Fact]
public async Task TestDuplicateFilesAreCopied() public async Task TestDuplicateFilesAreCopied()
{ {
var profile = utils.AddProfile(); var profile = utils.AddProfile();
var mod = utils.AddMod(); var mod = utils.AddMod();
var test_pex = utils.AddModFile(mod, @"Data\scripts\test.pex", 10); var testPex = utils.AddModFile(mod, @"Data\scripts\test.pex", 10);
// Make a copy to make sure it gets picked up and moved around. // Make a copy to make sure it gets picked up and moved around.
File.Copy(test_pex, test_pex + ".copy"); testPex.CopyTo(testPex.WithExtension(new Extension(".copy")));
utils.Configure(); await utils.Configure();
utils.AddManualDownload( utils.AddManualDownload(
new Dictionary<string, byte[]> { { "/baz/biz.pex", File.ReadAllBytes(test_pex) } }); new Dictionary<string, byte[]> { { "/baz/biz.pex", await testPex.ReadAllBytesAsync() } });
await CompileAndInstall(profile); await CompileAndInstall(profile);
@ -94,7 +98,7 @@ namespace Wabbajack.Test
utils.VerifyInstalledFile(mod, @"Data\scripts\test.pex.copy"); utils.VerifyInstalledFile(mod, @"Data\scripts\test.pex.copy");
} }
[TestMethod] [Fact]
public async Task TestUpdating() public async Task TestUpdating()
{ {
@ -104,14 +108,14 @@ namespace Wabbajack.Test
var deleted = utils.AddModFile(mod, @"Data\scripts\deleted.pex", 10); var deleted = utils.AddModFile(mod, @"Data\scripts\deleted.pex", 10);
var modified = utils.AddModFile(mod, @"Data\scripts\modified.pex", 10); var modified = utils.AddModFile(mod, @"Data\scripts\modified.pex", 10);
utils.Configure(); await utils.Configure();
utils.AddManualDownload( utils.AddManualDownload(
new Dictionary<string, byte[]> new Dictionary<string, byte[]>
{ {
{ "/baz/unchanged.pex", File.ReadAllBytes(unchanged) }, { "/baz/unchanged.pex", await unchanged.ReadAllBytesAsync() },
{ "/baz/deleted.pex", File.ReadAllBytes(deleted) }, { "/baz/deleted.pex", await deleted.ReadAllBytesAsync() },
{ "/baz/modified.pex", File.ReadAllBytes(modified) }, { "/baz/modified.pex", await modified.ReadAllBytesAsync() },
}); });
await CompileAndInstall(profile); await CompileAndInstall(profile);
@ -120,26 +124,27 @@ namespace Wabbajack.Test
utils.VerifyInstalledFile(mod, @"Data\scripts\deleted.pex"); utils.VerifyInstalledFile(mod, @"Data\scripts\deleted.pex");
utils.VerifyInstalledFile(mod, @"Data\scripts\modified.pex"); utils.VerifyInstalledFile(mod, @"Data\scripts\modified.pex");
var unchanged_path = utils.PathOfInstalledFile(mod, @"Data\scripts\unchanged.pex"); var unchangedPath = utils.PathOfInstalledFile(mod, @"Data\scripts\unchanged.pex");
var deleted_path = utils.PathOfInstalledFile(mod, @"Data\scripts\deleted.pex"); var deletedPath = utils.PathOfInstalledFile(mod, @"Data\scripts\deleted.pex");
var modified_path = utils.PathOfInstalledFile(mod, @"Data\scripts\modified.pex"); var modifiedPath = utils.PathOfInstalledFile(mod, @"Data\scripts\modified.pex");
var extra_path = utils.PathOfInstalledFile(mod, @"something_i_made.foo"); var extraPath = utils.PathOfInstalledFile(mod, @"something_i_made.foo");
File.WriteAllText(extra_path, "bleh"); await extraPath.WriteAllTextAsync("bleh");
var extra_folder = Path.Combine(Path.GetDirectoryName(utils.PathOfInstalledFile(mod, @"something_i_made.foo")), "folder_i_made"); var extraFolder = utils.PathOfInstalledFile(mod, @"something_i_made.foo").Parent.Combine("folder_i_made");
Directory.CreateDirectory(extra_folder); extraFolder.CreateDirectory();
Assert.IsTrue(Directory.Exists(extra_folder)); Assert.True(extraFolder.IsDirectory);
var unchanged_modified = File.GetLastWriteTime(unchanged_path); var unchangedModified = unchangedPath.LastModified;
var modified_modified = File.GetLastWriteTime(modified_path);
File.WriteAllText(modified_path, "random data"); await modifiedPath.WriteAllTextAsync("random data");
File.Delete(deleted_path); var modifiedModified = modifiedPath.LastModified;
Assert.IsTrue(File.Exists(extra_path)); deletedPath.Delete();
Assert.True(extraPath.Exists);
await CompileAndInstall(profile); await CompileAndInstall(profile);
@ -147,24 +152,24 @@ namespace Wabbajack.Test
utils.VerifyInstalledFile(mod, @"Data\scripts\deleted.pex"); utils.VerifyInstalledFile(mod, @"Data\scripts\deleted.pex");
utils.VerifyInstalledFile(mod, @"Data\scripts\modified.pex"); utils.VerifyInstalledFile(mod, @"Data\scripts\modified.pex");
Assert.AreEqual(unchanged_modified, File.GetLastWriteTime(unchanged_path)); Assert.Equal(unchangedModified, unchangedPath.LastModified);
Assert.AreNotEqual(modified_modified, File.GetLastWriteTime(modified_path)); Assert.NotEqual(modifiedModified, modifiedPath.LastModified);
Assert.IsFalse(File.Exists(extra_path)); Assert.False(extraPath.Exists);
Assert.IsFalse(Directory.Exists(extra_folder)); Assert.False(extraFolder.Exists);
} }
[TestMethod] [Fact]
public async Task CleanedESMTest() public async Task CleanedESMTest()
{ {
var profile = utils.AddProfile(); var profile = utils.AddProfile();
var mod = utils.AddMod("Cleaned ESMs"); var mod = utils.AddMod("Cleaned ESMs");
var update_esm = utils.AddModFile(mod, @"Update.esm", 10); var updateEsm = utils.AddModFile(mod, @"Update.esm", 10);
utils.Configure(); await utils.Configure();
var game_file = Path.Combine(utils.GameFolder, "Data", "Update.esm"); var gameFile = utils.GameFolder.Combine("Data", "Update.esm");
utils.GenerateRandomFileData(game_file, 20); utils.GenerateRandomFileData(gameFile, 20);
var modlist = await CompileAndInstall(profile); var modlist = await CompileAndInstall(profile);
@ -173,65 +178,62 @@ namespace Wabbajack.Test
var compiler = await ConfigureAndRunCompiler(profile); var compiler = await ConfigureAndRunCompiler(profile);
// Update the file and verify that it throws an error. // Update the file and verify that it throws an error.
utils.GenerateRandomFileData(game_file, 20); utils.GenerateRandomFileData(gameFile, 20);
var exception = await Assert.ThrowsExceptionAsync<InvalidGameESMError>(async () => await Install(compiler)); var exception = await Assert.ThrowsAsync<InvalidGameESMError>(async () => await Install(compiler));
Assert.IsInstanceOfType(exception, typeof(InvalidGameESMError)); Assert.IsAssignableFrom<InvalidGameESMError>(exception);
} }
[TestMethod] [Fact]
public async Task SetScreenSizeTest() public async Task SetScreenSizeTest()
{ {
var profile = utils.AddProfile(); var profile = utils.AddProfile();
var mod = utils.AddMod("dummy"); var mod = utils.AddMod("dummy");
utils.Configure(); await utils.Configure();
File.WriteAllLines(Path.Combine(utils.MO2Folder, "profiles", profile, "somegameprefs.ini"), await utils.MO2Folder.Combine("profiles", profile, "somegameprefs.ini").WriteAllLinesAsync(
new List<string>
{
// Beth inis are messy, let's make ours just as messy to catch some parse failures // Beth inis are messy, let's make ours just as messy to catch some parse failures
"[Display]", "[Display]",
"foo=4", "foo=4",
"[Display]", "[Display]",
"STestFile=f", "STestFile=f",
"STestFile=", "STestFile=",
"iSize H=3",
"iSize W=-200",
"[Display]", "[Display]",
"foo=4", "foo=4",
"iSize H=50",
"iSize W=100",
"[MEMORY]", "[MEMORY]",
"VideoMemorySizeMb=22" "VideoMemorySizeMb=22");
});
var modlist = await CompileAndInstall(profile); var modlist = await CompileAndInstall(profile);
var ini = Path.Combine(utils.InstallFolder, "profiles", profile, "somegameprefs.ini").LoadIniFile(); var ini = utils.InstallFolder.Combine("profiles", profile, "somegameprefs.ini").LoadIniFile();
var sysinfo = SystemParametersConstructor.Create(); var sysinfo = CreateDummySystemParameters();
Assert.AreEqual(System.Windows.SystemParameters.PrimaryScreenHeight.ToString(), ini?.Display?["iSize H"]); Assert.Equal(sysinfo.ScreenHeight.ToString(), ini?.Display?["iSize H"]);
Assert.AreEqual(System.Windows.SystemParameters.PrimaryScreenWidth.ToString(), ini?.Display?["iSize W"]); Assert.Equal(sysinfo.ScreenWidth.ToString(), ini?.Display?["iSize W"]);
Assert.AreEqual(sysinfo.EnbLEVRAMSize.ToString(), ini?.MEMORY?["VideoMemorySizeMb"]); Assert.Equal(sysinfo.EnbLEVRAMSize.ToString(), ini?.MEMORY?["VideoMemorySizeMb"]);
} }
[TestMethod] [Fact]
public async Task UnmodifiedInlinedFilesArePulledFromArchives() public async Task UnmodifiedInlinedFilesArePulledFromArchives()
{ {
var profile = utils.AddProfile(); var profile = utils.AddProfile();
var mod = utils.AddMod(); var mod = utils.AddMod();
var ini = utils.AddModFile(mod, @"foo.ini", 10); var ini = utils.AddModFile(mod, @"foo.ini", 10);
utils.Configure(); await utils.Configure();
utils.AddManualDownload( utils.AddManualDownload(
new Dictionary<string, byte[]> { { "/baz/biz.pex", File.ReadAllBytes(ini) } }); new Dictionary<string, byte[]> { { "/baz/biz.pex", await ini.ReadAllBytesAsync() } });
var modlist = await CompileAndInstall(profile); var modlist = await CompileAndInstall(profile);
var directive = modlist.Directives.Where(m => m.To == $"mods\\{mod}\\foo.ini").FirstOrDefault(); var directive = modlist.Directives.FirstOrDefault(m => m.To == (RelativePath)$"mods\\{mod}\\foo.ini");
Assert.IsNotNull(directive); Assert.NotNull(directive);
Assert.IsInstanceOfType(directive, typeof(FromArchive)); Assert.IsAssignableFrom<FromArchive>(directive);
} }
[TestMethod] [Fact]
public async Task ModifiedIniFilesArePatchedAgainstFileWithSameName() public async Task ModifiedIniFilesArePatchedAgainstFileWithSameName()
{ {
var profile = utils.AddProfile(); var profile = utils.AddProfile();
@ -239,26 +241,25 @@ namespace Wabbajack.Test
var ini = utils.AddModFile(mod, @"foo.ini", 10); var ini = utils.AddModFile(mod, @"foo.ini", 10);
var meta = utils.AddModFile(mod, "meta.ini"); var meta = utils.AddModFile(mod, "meta.ini");
utils.Configure(); await utils.Configure();
var archive = utils.AddManualDownload( var archive = utils.AddManualDownload(
new Dictionary<string, byte[]> { { "/baz/foo.ini", File.ReadAllBytes(ini) } }); new Dictionary<string, byte[]> { { "/baz/foo.ini", await ini.ReadAllBytesAsync() } });
File.WriteAllLines(meta, new[] await meta.WriteAllLinesAsync(
{
"[General]", "[General]",
$"installationFile={archive}", $"installationFile={archive}");
});
// Modify after creating mod archive in the downloads folder // Modify after creating mod archive in the downloads folder
File.WriteAllText(ini, "Wabbajack, Wabbajack, Wabbajack!"); await ini.WriteAllTextAsync("Wabbajack, Wabbajack, Wabbajack!");
var modlist = await CompileAndInstall(profile); var modlist = await CompileAndInstall(profile);
var directive = modlist.Directives.Where(m => m.To == $"mods\\{mod}\\foo.ini").FirstOrDefault(); var directive = modlist.Directives.FirstOrDefault(m => m.To == (RelativePath)$"mods\\{mod}\\foo.ini");
Assert.IsNotNull(directive); Assert.NotNull(directive);
Assert.IsInstanceOfType(directive, typeof(PatchedFromArchive)); Assert.IsAssignableFrom<PatchedFromArchive>(directive);
} }
} }
} }

View File

@ -44,13 +44,11 @@ namespace Wabbajack.Test
public async Task Configure() public async Task Configure()
{ {
await MO2Folder.Combine("ModOrganizer.ini").WriteAllLinesAsync(new [] await MO2Folder.Combine("ModOrganizer.ini").WriteAllLinesAsync(
{
"[General]", "[General]",
$"gameName={Game.MetaData().MO2Name}", $"gameName={Game.MetaData().MO2Name}",
$"gamePath={((string)GameFolder).Replace("\\", "\\\\")}", $"gamePath={((string)GameFolder).Replace("\\", "\\\\")}",
$"download_directory={DownloadsFolder}" $"download_directory={DownloadsFolder}");
});
DownloadsFolder.CreateDirectory(); DownloadsFolder.CreateDirectory();
GameFolder.Combine("Data").CreateDirectory(); GameFolder.Combine("Data").CreateDirectory();
@ -157,12 +155,9 @@ namespace Wabbajack.Test
}); });
DownloadsFolder.Combine(name + Consts.MetaFileExtension).WriteAllLines( DownloadsFolder.Combine(name + Consts.MetaFileExtension).WriteAllLines(
new string[]
{
"[General]", "[General]",
"manualURL=<TESTING>" "manualURL=<TESTING>"
}); );
return name; return name;
} }
@ -173,7 +168,7 @@ namespace Wabbajack.Test
Assert.True(src.Exists); Assert.True(src.Exists);
var dest = InstallFolder.Combine((string)Consts.MO2ModFolderName, mod, file); var dest = InstallFolder.Combine((string)Consts.MO2ModFolderName, mod, file);
Assert.True(src.Exists); Assert.True(dest.Exists, $"Destination {dest} doesn't exist");
var srcData = src.ReadAllBytes(); var srcData = src.ReadAllBytes();
var destData = dest.ReadAllBytes(); var destData = dest.ReadAllBytes();

View File

@ -20,8 +20,6 @@
<None Include="Extensions.cs" /> <None Include="Extensions.cs" />
<Compile Remove="RestartingDownloadsTests.cs" /> <Compile Remove="RestartingDownloadsTests.cs" />
<None Include="RestartingDownloadsTests.cs" /> <None Include="RestartingDownloadsTests.cs" />
<Compile Remove="SanityTests.cs" />
<None Include="SanityTests.cs" />
<Compile Remove="SimpleHTTPServer.cs" /> <Compile Remove="SimpleHTTPServer.cs" />
<None Include="SimpleHTTPServer.cs" /> <None Include="SimpleHTTPServer.cs" />
<Compile Remove="VortexTests.cs" /> <Compile Remove="VortexTests.cs" />

View File

@ -243,21 +243,15 @@ namespace Wabbajack.VirtualFileSystem
public async Task BackfillMissing() public async Task BackfillMissing()
{ {
var newFiles = _knownFiles.Where(f => f.Paths.Length == 0) var newFiles = _knownArchives.ToDictionary(kv => kv.Key,
.GroupBy(f => f.BaseHash) kv => new VirtualFile {Name = kv.Value, Size = kv.Value.Size, Hash = kv.Key});
.ToDictionary(f => f.Key, s => new VirtualFile()
{
Name = s.First().Paths[0],
Hash = s.First().BaseHash,
Context = this
});
var parentchild = new Dictionary<(VirtualFile, RelativePath), VirtualFile>(); var parentchild = new Dictionary<(VirtualFile, RelativePath), VirtualFile>();
void BackFillOne(HashRelativePath file) void BackFillOne(HashRelativePath file)
{ {
var parent = newFiles[file.BaseHash]; var parent = newFiles[file.BaseHash];
foreach (var path in file.Paths.Skip(1)) foreach (var path in file.Paths)
{ {
if (parentchild.TryGetValue((parent, path), out var foundParent)) if (parentchild.TryGetValue((parent, path), out var foundParent))
{ {
@ -271,7 +265,7 @@ namespace Wabbajack.VirtualFileSystem
parent = nf; parent = nf;
} }
} }
_knownFiles.Where(f => f.Paths.Length > 1).Do(BackFillOne); _knownFiles.Where(f => f.Paths.Length > 0).Do(BackFillOne);
var newIndex = await Index.Integrate(newFiles.Values.ToList()); var newIndex = await Index.Integrate(newFiles.Values.ToList());

View File

@ -38,7 +38,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wabbajack.CLI", "Wabbajack.
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wabbajack.Launcher", "Wabbajack.Launcher\Wabbajack.Launcher.csproj", "{D6856DBF-C959-4867-A8A8-343DA2D2715E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wabbajack.Launcher", "Wabbajack.Launcher\Wabbajack.Launcher.csproj", "{D6856DBF-C959-4867-A8A8-343DA2D2715E}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Common.Test", "Wabbajack.Common.Test\Wabbajack.Common.Test.csproj", "{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wabbajack.Common.Test", "Wabbajack.Common.Test\Wabbajack.Common.Test.csproj", "{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -124,14 +124,12 @@ Global
{D6856DBF-C959-4867-A8A8-343DA2D2715E}.Release|Any CPU.Build.0 = Release|Any CPU {D6856DBF-C959-4867-A8A8-343DA2D2715E}.Release|Any CPU.Build.0 = Release|Any CPU
{D6856DBF-C959-4867-A8A8-343DA2D2715E}.Release|x64.ActiveCfg = Release|Any CPU {D6856DBF-C959-4867-A8A8-343DA2D2715E}.Release|x64.ActiveCfg = Release|Any CPU
{D6856DBF-C959-4867-A8A8-343DA2D2715E}.Release|x64.Build.0 = Release|Any CPU {D6856DBF-C959-4867-A8A8-343DA2D2715E}.Release|x64.Build.0 = Release|Any CPU
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Debug|Any CPU.ActiveCfg = Debug|x64
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Release|Any CPU.Build.0 = Release|Any CPU
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Release|x64.ActiveCfg = Release|Any CPU
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Release|x64.Build.0 = Release|Any CPU
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Debug|x64.ActiveCfg = Debug|x64 {BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Debug|x64.ActiveCfg = Debug|x64
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Debug|x64.Build.0 = Debug|x64 {BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Debug|x64.Build.0 = Debug|x64
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Release|Any CPU.ActiveCfg = Release|x64
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Release|x64.ActiveCfg = Release|x64
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE