2020-05-02 23:05:05 +00:00
using System ;
using System.Collections.Generic ;
2020-01-05 05:07:00 +00:00
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-06-27 17:04:59 +00:00
using Compression.BSA ;
2019-12-06 04:58:18 +00:00
using Wabbajack.Common ;
2021-06-17 23:09:03 +00:00
using Wabbajack.ImageHashing ;
2019-10-16 03:10:34 +00:00
using Wabbajack.Lib ;
2020-10-22 00:43:02 +00:00
using Wabbajack.Lib.CompilationSteps ;
2020-03-28 02:54:14 +00:00
using Xunit ;
using Xunit.Abstractions ;
2020-07-07 20:17:49 +00:00
using Xunit.Sdk ;
2021-07-10 22:27:36 +00:00
using DXGI_FORMAT = Wabbajack . ImageHashing . DXGI_FORMAT ;
2019-09-24 04:20:24 +00:00
namespace Wabbajack.Test
{
2019-10-31 02:24:42 +00:00
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 ( ) ;
2020-05-25 17:34:25 +00:00
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
2020-05-25 17:34:25 +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
2020-05-25 17:34:25 +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
2021-02-24 00:26:50 +00:00
[Fact]
public async Task TestCacheFileAreIgnored ( )
{
var profile = utils . AddProfile ( ) ;
var mod = await utils . AddMod ( ) ;
var testCache = await utils . AddModFile ( mod , @"Data\scripts\test.cache" , 10 ) ;
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 CompileAndInstall ( profile ) ;
await utils . VerifyInstalledFile ( mod , @"Data\scripts\test.pex" ) ;
}
2020-05-10 12:37:55 +00:00
[Fact]
public async Task ExtraFilesInDownloadFolderDontStopCompilation ( )
{
var profile = utils . AddProfile ( ) ;
2020-05-25 17:34:25 +00:00
var mod = await utils . AddMod ( ) ;
var testPex = await utils . AddModFile ( mod , @"Data\scripts\test.pex" , 10 ) ;
2020-05-10 12:37:55 +00:00
await utils . Configure ( ) ;
2020-05-25 17:34:25 +00:00
await utils . AddManualDownload (
2020-05-10 12:37:55 +00:00
new Dictionary < string , byte [ ] > { { "/baz/biz.pex" , await testPex . ReadAllBytesAsync ( ) } } ) ;
2020-10-18 19:03:50 +00:00
await utils . DownloadsPath . Combine ( "some_other_file.7z" ) . WriteAllTextAsync ( "random data" ) ;
2020-05-10 12:37:55 +00:00
await CompileAndInstall ( profile ) ;
2020-05-25 17:34:25 +00:00
await utils . VerifyInstalledFile ( mod , @"Data\scripts\test.pex" ) ;
2020-05-10 12:37:55 +00:00
}
2020-03-28 02:54:14 +00:00
[Fact]
2020-01-07 00:24:33 +00:00
public async Task TestDirectMatchFromGameFolder ( )
{
2020-07-07 20:17:49 +00:00
// This code is disabled, but we'll still test for it in case it somehow gets re-enabled in the future
2020-01-07 00:24:33 +00:00
var profile = utils . AddProfile ( ) ;
2020-05-25 17:34:25 +00:00
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-05-25 17:34:25 +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
2020-06-02 02:18:32 +00:00
await CompileAndInstall ( profile , useGameFiles : true ) ;
2020-01-07 00:24:33 +00:00
2020-07-07 20:17:49 +00:00
// This should fail
await Assert . ThrowsAsync < TrueException > ( async ( ) = > 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 ( ) ;
2020-05-25 17:34:25 +00:00
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-10-18 19:03:50 +00:00
utils . SourcePath . Combine ( Consts . GameFolderFilesDir ) . CreateDirectory ( ) ;
2020-01-07 00:24:33 +00:00
2020-05-25 17:34:25 +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-10-18 19:03:50 +00:00
Assert . False ( utils . InstallPath . 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 ( )
2019-11-07 04:43:30 +00:00
{
var profile = utils . AddProfile ( ) ;
2020-05-25 17:34:25 +00:00
var mod = await utils . AddMod ( ) ;
var testPex = await utils . AddModFile ( mod , @"Data\scripts\test.pex" , 10 ) ;
2019-11-07 04:43:30 +00:00
// Make a copy to make sure it gets picked up and moved around.
2020-05-25 17:34:25 +00:00
await testPex . CopyToAsync ( testPex . WithExtension ( new Extension ( ".copy" ) ) ) ;
2019-11-07 04:43:30 +00:00
2020-03-28 02:54:14 +00:00
await utils . Configure ( ) ;
2019-11-07 04:43:30 +00:00
2020-05-25 17:34:25 +00:00
await utils . AddManualDownload (
2020-03-28 02:54:14 +00:00
new Dictionary < string , byte [ ] > { { "/baz/biz.pex" , await testPex . ReadAllBytesAsync ( ) } } ) ;
2019-11-07 04:43:30 +00:00
2019-12-07 02:54:27 +00:00
await CompileAndInstall ( profile ) ;
2019-11-07 04:43:30 +00:00
2020-05-25 17:34:25 +00:00
await utils . VerifyInstalledFile ( mod , @"Data\scripts\test.pex" ) ;
await utils . VerifyInstalledFile ( mod , @"Data\scripts\test.pex.copy" ) ;
2019-11-07 04:43:30 +00:00
}
2020-03-28 02:54:14 +00:00
[Fact]
2019-12-07 02:54:27 +00:00
public async Task TestUpdating ( )
2019-11-18 05:21:24 +00:00
{
var profile = utils . AddProfile ( ) ;
2020-05-25 17:34:25 +00:00
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 ) ;
2019-11-18 05:21:24 +00:00
2020-03-28 02:54:14 +00:00
await utils . Configure ( ) ;
2019-11-18 05:21:24 +00:00
2020-05-25 17:34:25 +00:00
await utils . AddManualDownload (
2019-11-18 05:21:24 +00:00
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-11-18 05:21:24 +00:00
} ) ;
2019-12-07 02:54:27 +00:00
await CompileAndInstall ( profile ) ;
2019-11-18 05:21:24 +00:00
2020-05-25 17:34:25 +00:00
await utils . VerifyInstalledFile ( mod , @"Data\scripts\unchanged.pex" ) ;
await utils . VerifyInstalledFile ( mod , @"Data\scripts\deleted.pex" ) ;
await utils . VerifyInstalledFile ( mod , @"Data\scripts\modified.pex" ) ;
2019-11-18 05:21:24 +00:00
2021-03-24 22:20:59 +00:00
var nodeletefile = utils . InstallPath . Combine ( "mods" , "[NoDelete] Mod I added" , "somefile.esp" ) ;
nodeletefile . Parent . CreateDirectory ( ) ;
await nodeletefile . WriteAllTextAsync ( "some data" ) ;
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" ) ;
2019-11-18 05:21:24 +00:00
2020-03-28 02:54:14 +00:00
var extraPath = utils . PathOfInstalledFile ( mod , @"something_i_made.foo" ) ;
await extraPath . WriteAllTextAsync ( "bleh" ) ;
2019-11-20 00:15:46 +00:00
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-01-05 05:07:00 +00:00
2020-03-28 02:54:14 +00:00
Assert . True ( extraFolder . IsDirectory ) ;
2020-01-05 05:07:00 +00:00
2019-11-18 05:21:24 +00:00
2020-03-28 02:54:14 +00:00
var unchangedModified = unchangedPath . LastModified ;
2019-11-18 05:21:24 +00:00
2020-03-28 02:54:14 +00:00
await modifiedPath . WriteAllTextAsync ( "random data" ) ;
var modifiedModified = modifiedPath . LastModified ;
2019-11-18 05:21:24 +00:00
2020-05-26 11:31:11 +00:00
await deletedPath . DeleteAsync ( ) ;
2019-11-20 00:15:46 +00:00
2020-03-28 02:54:14 +00:00
Assert . True ( extraPath . Exists ) ;
2019-12-07 02:54:27 +00:00
await CompileAndInstall ( profile ) ;
2019-11-18 05:21:24 +00:00
2020-05-25 17:34:25 +00:00
await utils . VerifyInstalledFile ( mod , @"Data\scripts\unchanged.pex" ) ;
await utils . VerifyInstalledFile ( mod , @"Data\scripts\deleted.pex" ) ;
await utils . VerifyInstalledFile ( mod , @"Data\scripts\modified.pex" ) ;
2019-11-18 05:21:24 +00:00
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 ) ;
2021-03-24 22:20:59 +00:00
Assert . True ( nodeletefile . Exists , "File should exist because it's in a [NoDelete] folder" ) ;
2019-11-18 05:21:24 +00:00
}
2020-07-01 03:46:26 +00:00
[Fact]
public async Task SaveFilesAreIgnored ( )
{
var profile = utils . AddProfile ( ) ;
var mod = await utils . AddMod ( "dummy" ) ;
2020-10-18 19:03:50 +00:00
var saveFolder = utils . SourcePath . Combine ( "profiles" , profile , "saves" ) ;
2020-07-01 03:46:26 +00:00
saveFolder . CreateDirectory ( ) ;
await saveFolder . Combine ( "incompilation" ) . WriteAllTextAsync ( "ignore this" ) ;
2020-10-18 19:03:50 +00:00
var installSaveFolderThisProfile = utils . InstallPath . Combine ( "profiles" , profile , "saves" ) ;
var installSaveFolderOtherProfile = utils . InstallPath . Combine ( "profiles" , "Other Profile" , "saves" ) ;
2020-07-01 03:46:26 +00:00
installSaveFolderThisProfile . CreateDirectory ( ) ;
installSaveFolderOtherProfile . CreateDirectory ( ) ;
await installSaveFolderOtherProfile . Combine ( "otherprofile" ) . WriteAllTextAsync ( "other profile file" ) ;
await installSaveFolderThisProfile . Combine ( "thisprofile" ) . WriteAllTextAsync ( "this profile file" ) ;
await utils . Configure ( ) ;
var modlist = await CompileAndInstall ( profile ) ;
Assert . Equal ( "other profile file" , await installSaveFolderOtherProfile . Combine ( "otherprofile" ) . ReadAllTextAsync ( ) ) ;
Assert . Equal ( "this profile file" , await installSaveFolderThisProfile . Combine ( "thisprofile" ) . ReadAllTextAsync ( ) ) ;
Assert . False ( installSaveFolderThisProfile . Combine ( "incompilation" ) . Exists ) ;
}
2020-03-28 02:54:14 +00:00
[Fact]
2019-12-13 13:02:58 +00:00
public async Task SetScreenSizeTest ( )
2019-12-06 04:58:18 +00:00
{
var profile = utils . AddProfile ( ) ;
2020-05-25 17:34:25 +00:00
var mod = await utils . AddMod ( "dummy" ) ;
2019-12-06 04:58:18 +00:00
2020-03-28 02:54:14 +00:00
await utils . Configure ( ) ;
2020-10-18 19:03:50 +00:00
await utils . SourcePath . Combine ( "profiles" , profile , "somegameprefs.ini" ) . WriteAllLinesAsync (
2020-03-28 02:54:14 +00:00
// 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" ) ;
2021-03-24 22:20:59 +00:00
await utils . SourcePath . Combine ( "profiles" , profile , "oblivion.ini" ) . WriteAllLinesAsync (
// Beth inis are messy, let's make ours just as messy to catch some parse failures
"STestFile=" ,
"[Display]" ,
"foo=4" ,
"iSize H=50" ,
"iSize W=100" ) ;
await utils . SourcePath . Combine ( "SseDisplayTweaks.ini" ) . WriteAllLinesAsync (
"[Render]" ,
"Resolution=100x100" ) ;
2019-12-06 04:58:18 +00:00
2019-12-13 13:02:58 +00:00
var modlist = await CompileAndInstall ( profile ) ;
2019-11-02 21:08:37 +00:00
2020-10-18 19:03:50 +00:00
var ini = utils . InstallPath . Combine ( "profiles" , profile , "somegameprefs.ini" ) . LoadIniFile ( ) ;
2019-11-02 21:08:37 +00:00
2020-03-28 02:54:14 +00:00
var sysinfo = CreateDummySystemParameters ( ) ;
2020-03-10 04:11:11 +00:00
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" ] ) ;
2021-03-24 22:20:59 +00:00
var ini2 = utils . InstallPath . Combine ( "profiles" , profile , "Oblivion.ini" ) . LoadIniFile ( ) ;
Assert . Equal ( sysinfo . ScreenHeight . ToString ( ) , ini2 ? . Display ? [ "iSize H" ] ) ;
Assert . Equal ( sysinfo . ScreenWidth . ToString ( ) , ini2 ? . Display ? [ "iSize W" ] ) ;
var ini3 = utils . InstallPath . Combine ( "sseDisplayTweaks.ini" ) . LoadIniFile ( ) ;
Assert . Equal ( $"{sysinfo.ScreenWidth}x{sysinfo.ScreenHeight}" , ini3 ? . Render ? . Resolution ) ;
2019-11-02 21:08:37 +00:00
}
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 ( ) ;
2020-05-25 17:34:25 +00:00
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
2020-05-25 17:34:25 +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 ( ) ;
2020-05-25 17:34:25 +00:00
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 ( ) ;
2020-05-25 17:34:25 +00:00
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 ( ) ;
2020-05-28 02:43:57 +00:00
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 ,
} ;
2020-07-20 01:19:56 +00:00
await using ( var bsa = await bsaState . MakeBuilder ( 1024 * 1024 ) )
2020-04-22 20:58:50 +00:00
{
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 ) ;
2020-05-25 17:34:25 +00:00
await utils . VerifyInstalledFile ( mod , @"baz.bin" ) ;
2020-04-22 20:58:50 +00:00
}
2021-06-17 23:09:03 +00:00
[Fact]
public async Task CanRecompressAndResizeDDSImages ( )
{
var profile = utils . AddProfile ( ) ;
var mod = await utils . AddMod ( ) ;
var nativeFile = await utils . AddModFile ( mod , @"native\whitestagbody.dds" , 0 ) ;
var recompressedFile = await utils . AddModFile ( mod , @"recompressed\whitestagbody.dds" , 0 ) ;
var resizedFile = await utils . AddModFile ( mod , @"resized\whitestagbody.dds" , 0 ) ;
var gameBSA = Game . SkyrimSpecialEdition . MetaData ( ) . GameLocation ( ) . Combine ( @"Data\Skyrim - Textures1.bsa" ) ;
var bsa = await BSADispatch . OpenRead ( gameBSA ) ;
var ddsExtension = new Extension ( ".dds" ) ;
var firstFile = bsa . Files . First ( f = > f . Path . Extension = = ddsExtension ) ;
await using ( var nf = await nativeFile . OpenWrite ( ) )
{
await firstFile . CopyDataTo ( nf ) ;
}
{
2021-07-10 22:27:36 +00:00
var originalDDS = await ImageState . GetState ( nativeFile ) ;
await ImageState . ConvertImage ( nativeFile , recompressedFile . Parent , originalDDS . Width , originalDDS . Height , DXGI_FORMAT . BC7_UNORM , recompressedFile . Extension ) ;
2021-07-17 10:21:26 +00:00
await ImageState . ConvertImage ( nativeFile , resizedFile . Parent , 1024 , 1024 , DXGI_FORMAT . BC7_UNORM , resizedFile . Extension ) ;
2021-06-17 23:09:03 +00:00
}
await utils . Configure ( ) ;
2021-07-17 10:21:26 +00:00
var compilerData = await CompileAndInstall ( profile , true ) ;
2021-06-17 23:09:03 +00:00
await utils . VerifyInstalledFile ( mod , @"native\whitestagbody.dds" ) ;
2021-07-17 10:21:26 +00:00
var directies = compilerData . Directives ;
Assert . True ( 0.99f < = ( await ImageState . GetState ( recompressedFile ) ) . PerceptualHash . Similarity ( await ImageState . GetPHash ( utils . InstalledPath ( mod , @"recompressed\whitestagbody.dds" ) ) ) ) ;
Assert . True ( 0.98f < = ( await ImageState . GetState ( resizedFile ) ) . PerceptualHash . Similarity ( await ImageState . GetPHash ( utils . InstalledPath ( mod , @"resized\whitestagbody.dds" ) ) ) ) ;
2021-06-17 23:09:03 +00:00
}
2020-04-27 21:32:19 +00:00
[Fact]
public async Task CanNoMatchIncludeFilesFromBSAs ( )
{
var profile = utils . AddProfile ( ) ;
2020-05-25 17:34:25 +00:00
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 ( ) ;
2020-05-28 02:43:57 +00:00
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 ) ;
2020-07-20 01:19:56 +00:00
await using ( var bsa = await bsaState . MakeBuilder ( 1024 * 1024 ) )
2020-04-27 21:32:19 +00:00
{
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 ) ;
2020-05-25 17:34:25 +00:00
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 ( ) ;
2020-05-25 17:34:25 +00:00
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 ( ) ;
2020-05-28 02:43:57 +00:00
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 ,
} ;
2020-07-20 01:19:56 +00:00
await using ( var bsa = await bsaState . MakeBuilder ( 1024 * 1024 ) )
2020-04-27 04:49:54 +00:00
{
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 ) ;
}
2020-05-25 17:34:25 +00:00
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 ) ;
2020-05-25 17:34:25 +00:00
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 ( ) ;
2020-05-25 17:34:25 +00:00
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
2020-05-28 02:43:57 +00:00
await using var tempFile = new TempFile ( ) ;
2020-07-20 01:19:56 +00:00
await using ( var bsa = await bsaState . MakeBuilder ( 1024 * 1024 ) )
2020-04-22 20:58:50 +00:00
{
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
2020-07-20 01:19:56 +00:00
await using ( var bsa = await bsaState . MakeBuilder ( 1024 * 1024 ) )
2020-04-22 20:58:50 +00:00
{
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 ) ;
2020-05-25 17:34:25 +00:00
await utils . VerifyInstalledFile ( mod , @"baz.bsa" ) ;
2020-04-22 20:58:50 +00:00
}
2020-05-02 21:09:29 +00:00
2020-05-09 05:12:51 +00:00
/ * TODO : Disabled For Now
2020-05-02 21:09:29 +00:00
[Fact]
public async Task CanSourceFilesFromStockGameFiles ( )
{
Consts . TestMode = false ;
var profile = utils . AddProfile ( ) ;
2020-05-25 17:34:25 +00:00
var mod = await utils . AddMod ( ) ;
var skyrimExe = await utils . AddModFile ( mod , @"Data\test.exe" , 10 ) ;
2020-05-02 21:09:29 +00:00
2020-05-02 23:05:05 +00:00
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 ! ) ) ;
2020-05-02 21:09:29 +00:00
await utils . Configure ( ) ;
await CompileAndInstall ( profile ) ;
utils . VerifyInstalledFile ( mod , @"Data\test.exe" ) ;
2020-05-02 23:05:05 +00:00
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 ) ;
2020-05-02 21:09:29 +00:00
2020-05-02 23:05:05 +00:00
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 ;
2020-05-02 21:09:29 +00:00
}
2020-05-09 05:12:51 +00:00
* /
2020-04-22 04:13:07 +00:00
[Fact]
public async Task NoMatchIncludeIncludesNonMatchingFiles ( )
{
var profile = utils . AddProfile ( ) ;
2020-05-25 17:34:25 +00:00
var mod = await utils . AddMod ( ) ;
var testPex = await utils . AddModFile ( mod , @"Data\scripts\test.pex" , 10 ) ;
2020-04-22 04:13:07 +00:00
await utils . Configure ( ) ;
2020-05-25 17:34:25 +00:00
await ( await utils . AddModFile ( mod , "meta.ini" ) ) . WriteAllLinesAsync ( new [ ]
2020-04-22 04:13:07 +00:00
{
"[General]" , "notes= fsdaf WABBAJACK_NOMATCH_INCLUDE fadsfsad" ,
} ) ;
await CompileAndInstall ( profile ) ;
2020-05-25 17:34:25 +00:00
await utils . VerifyInstalledFile ( mod , @"Data\scripts\test.pex" ) ;
2020-04-22 04:13:07 +00:00
}
2020-05-23 21:41:41 +00:00
2020-06-20 22:51:47 +00:00
[Fact]
public async Task CanSourceFilesFromTheGameFiles ( )
{
var profile = utils . AddProfile ( ) ;
var mod = await utils . AddMod ( ) ;
2020-09-11 12:54:24 +00:00
await new CompilerSettings ( )
{
IncludedGames = new [ ] { Game . Morrowind }
2020-10-18 19:03:50 +00:00
} . ToJsonAsync ( utils . SourcePath . Combine ( "profiles" , profile , CompilerSettings . FileName ) , true ) ;
2020-09-11 12:54:24 +00:00
2020-06-20 22:51:47 +00:00
Game . SkyrimSpecialEdition . MetaData ( ) . CanSourceFrom = new [ ] { Game . Morrowind , Game . Skyrim } ;
// Morrowind file with different name
var mwFile = Game . Morrowind . MetaData ( ) . GameLocation ( ) . Combine ( "Data Files" , "Bloodmoon.esm" ) ;
var testMW = await utils . AddModFile ( mod , @"Data\MW\Bm.esm" ) ;
await mwFile . CopyToAsync ( testMW ) ;
2020-06-21 02:55:42 +00:00
// SkyrimSE file with same name
var skyrimFile = Game . SkyrimSpecialEdition . MetaData ( ) . GameLocation ( ) . Combine ( "Data" , "Update.esm" ) ;
var testSky = await utils . AddModFile ( mod , @"Data\SkyrimSE\Update.esm.old" ) ;
2020-06-20 22:51:47 +00:00
await skyrimFile . CopyToAsync ( testSky ) ;
// Same game, but patched ata
var pdata = utils . RandomData ( 1024 ) ;
var testSkySE = await utils . AddModFile ( mod , @"Data\SkyrimSE\Update.esm" ) ;
await testSkySE . WriteAllBytesAsync ( pdata ) ;
await utils . Configure ( ) ;
await CompileAndInstall ( profile , useGameFiles : true ) ;
await utils . VerifyInstalledFile ( mod , @"Data\MW\Bm.esm" ) ;
2020-06-21 02:55:42 +00:00
await utils . VerifyInstalledFile ( mod , @"Data\SkyrimSE\Update.esm.old" ) ;
2020-06-20 22:51:47 +00:00
await utils . VerifyInstalledFile ( mod , @"Data\SkyrimSE\Update.esm" ) ;
2020-10-18 19:03:50 +00:00
Assert . False ( utils . InstallPath . Combine ( Consts . GameFolderFilesDir ) . IsDirectory ) ;
2020-07-07 20:17:49 +00:00
2020-06-20 22:51:47 +00:00
}
2020-07-16 02:53:58 +00:00
[Fact]
public async Task MissingGameFolderFilesBreakInstallation ( )
{
var profile = utils . AddProfile ( ) ;
var mod = await utils . AddMod ( ) ;
var testPex = await utils . AddModFile ( mod , @"Data\scripts\test.pex" , 10 ) ;
await utils . Configure ( ) ;
2020-10-18 19:03:50 +00:00
utils . SourcePath . Combine ( Consts . GameFolderFilesDir ) . CreateDirectory ( ) ;
await utils . SourcePath . Combine ( Consts . GameFolderFilesDir ) . Combine ( "dx4242.dll" )
2020-07-16 02:53:58 +00:00
. WriteAllBytesAsync ( utils . RandomData ( ) ) ;
await utils . AddManualDownload (
new Dictionary < string , byte [ ] > { { "/baz/biz.pex" , await testPex . ReadAllBytesAsync ( ) } } ) ;
await Assert . ThrowsAsync < TrueException > ( async ( ) = > await CompileAndInstall ( profile ) ) ;
}
2020-05-23 21:41:41 +00:00
/// <summary>
/// Issue #861 : https://github.com/wabbajack-tools/wabbajack/issues/861
/// </summary>
/// <returns></returns>
[Fact]
public async Task AlwaysEnabledModsRetainTheirOrder ( )
{
var profile = utils . AddProfile ( ) ;
2020-05-25 17:34:25 +00:00
var enabledMod = await utils . AddMod ( ) ;
var enabledTestPex = await utils . AddModFile ( enabledMod , @"Data\scripts\enabledTestPex.pex" , 10 ) ;
2020-05-23 21:41:41 +00:00
2020-05-25 17:34:25 +00:00
var disabledMod = await utils . AddMod ( ) ;
var disabledTestPex = await utils . AddModFile ( disabledMod , @"Data\scripts\disabledTestPex.pex" , 10 ) ;
2020-05-23 21:41:41 +00:00
2020-10-18 19:03:50 +00:00
await disabledMod . RelativeTo ( utils . ModsPath ) . Combine ( "meta.ini" ) . WriteAllLinesAsync (
2020-05-23 21:41:41 +00:00
"[General]" ,
$"notes={Consts.WABBAJACK_ALWAYS_ENABLE}" ) ;
await utils . Configure ( new [ ]
{
( disabledMod , false ) ,
( enabledMod , true )
} ) ;
2020-05-25 17:34:25 +00:00
await utils . AddManualDownload (
2020-05-23 21:41:41 +00:00
new Dictionary < string , byte [ ] >
{
{ "/file1.pex" , await enabledTestPex . ReadAllBytesAsync ( ) } ,
{ "/file2.pex" , await disabledTestPex . ReadAllBytesAsync ( ) } ,
} ) ;
await CompileAndInstall ( profile ) ;
2020-05-25 17:34:25 +00:00
await utils . VerifyInstalledFile ( enabledMod , @"Data\scripts\enabledTestPex.pex" ) ;
await utils . VerifyInstalledFile ( disabledMod , @"Data\scripts\disabledTestPex.pex" ) ;
2020-05-23 21:41:41 +00:00
2020-10-18 19:03:50 +00:00
var modlistTxt = await utils . InstallPath . Combine ( "profiles" , profile , "modlist.txt" ) . ReadAllLinesAsync ( ) ;
2020-05-23 21:41:41 +00:00
Assert . Equal ( new string [ ]
{
$"-{disabledMod}" ,
$"+{enabledMod}"
} , modlistTxt . ToArray ( ) ) ;
}
2020-03-28 02:54:14 +00:00
2020-10-18 19:03:50 +00:00
[Fact]
public async Task CanCompileFromNativeSource ( )
{
utils . CreatePaths ( ) ;
var gameFolder = Game . SkyrimSpecialEdition . MetaData ( ) . GameLocation ( ) ;
await gameFolder . Combine ( "SkyrimSE.exe" ) . CopyToAsync ( utils . SourcePath . Combine ( "SkyrimSE.exe" ) ) ;
2021-07-17 12:37:16 +00:00
var some_dds = utils . SourcePath . Combine ( "some_file.txx" ) ;
2020-10-18 19:03:50 +00:00
await some_dds . WriteAllBytesAsync ( utils . RandomData ( ) ) ;
2020-10-19 00:15:22 +00:00
var blerg = utils . SourcePath . Combine ( "file1.blerg" ) ;
await blerg . WriteAllBytesAsync ( utils . RandomData ( ) ) ;
2020-10-18 19:03:50 +00:00
await utils . AddManualDownload (
new Dictionary < string , byte [ ] >
{
2020-10-19 00:15:22 +00:00
{ "file1.blerg" , await some_dds . ReadAllBytesAsync ( ) } ,
2020-10-18 19:03:50 +00:00
} ) ;
var settings = new NativeCompilerSettings
{
CompilingGame = Game . SkyrimSpecialEdition ,
CompilationSteps = new [ ]
{
new [ ] { "IgnoreStartsWith" , "downloads" } ,
new [ ] { "IncludeConfigs" } ,
new [ ] { "IncludeDirectMatches" } ,
2020-10-19 00:15:22 +00:00
new [ ] { "IncludePatches" }
2020-10-18 19:03:50 +00:00
}
} ;
var settingsPath = utils . SourcePath . Combine ( "native_compiler_settings.json" ) ;
await settings . ToJsonAsync ( utils . SourcePath . Combine ( "native_compiler_settings.json" ) , true ) ;
await CompileAndInstall ( settingsPath , true ) ;
2021-07-17 12:37:16 +00:00
Assert . Equal ( await some_dds . FileHashAsync ( ) , await utils . InstallPath . Combine ( "some_file.txx" ) . FileHashAsync ( ) ) ;
2020-10-18 19:03:50 +00:00
Assert . Equal ( await gameFolder . Combine ( "SkyrimSE.exe" ) . FileHashAsync ( ) ,
await utils . InstallPath . Combine ( "SkyrimSE.exe" ) . FileHashAsync ( ) ) ;
}
2020-10-22 00:43:02 +00:00
[Fact]
public async Task IniFilesRemapAsExpected ( )
{
var file1 = await @"Resources\test_ini01.ini" . RelativeTo ( AbsolutePath . EntryPoint ) . ReadAllTextAsync ( ) ;
ACompiler compiler = new NativeCompiler ( new NativeCompilerSettings ( )
{
CompilingGame = Game . SkyrimSpecialEdition ,
} , sourcePath : ( AbsolutePath ) @"C:/Modlists/Living Skyrim 2/" ,
downloadsPath : AbsolutePath . EntryPoint ,
AbsolutePath . EntryPoint ) ;
2020-10-24 00:16:13 +00:00
var gamePath = Game . SkyrimSpecialEdition . MetaData ( ) . GameLocation ( ) . Normalize ( ) ;
2020-10-24 13:32:56 +00:00
file1 = file1 . Replace ( @"C:\\Steam_SUBS\\steamapps\\common\\Skyrim Special Edition" , gamePath . Replace ( @"\" , @"\\" ) , StringComparison . InvariantCultureIgnoreCase ) ;
file1 = file1 . Replace ( @"C:\Steam_SUBS\steamapps\common\Skyrim Special Edition" , gamePath , StringComparison . InvariantCultureIgnoreCase ) ;
file1 = file1 . Replace ( "C:/Steam_SUBS/steamapps/common/Skyrim Special Edition" , gamePath . Replace ( @"\" , "/" ) , StringComparison . InvariantCultureIgnoreCase ) ;
var newData = IncludeStubbedConfigFiles . RemapData ( compiler , string . Join ( "\n" , file1 ) ) ;
2020-10-22 00:43:02 +00:00
var ini = newData . LoadIniString ( ) . customExecutables ;
Assert . Equal ( $"{Consts.GAME_PATH_MAGIC_FORWARD}/skse64_loader.exe" , ini [ @"1\binary" ] ) ;
Assert . Equal ( $"\\\" { Consts . GAME_PATH_MAGIC_DOUBLE_BACK } \ \ \ \ data \ \ \ "" , ini [ @"5\arguments" ] ) ;
Assert . Equal ( $"{Consts.MO2_PATH_MAGIC_FORWARD}/mods/Fores New Idles in Skyrim SE - FNIS SE/tools/GenerateFNIS_for_Users/GenerateFNISforUsers.exe" , ini [ @"8\binary" ] ) ;
}
2019-09-24 04:20:24 +00:00
}
}