2020-09-04 21:00:29 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.IO.Compression;
|
2020-09-08 22:15:33 +00:00
|
|
|
|
using System.Linq;
|
2020-09-04 21:00:29 +00:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Wabbajack.Common;
|
2020-09-08 22:15:33 +00:00
|
|
|
|
using Wabbajack.Lib.Downloaders;
|
|
|
|
|
using Wabbajack.Lib.NexusApi;
|
2020-09-04 21:00:29 +00:00
|
|
|
|
using Xunit;
|
2020-09-09 02:34:53 +00:00
|
|
|
|
using Xunit.Abstractions;
|
2020-09-04 21:00:29 +00:00
|
|
|
|
|
|
|
|
|
namespace Wabbajack.VirtualFileSystem.Test
|
|
|
|
|
{
|
2020-09-09 02:34:53 +00:00
|
|
|
|
public class FileExtractorTests : IAsyncLifetime
|
2020-09-04 21:00:29 +00:00
|
|
|
|
{
|
2020-09-09 02:34:53 +00:00
|
|
|
|
private ITestOutputHelper _helper;
|
|
|
|
|
private IDisposable _unsub;
|
|
|
|
|
|
|
|
|
|
public FileExtractorTests(ITestOutputHelper helper)
|
|
|
|
|
{
|
|
|
|
|
_helper = helper;
|
2020-09-09 04:06:15 +00:00
|
|
|
|
_unsub = Utils.LogMessages.Subscribe(f =>
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_helper.WriteLine(f.ShortDescription);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception _)
|
|
|
|
|
{
|
|
|
|
|
// ignored
|
|
|
|
|
}
|
|
|
|
|
});
|
2020-09-09 02:34:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task InitializeAsync()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task DisposeAsync()
|
|
|
|
|
{
|
|
|
|
|
_unsub.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-04 21:00:29 +00:00
|
|
|
|
[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) =>
|
2020-09-11 01:22:07 +00:00
|
|
|
|
{
|
|
|
|
|
await using var s = await sfn.GetStream();
|
|
|
|
|
return await s.xxHashAsync();
|
|
|
|
|
});
|
2020-09-04 21:00:29 +00:00
|
|
|
|
|
|
|
|
|
Assert.Equal(10, results.Count);
|
|
|
|
|
foreach (var (path, hash) in results)
|
|
|
|
|
{
|
|
|
|
|
Assert.Equal(await temp.Dir.Combine(path).FileHashAsync(), hash);
|
|
|
|
|
}
|
2020-09-08 22:15:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-11 01:22:07 +00:00
|
|
|
|
[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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-08 22:15:33 +00:00
|
|
|
|
private static Extension OMODExtension = new Extension(".omod");
|
|
|
|
|
private static Extension CRCExtension = new Extension(".crc");
|
2020-09-04 21:00:29 +00:00
|
|
|
|
|
2020-09-08 22:15:33 +00:00
|
|
|
|
[Fact]
|
|
|
|
|
public async Task CanGatherDataFromOMODFiles()
|
|
|
|
|
{
|
|
|
|
|
var src = await DownloadMod(Game.Oblivion, 18498);
|
2020-09-04 21:00:29 +00:00
|
|
|
|
|
2020-09-08 22:15:33 +00:00
|
|
|
|
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;
|
|
|
|
|
});
|
2020-09-04 21:00:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-08 22:15:33 +00:00
|
|
|
|
|
|
|
|
|
private static AbsolutePath _stagingFolder = ((RelativePath)"NexusDownloads").RelativeToEntryPoint();
|
2020-09-09 02:34:53 +00:00
|
|
|
|
|
2020-09-08 22:15:33 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-04 21:00:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|