wabbajack/Compression.BSA.Test/BSATests.cs

176 lines
6.7 KiB
C#
Raw Normal View History

2019-11-11 06:15:52 +00:00
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
2019-11-11 06:15:52 +00:00
using Alphaleonis.Win32.Filesystem;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using Wabbajack.Common;
using Wabbajack.Lib.Downloaders;
using Wabbajack.Lib.NexusApi;
using Wabbajack.VirtualFileSystem;
2019-11-11 06:15:52 +00:00
using Directory = Alphaleonis.Win32.Filesystem.Directory;
using File = Alphaleonis.Win32.Filesystem.File;
using FileInfo = Alphaleonis.Win32.Filesystem.FileInfo;
using Path = Alphaleonis.Win32.Filesystem.Path;
namespace Compression.BSA.Test
{
[TestClass]
public class BSATests
{
private static AbsolutePath _stagingFolder = ((RelativePath)"NexusDownloads").RelativeToEntryPoint();
private static AbsolutePath _bsaFolder = ((RelativePath)"BSAs").RelativeToEntryPoint();
private static AbsolutePath _testDir = ((RelativePath)"BSA Test Dir").RelativeToEntryPoint();
private static AbsolutePath _tempDir = ((RelativePath)"BSA Temp Dir").RelativeToEntryPoint();
2019-11-11 06:15:52 +00:00
public TestContext TestContext { get; set; }
2019-11-17 04:16:42 +00:00
private static WorkQueue Queue { get; set; }
2019-11-11 06:15:52 +00:00
[ClassInitialize]
public static async Task Setup(TestContext testContext)
2019-11-11 06:15:52 +00:00
{
2019-11-17 04:16:42 +00:00
Queue = new WorkQueue();
2019-12-04 04:12:08 +00:00
Utils.LogMessages.Subscribe(f => testContext.WriteLine(f.ShortDescription));
_stagingFolder.DeleteDirectory();
_bsaFolder.DeleteDirectory();
2019-11-11 06:15:52 +00:00
2019-11-21 15:41:46 +00:00
var modIDs = new[]
2019-11-11 06:15:52 +00:00
{
(Game.SkyrimSpecialEdition, 12604), // SkyUI
(Game.Skyrim, 3863), // SkyUI
(Game.Skyrim, 51473), // iNeed
//(Game.Fallout4, 22223) // 10mm SMG
(Game.Fallout4, 4472), // True Storms
(Game.Morrowind, 44537) // Morrowind TAMRIEL_DATA
2019-11-11 06:15:52 +00:00
};
2019-12-07 02:45:13 +00:00
await Task.WhenAll(modIDs.Select(async (info) =>
2019-11-11 06:15:52 +00:00
{
var filename = await DownloadMod(info);
var folder = _bsaFolder.Combine(info.Item1.ToString(), info.Item2.ToString());
folder.CreateDirectory();
await FileExtractor.ExtractAll(Queue, filename, folder);
2019-12-07 02:45:13 +00:00
}));
2019-11-11 06:15:52 +00:00
}
private static async Task<AbsolutePath> DownloadMod((Game, int) info)
2019-11-11 06:15:52 +00:00
{
using var client = await NexusApiClient.Get();
var results = await client.GetModFiles(info.Item1, info.Item2);
var file = results.files.FirstOrDefault(f => f.is_primary) ??
results.files.OrderByDescending(f => f.uploaded_timestamp).First();
var src = _stagingFolder.Combine(file.file_name);
if (src.Exists) return src;
var state = new NexusDownloader.State
{
ModID = info.Item2.ToString(),
GameName = info.Item1.MetaData().NexusName,
FileID = file.file_id.ToString()
};
await state.Download(src);
return src;
2019-11-11 06:15:52 +00:00
}
public static IEnumerable<object[]> BSAs()
{
return _bsaFolder.EnumerateFiles()
.Where(f => Consts.SupportedBSAs.Contains(f.Extension))
2019-11-11 06:15:52 +00:00
.Select(nm => new object[] {nm});
}
[TestMethod]
[DataTestMethod]
[DynamicData(nameof(BSAs), DynamicDataSourceType.Method)]
public async Task BSACompressionRecompression(AbsolutePath bsa)
2019-11-11 06:15:52 +00:00
{
TestContext.WriteLine($"From {bsa}");
TestContext.WriteLine("Cleaning Output Dir");
_tempDir.DeleteDirectory();
_tempDir.CreateDirectory();
2019-11-11 06:15:52 +00:00
TestContext.WriteLine($"Reading {bsa}");
var tempFile = ((RelativePath)"tmp.bsa").RelativeToEntryPoint();
var size = bsa.Size;
2019-11-16 00:01:37 +00:00
using (var a = BSADispatch.OpenRead(bsa))
2019-11-11 06:15:52 +00:00
{
await a.Files.PMap(Queue, file =>
2019-11-11 06:15:52 +00:00
{
var absName = _tempDir.Combine(file.Path);
2019-11-11 06:15:52 +00:00
ViaJson(file.State);
absName.Parent.CreateDirectory();
using (var fs = absName.Create())
2019-11-11 06:15:52 +00:00
{
2019-11-16 00:01:37 +00:00
file.CopyDataTo(fs);
2019-11-11 06:15:52 +00:00
}
Assert.AreEqual(file.Size, absName.Size);
2019-11-11 06:15:52 +00:00
});
Console.WriteLine($"Building {bsa}");
2020-03-09 20:38:35 +00:00
using (var w = ViaJson(a.State).MakeBuilder(size))
2019-11-11 06:15:52 +00:00
{
var streams = await a.Files.PMap(Queue, file =>
2019-11-11 06:15:52 +00:00
{
var absPath = _tempDir.Combine(file.Path);
var str = absPath.OpenRead();
w.AddFile(ViaJson(file.State), str);
return str;
2019-11-11 06:15:52 +00:00
});
2019-11-21 15:41:46 +00:00
w.Build(tempFile);
streams.Do(s => s.Dispose());
2019-11-11 06:15:52 +00:00
}
Console.WriteLine($"Verifying {bsa}");
2019-11-21 15:41:46 +00:00
using (var b = BSADispatch.OpenRead(tempFile))
2019-11-11 06:15:52 +00:00
{
Console.WriteLine($"Performing A/B tests on {bsa}");
Assert.AreEqual(JsonConvert.SerializeObject(a.State), JsonConvert.SerializeObject(b.State));
// Check same number of files
Assert.AreEqual(a.Files.Count(), b.Files.Count());
var idx = 0;
await a.Files.Zip(b.Files, (ai, bi) => (ai, bi))
2019-11-17 04:16:42 +00:00
.PMap(Queue, pair =>
{
idx++;
Assert.AreEqual(JsonConvert.SerializeObject(pair.ai.State),
JsonConvert.SerializeObject(pair.bi.State));
//Console.WriteLine($" - {pair.ai.Path}");
Assert.AreEqual(pair.ai.Path, pair.bi.Path);
//Equal(pair.ai.Compressed, pair.bi.Compressed);
Assert.AreEqual(pair.ai.Size, pair.bi.Size);
CollectionAssert.AreEqual(GetData(pair.ai), GetData(pair.bi), $"{pair.ai.Path} {JsonConvert.SerializeObject(pair.ai.State)}");
});
2019-11-11 06:15:52 +00:00
}
}
}
2019-11-16 00:01:37 +00:00
private static byte[] GetData(IFile pairAi)
2019-11-11 06:15:52 +00:00
{
using (var ms = new MemoryStream())
{
2019-11-16 00:01:37 +00:00
pairAi.CopyDataTo(ms);
2019-11-11 06:15:52 +00:00
return ms.ToArray();
}
}
public static T ViaJson<T>(T i)
{
var settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
};
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(i, settings), settings);
}
}
}