wabbajack/Wabbajack.Test/SanityTests.cs

524 lines
19 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.IO;
2019-09-26 23:08:10 +00:00
using System.Linq;
2019-12-07 02:54:27 +00:00
using System.Threading.Tasks;
2020-04-22 20:58:50 +00:00
using Compression.BSA;
using Wabbajack.Common;
using Wabbajack.Lib;
2019-12-06 00:05:26 +00:00
using Wabbajack.Lib.CompilationSteps.CompilationErrors;
2020-03-28 02:54:14 +00:00
using Xunit;
using Xunit.Abstractions;
using File = Alphaleonis.Win32.Filesystem.File;
using Path = Alphaleonis.Win32.Filesystem.Path;
2019-09-24 04:20:24 +00:00
namespace Wabbajack.Test
{
public class SanityTests : ACompilerTest
2019-09-24 04:20:24 +00:00
{
2020-03-28 02:54:14 +00:00
public SanityTests(ITestOutputHelper helper) : base(helper)
{
}
[Fact]
public async Task TestDirectMatch()
2019-09-24 04:20:24 +00:00
{
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var testPex = await utils.AddModFile(mod, @"Data\scripts\test.pex", 10);
2019-09-26 22:32:15 +00:00
2020-03-28 02:54:14 +00:00
await utils.Configure();
2019-09-24 04:20:24 +00:00
await utils.AddManualDownload(
2020-03-28 02:54:14 +00:00
new Dictionary<string, byte[]> {{"/baz/biz.pex", await testPex.ReadAllBytesAsync()}});
2019-09-24 04:20:24 +00:00
2019-12-07 02:54:27 +00:00
await CompileAndInstall(profile);
2019-09-24 04:20:24 +00:00
await utils.VerifyInstalledFile(mod, @"Data\scripts\test.pex");
2019-09-26 22:32:15 +00:00
}
2020-01-07 00:24:33 +00:00
[Fact]
public async Task ExtraFilesInDownloadFolderDontStopCompilation()
{
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var testPex = await utils.AddModFile(mod, @"Data\scripts\test.pex", 10);
await utils.Configure();
await utils.AddManualDownload(
new Dictionary<string, byte[]> {{"/baz/biz.pex", await testPex.ReadAllBytesAsync()}});
await utils.DownloadsFolder.Combine("some_other_file.7z").WriteAllTextAsync("random data");
await CompileAndInstall(profile);
await utils.VerifyInstalledFile(mod, @"Data\scripts\test.pex");
}
2020-03-28 02:54:14 +00:00
[Fact]
2020-01-07 00:24:33 +00:00
public async Task TestDirectMatchFromGameFolder()
{
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var testPex = await utils.AddGameFile(@"enbstuff\test.pex", 10);
2020-01-07 00:24:33 +00:00
2020-03-28 02:54:14 +00:00
await utils.Configure();
2020-01-07 00:24:33 +00:00
await utils.AddManualDownload(
2020-03-28 02:54:14 +00:00
new Dictionary<string, byte[]> {{"/baz/biz.pex", await testPex.ReadAllBytesAsync()}});
2020-01-07 00:24:33 +00:00
await CompileAndInstall(profile);
await utils.VerifyInstalledGameFile(@"enbstuff\test.pex");
2020-01-07 00:24:33 +00:00
}
2020-03-28 02:54:14 +00:00
[Fact]
2020-01-07 00:24:33 +00:00
public async Task TestDirectMatchIsIgnoredWhenGameFolderFilesOverrideExists()
{
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var testPex = await utils.AddGameFile(@"enbstuff\test.pex", 10);
2020-01-07 00:24:33 +00:00
2020-03-28 02:54:14 +00:00
await utils.Configure();
2020-01-07 00:24:33 +00:00
2020-03-28 02:54:14 +00:00
utils.MO2Folder.Combine(Consts.GameFolderFilesDir).CreateDirectory();
2020-01-07 00:24:33 +00:00
await utils.AddManualDownload(
2020-03-28 02:54:14 +00:00
new Dictionary<string, byte[]> {{"/baz/biz.pex", await testPex.ReadAllBytesAsync()}});
2020-01-07 00:24:33 +00:00
await CompileAndInstall(profile);
2020-03-28 02:54:14 +00:00
Assert.False(utils.InstallFolder.Combine(Consts.GameFolderFilesDir, (RelativePath)@"enbstuff\test.pex").IsFile);
2020-01-07 00:24:33 +00:00
}
2019-09-26 22:32:15 +00:00
2020-03-28 02:54:14 +00:00
[Fact]
2019-12-07 02:54:27 +00:00
public async Task TestDuplicateFilesAreCopied()
{
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var testPex = await utils.AddModFile(mod, @"Data\scripts\test.pex", 10);
// Make a copy to make sure it gets picked up and moved around.
await testPex.CopyToAsync(testPex.WithExtension(new Extension(".copy")));
2020-03-28 02:54:14 +00:00
await utils.Configure();
await utils.AddManualDownload(
2020-03-28 02:54:14 +00:00
new Dictionary<string, byte[]> { { "/baz/biz.pex", await testPex.ReadAllBytesAsync() } });
2019-12-07 02:54:27 +00:00
await CompileAndInstall(profile);
await utils.VerifyInstalledFile(mod, @"Data\scripts\test.pex");
await utils.VerifyInstalledFile(mod, @"Data\scripts\test.pex.copy");
}
2020-03-28 02:54:14 +00:00
[Fact]
2019-12-07 02:54:27 +00:00
public async Task TestUpdating()
{
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var unchanged = await utils.AddModFile(mod, @"Data\scripts\unchanged.pex", 10);
var deleted = await utils.AddModFile(mod, @"Data\scripts\deleted.pex", 10);
var modified = await utils.AddModFile(mod, @"Data\scripts\modified.pex", 10);
2020-03-28 02:54:14 +00:00
await utils.Configure();
await utils.AddManualDownload(
new Dictionary<string, byte[]>
{
2020-03-28 02:54:14 +00:00
{ "/baz/unchanged.pex", await unchanged.ReadAllBytesAsync() },
{ "/baz/deleted.pex", await deleted.ReadAllBytesAsync() },
{ "/baz/modified.pex", await modified.ReadAllBytesAsync() },
});
2019-12-07 02:54:27 +00:00
await CompileAndInstall(profile);
await utils.VerifyInstalledFile(mod, @"Data\scripts\unchanged.pex");
await utils.VerifyInstalledFile(mod, @"Data\scripts\deleted.pex");
await utils.VerifyInstalledFile(mod, @"Data\scripts\modified.pex");
2020-03-28 02:54:14 +00:00
var unchangedPath = utils.PathOfInstalledFile(mod, @"Data\scripts\unchanged.pex");
var deletedPath = utils.PathOfInstalledFile(mod, @"Data\scripts\deleted.pex");
var modifiedPath = utils.PathOfInstalledFile(mod, @"Data\scripts\modified.pex");
2020-03-28 02:54:14 +00:00
var extraPath = utils.PathOfInstalledFile(mod, @"something_i_made.foo");
await extraPath.WriteAllTextAsync("bleh");
2020-03-28 02:54:14 +00:00
var extraFolder = utils.PathOfInstalledFile(mod, @"something_i_made.foo").Parent.Combine("folder_i_made");
extraFolder.CreateDirectory();
2020-03-28 02:54:14 +00:00
Assert.True(extraFolder.IsDirectory);
2020-03-28 02:54:14 +00:00
var unchangedModified = unchangedPath.LastModified;
2020-03-28 02:54:14 +00:00
await modifiedPath.WriteAllTextAsync("random data");
var modifiedModified = modifiedPath.LastModified;
2020-05-26 11:31:11 +00:00
await deletedPath.DeleteAsync();
2020-03-28 02:54:14 +00:00
Assert.True(extraPath.Exists);
2019-12-07 02:54:27 +00:00
await CompileAndInstall(profile);
await utils.VerifyInstalledFile(mod, @"Data\scripts\unchanged.pex");
await utils.VerifyInstalledFile(mod, @"Data\scripts\deleted.pex");
await utils.VerifyInstalledFile(mod, @"Data\scripts\modified.pex");
2020-03-28 02:54:14 +00:00
Assert.Equal(unchangedModified, unchangedPath.LastModified);
Assert.NotEqual(modifiedModified, modifiedPath.LastModified);
Assert.False(extraPath.Exists);
Assert.False(extraFolder.Exists);
}
2020-03-28 02:54:14 +00:00
[Fact]
2019-12-13 13:02:58 +00:00
public async Task SetScreenSizeTest()
{
var profile = utils.AddProfile();
var mod = await utils.AddMod("dummy");
2020-03-28 02:54:14 +00:00
await utils.Configure();
await utils.MO2Folder.Combine("profiles", profile, "somegameprefs.ini").WriteAllLinesAsync(
// Beth inis are messy, let's make ours just as messy to catch some parse failures
"[Display]",
"foo=4",
"[Display]",
"STestFile=f",
"STestFile=",
"[Display]",
"foo=4",
"iSize H=50",
"iSize W=100",
"[MEMORY]",
"VideoMemorySizeMb=22");
2019-12-13 13:02:58 +00:00
var modlist = await CompileAndInstall(profile);
2020-03-28 02:54:14 +00:00
var ini = utils.InstallFolder.Combine("profiles", profile, "somegameprefs.ini").LoadIniFile();
2020-03-28 02:54:14 +00:00
var sysinfo = CreateDummySystemParameters();
2020-03-28 02:54:14 +00:00
Assert.Equal(sysinfo.ScreenHeight.ToString(), ini?.Display?["iSize H"]);
Assert.Equal(sysinfo.ScreenWidth.ToString(), ini?.Display?["iSize W"]);
Assert.Equal(sysinfo.EnbLEVRAMSize.ToString(), ini?.MEMORY?["VideoMemorySizeMb"]);
}
2020-03-28 02:54:14 +00:00
[Fact]
2019-12-07 02:54:27 +00:00
public async Task UnmodifiedInlinedFilesArePulledFromArchives()
2019-09-26 23:08:10 +00:00
{
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var ini = await utils.AddModFile(mod, @"foo.ini", 10);
2020-03-28 02:54:14 +00:00
await utils.Configure();
2019-09-26 23:08:10 +00:00
await utils.AddManualDownload(
2020-03-28 02:54:14 +00:00
new Dictionary<string, byte[]> { { "/baz/biz.pex", await ini.ReadAllBytesAsync() } });
2019-09-26 23:08:10 +00:00
2019-12-07 02:54:27 +00:00
var modlist = await CompileAndInstall(profile);
2020-03-28 02:54:14 +00:00
var directive = modlist.Directives.FirstOrDefault(m => m.To == (RelativePath)$"mods\\{mod}\\foo.ini");
2019-09-26 23:08:10 +00:00
2020-03-28 02:54:14 +00:00
Assert.NotNull(directive);
Assert.IsAssignableFrom<FromArchive>(directive);
2019-09-26 23:08:10 +00:00
}
2020-03-28 02:54:14 +00:00
[Fact]
2019-12-07 02:54:27 +00:00
public async Task ModifiedIniFilesArePatchedAgainstFileWithSameName()
2019-09-26 23:08:10 +00:00
{
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var ini = await utils.AddModFile(mod, @"foo.ini", 10);
var meta = await utils.AddModFile(mod, "meta.ini");
2019-11-21 21:32:58 +00:00
2020-03-28 02:54:14 +00:00
await utils.Configure();
2019-09-26 23:08:10 +00:00
2019-11-21 21:32:58 +00:00
var archive = utils.AddManualDownload(
2020-03-28 02:54:14 +00:00
new Dictionary<string, byte[]> { { "/baz/foo.ini", await ini.ReadAllBytesAsync() } });
2019-09-26 23:08:10 +00:00
2020-03-28 02:54:14 +00:00
await meta.WriteAllLinesAsync(
2019-11-21 21:32:58 +00:00
"[General]",
2020-03-28 02:54:14 +00:00
$"installationFile={archive}");
2019-11-21 21:32:58 +00:00
2019-09-26 23:08:10 +00:00
// Modify after creating mod archive in the downloads folder
2020-03-28 02:54:14 +00:00
await ini.WriteAllTextAsync("Wabbajack, Wabbajack, Wabbajack!");
2019-09-26 23:08:10 +00:00
2019-12-07 02:54:27 +00:00
var modlist = await CompileAndInstall(profile);
2020-03-28 02:54:14 +00:00
var directive = modlist.Directives.FirstOrDefault(m => m.To == (RelativePath)$"mods\\{mod}\\foo.ini");
2019-09-26 23:08:10 +00:00
2020-03-28 02:54:14 +00:00
Assert.NotNull(directive);
Assert.IsAssignableFrom<PatchedFromArchive>(directive);
2019-09-26 23:08:10 +00:00
}
2020-04-22 20:58:50 +00:00
[Fact]
public async Task CanPatchFilesSourcedFromBSAs()
{
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var file = await utils.AddModFile(mod, @"baz.bin", 10);
2020-04-22 20:58:50 +00:00
await utils.Configure();
await using var tempFile = new TempFile();
2020-04-22 20:58:50 +00:00
var bsaState = new BSAStateObject
{
Magic = "BSA\0", Version = 0x69, ArchiveFlags = 0x107, FileFlags = 0x0,
};
await using (var bsa = bsaState.MakeBuilder(1024 * 1024))
{
await bsa.AddFile(new BSAFileStateObject
{
Path = (RelativePath)@"foo\bar\baz.bin", Index = 0, FlipCompression = false
}, new MemoryStream(utils.RandomData()));
await bsa.Build(tempFile.Path);
}
var archive = utils.AddManualDownload(
new Dictionary<string, byte[]> { { "/stuff/files.bsa", await tempFile.Path.ReadAllBytesAsync() } });
await CompileAndInstall(profile);
await utils.VerifyInstalledFile(mod, @"baz.bin");
2020-04-22 20:58:50 +00:00
}
2020-04-27 21:32:19 +00:00
[Fact]
public async Task CanNoMatchIncludeFilesFromBSAs()
{
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var file = await utils.AddModFile(mod, @"baz.bsa", 10);
2020-04-27 21:32:19 +00:00
await file.Parent.Combine("meta.ini").WriteAllLinesAsync(new[]
{
"[General]",
"notes= asdf WABBAJACK_NOMATCH_INCLUDE asdfa"
});
await utils.Configure();
await using var tempFile = new TempFile();
2020-04-27 21:32:19 +00:00
var bsaState = new BSAStateObject
{
Magic = "BSA\0", Version = 0x69, ArchiveFlags = 0x107, FileFlags = 0x0,
};
var tempFileData = utils.RandomData(1024);
await using (var bsa = bsaState.MakeBuilder(1024 * 1024))
{
await bsa.AddFile(new BSAFileStateObject
{
Path = (RelativePath)@"matching_file.bin", Index = 0, FlipCompression = false
}, new MemoryStream(tempFileData));
await bsa.AddFile(
new BSAFileStateObject()
{
Path = (RelativePath)@"unmatching_file.bin", Index = 1, FlipCompression = false
}, new MemoryStream(utils.RandomData(1024)));
await bsa.Build(file);
}
var archive = utils.AddManualDownload(
new Dictionary<string, byte[]> { { "/stuff/matching_file_data.bin", tempFileData } });
await CompileAndInstall(profile);
await utils.VerifyInstalledFile(mod, @"baz.bsa");
2020-04-27 21:32:19 +00:00
}
2020-04-27 04:49:54 +00:00
[Fact]
public async Task CanInstallFilesFromBSAAndBSA()
{
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var file = await utils.AddModFile(mod, @"baz.bin", 128);
2020-04-27 04:49:54 +00:00
await utils.Configure();
await using var tempFile = new TempFile();
2020-04-27 04:49:54 +00:00
var bsaState = new BSAStateObject
{
Magic = "BSA\0", Version = 0x69, ArchiveFlags = 0x107, FileFlags = 0x0,
};
await using (var bsa = bsaState.MakeBuilder(1024 * 1024))
{
await bsa.AddFile(new BSAFileStateObject
{
Path = (RelativePath)@"foo\bar\baz.bin", Index = 0, FlipCompression = false
}, new MemoryStream(await file.ReadAllBytesAsync()));
await bsa.Build(tempFile.Path);
}
await tempFile.Path.CopyToAsync(file.Parent.Combine("bsa_data.bsa"));
2020-04-27 04:49:54 +00:00
var archive = utils.AddManualDownload(
new Dictionary<string, byte[]> { { "/stuff/files.bsa", await tempFile.Path.ReadAllBytesAsync() } });
await CompileAndInstall(profile);
await utils.VerifyInstalledFile(mod, @"baz.bin");
await utils.VerifyInstalledFile(mod, @"bsa_data.bsa");
2020-04-27 04:49:54 +00:00
}
2020-04-22 20:58:50 +00:00
[Fact]
public async Task CanRecreateBSAsFromFilesSourcedInOtherBSAs()
{
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var file = await utils.AddModFile(mod, @"baz.bsa", 10);
2020-04-22 20:58:50 +00:00
await utils.Configure();
var bsaState = new BSAStateObject
{
Magic = "BSA\0", Version = 0x69, ArchiveFlags = 0x107, FileFlags = 0x0,
};
// Create the download
await using var tempFile = new TempFile();
2020-04-22 20:58:50 +00:00
await using (var bsa = bsaState.MakeBuilder(1024 * 1024))
{
await bsa.AddFile(new BSAFileStateObject
{
Path = (RelativePath)@"foo\bar\baz.bin", Index = 0, FlipCompression = false
}, new MemoryStream(utils.RandomData()));
await bsa.Build(tempFile.Path);
}
var archive = utils.AddManualDownload(
new Dictionary<string, byte[]> { { "/stuff/baz.bsa", await tempFile.Path.ReadAllBytesAsync() } });
// Create the result
await using (var bsa = bsaState.MakeBuilder(1024 * 1024))
{
await bsa.AddFile(new BSAFileStateObject
{
Path = (RelativePath)@"foo\bar\baz.bin", Index = 0, FlipCompression = false
}, new MemoryStream(utils.RandomData()));
await bsa.Build(file);
}
await CompileAndInstall(profile);
await utils.VerifyInstalledFile(mod, @"baz.bsa");
2020-04-22 20:58:50 +00:00
}
/* TODO : Disabled For Now
[Fact]
public async Task CanSourceFilesFromStockGameFiles()
{
Consts.TestMode = false;
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var skyrimExe = await utils.AddModFile(mod, @"Data\test.exe", 10);
var gameFolder = Consts.GameFolderFilesDir.RelativeTo(utils.MO2Folder);
gameFolder.CreateDirectory();
var gameMeta = Game.SkyrimSpecialEdition.MetaData();
await gameMeta.GameLocation().Combine(gameMeta.MainExecutable!).CopyToAsync(skyrimExe);
await gameMeta.GameLocation().Combine(gameMeta.MainExecutable!).CopyToAsync(gameFolder.Combine(gameMeta.MainExecutable!));
await utils.Configure();
await CompileAndInstall(profile);
utils.VerifyInstalledFile(mod, @"Data\test.exe");
Assert.False("SkyrimSE.exe".RelativeTo(utils.DownloadsFolder).Exists, "File should not appear in the download folder because it should be copied from the game folder");
var file = "ModOrganizer.ini".RelativeTo(utils.InstallFolder);
Assert.True(file.Exists);
var ini = file.LoadIniFile();
Assert.Equal(((AbsolutePath)(string)ini?.General?.gamePath).Combine(gameMeta.MainExecutable),
Consts.GameFolderFilesDir.Combine(gameMeta.MainExecutable).RelativeTo(utils.InstallFolder));
Consts.TestMode = true;
}
*/
[Fact]
public async Task NoMatchIncludeIncludesNonMatchingFiles()
{
var profile = utils.AddProfile();
var mod = await utils.AddMod();
var testPex = await utils.AddModFile(mod, @"Data\scripts\test.pex", 10);
await utils.Configure();
await (await utils.AddModFile(mod, "meta.ini")).WriteAllLinesAsync(new[]
{
"[General]", "notes= fsdaf WABBAJACK_NOMATCH_INCLUDE fadsfsad",
});
await CompileAndInstall(profile);
await utils.VerifyInstalledFile(mod, @"Data\scripts\test.pex");
}
/// <summary>
/// Issue #861 : https://github.com/wabbajack-tools/wabbajack/issues/861
/// </summary>
/// <returns></returns>
[Fact]
public async Task AlwaysEnabledModsRetainTheirOrder()
{
var profile = utils.AddProfile();
var enabledMod = await utils.AddMod();
var enabledTestPex = await utils.AddModFile(enabledMod, @"Data\scripts\enabledTestPex.pex", 10);
var disabledMod = await utils.AddMod();
var disabledTestPex = await utils.AddModFile(disabledMod, @"Data\scripts\disabledTestPex.pex", 10);
await disabledMod.RelativeTo(utils.ModsFolder).Combine("meta.ini").WriteAllLinesAsync(
"[General]",
$"notes={Consts.WABBAJACK_ALWAYS_ENABLE}");
await utils.Configure(new []
{
(disabledMod, false),
(enabledMod, true)
});
await utils.AddManualDownload(
new Dictionary<string, byte[]>
{
{"/file1.pex", await enabledTestPex.ReadAllBytesAsync()},
{"/file2.pex", await disabledTestPex.ReadAllBytesAsync()},
});
await CompileAndInstall(profile);
await utils.VerifyInstalledFile(enabledMod, @"Data\scripts\enabledTestPex.pex");
await utils.VerifyInstalledFile(disabledMod, @"Data\scripts\disabledTestPex.pex");
var modlistTxt = await utils.InstallFolder.Combine("profiles", profile, "modlist.txt").ReadAllLinesAsync();
Assert.Equal(new string[]
{
$"-{disabledMod}",
$"+{enabledMod}"
}, modlistTxt.ToArray());
}
2020-03-28 02:54:14 +00:00
2019-09-24 04:20:24 +00:00
}
}