wabbajack/Wabbajack.VirtualFileSystem.Test/FileExtractorTests.cs
2020-09-10 19:22:07 -06:00

166 lines
5.4 KiB
C#

using System;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
using Wabbajack.Common;
using Wabbajack.Lib.Downloaders;
using Wabbajack.Lib.NexusApi;
using Xunit;
using Xunit.Abstractions;
namespace Wabbajack.VirtualFileSystem.Test
{
public class FileExtractorTests : IAsyncLifetime
{
private ITestOutputHelper _helper;
private IDisposable _unsub;
public FileExtractorTests(ITestOutputHelper helper)
{
_helper = helper;
_unsub = Utils.LogMessages.Subscribe(f =>
{
try
{
_helper.WriteLine(f.ShortDescription);
}
catch (Exception _)
{
// ignored
}
});
}
public async Task InitializeAsync()
{
}
public async Task DisposeAsync()
{
_unsub.Dispose();
}
[Fact]
public async Task CanGatherDataFromZipFiles()
{
await using var temp = await TempFolder.Create();
await using var archive = new TempFile();
for (int i = 0; i < 10; i ++)
{
await WriteRandomData(temp.Dir.Combine($"{i}.bin"), _rng.Next(10, 1024));
}
await ZipUpFolder(temp.Dir, archive.Path, false);
var results = await FileExtractor2.GatheringExtract(new NativeFileStreamFactory(archive.Path),
_ => true,
async (path, sfn) =>
{
await using var s = await sfn.GetStream();
return await s.xxHashAsync();
});
Assert.Equal(10, results.Count);
foreach (var (path, hash) in results)
{
Assert.Equal(await temp.Dir.Combine(path).FileHashAsync(), hash);
}
}
[Fact]
public async Task CanExtractEmptyFiles()
{
await using var temp = await TempFolder.Create();
await using var archive = new TempFile();
for (int i = 0; i < 1; i ++)
{
await WriteRandomData(temp.Dir.Combine($"{i}.bin"), _rng.Next(10, 1024));
}
await (await temp.Dir.Combine("empty.txt").Create()).DisposeAsync();
await ZipUpFolder(temp.Dir, archive.Path, false);
var results = await FileExtractor2.GatheringExtract(new NativeFileStreamFactory(archive.Path),
_ => true,
async (path, sfn) =>
{
await using var s = await sfn.GetStream();
return await s.xxHashAsync();
});
Assert.Equal(2, results.Count);
foreach (var (path, hash) in results)
{
Assert.Equal(await temp.Dir.Combine(path).FileHashAsync(), hash);
}
}
private static Extension OMODExtension = new Extension(".omod");
private static Extension CRCExtension = new Extension(".crc");
[Fact]
public async Task CanGatherDataFromOMODFiles()
{
var src = await DownloadMod(Game.Oblivion, 18498);
await FileExtractor2.GatheringExtract(new NativeFileStreamFactory(src),
p => p.Extension == OMODExtension, async (path, sfn) =>
{
await FileExtractor2.GatheringExtract(sfn, _ => true, async (ipath, isfn) => {
// We shouldn't have any .crc files because this file should be recognized as a OMOD and extracted correctly
Assert.NotEqual(CRCExtension, ipath.Extension);
return 0;
});
return 0;
});
}
private static readonly Random _rng = new Random();
private static async Task WriteRandomData(AbsolutePath path, int size)
{
var buff = new byte[size];
_rng.NextBytes(buff);
await path.WriteAllBytesAsync(buff);
}
private static async Task AddFile(AbsolutePath filename, string text)
{
filename.Parent.CreateDirectory();
await filename.WriteAllTextAsync(text);
}
private static async Task ZipUpFolder(AbsolutePath folder, AbsolutePath output, bool deleteSource = true)
{
ZipFile.CreateFromDirectory((string)folder, (string)output);
if (deleteSource)
await folder.DeleteDirectory();
}
private static AbsolutePath _stagingFolder = ((RelativePath)"NexusDownloads").RelativeToEntryPoint();
private static async Task<AbsolutePath> DownloadMod(Game game, int mod)
{
using var client = await NexusApiClient.Get();
var results = await client.GetModFiles(game, mod);
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 = mod,
Game = game,
FileID = file.file_id
};
await state.Download(src);
return src;
}
}
}