mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Moved Wabbajack.Commons tests into Wabbajack.Commons.Test out of Wabbajack.Test. They all pass
This commit is contained in:
parent
006b045348
commit
51bad949ec
@ -20,10 +20,10 @@ namespace Compression.BSA.Test
|
||||
[TestClass]
|
||||
public class BSATests
|
||||
{
|
||||
private static string _stagingFolder = "NexusDownloads";
|
||||
private static string _bsaFolder = "BSAs";
|
||||
private static string _testDir = "BSA Test Dir";
|
||||
private static string _tempDir = "BSA Temp Dir";
|
||||
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();
|
||||
|
||||
public TestContext TestContext { get; set; }
|
||||
|
||||
@ -34,11 +34,8 @@ namespace Compression.BSA.Test
|
||||
{
|
||||
Queue = new WorkQueue();
|
||||
Utils.LogMessages.Subscribe(f => testContext.WriteLine(f.ShortDescription));
|
||||
if (!Directory.Exists(_stagingFolder))
|
||||
Directory.CreateDirectory(_stagingFolder);
|
||||
|
||||
if (!Directory.Exists(_bsaFolder))
|
||||
Directory.CreateDirectory(_bsaFolder);
|
||||
_stagingFolder.DeleteDirectory();
|
||||
_bsaFolder.DeleteDirectory();
|
||||
|
||||
var modIDs = new[]
|
||||
{
|
||||
@ -53,22 +50,21 @@ namespace Compression.BSA.Test
|
||||
await Task.WhenAll(modIDs.Select(async (info) =>
|
||||
{
|
||||
var filename = await DownloadMod(info);
|
||||
var folder = Path.Combine(_bsaFolder, info.Item1.ToString(), info.Item2.ToString());
|
||||
if (!Directory.Exists(folder))
|
||||
Directory.CreateDirectory(folder);
|
||||
var folder = _bsaFolder.Combine(info.Item1.ToString(), info.Item2.ToString());
|
||||
folder.CreateDirectory();
|
||||
await FileExtractor.ExtractAll(Queue, filename, folder);
|
||||
}));
|
||||
}
|
||||
|
||||
private static async Task<string> DownloadMod((Game, int) info)
|
||||
private static async Task<AbsolutePath> DownloadMod((Game, int) info)
|
||||
{
|
||||
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 = Path.Combine(_stagingFolder, file.file_name);
|
||||
var src = _stagingFolder.Combine(file.file_name);
|
||||
|
||||
if (File.Exists(src)) return src;
|
||||
if (src.Exists) return src;
|
||||
|
||||
var state = new NexusDownloader.State
|
||||
{
|
||||
@ -82,41 +78,38 @@ namespace Compression.BSA.Test
|
||||
|
||||
public static IEnumerable<object[]> BSAs()
|
||||
{
|
||||
return Directory.EnumerateFiles(_bsaFolder, "*", DirectoryEnumerationOptions.Recursive)
|
||||
.Where(f => Consts.SupportedBSAs.Contains(Path.GetExtension(f)))
|
||||
return _bsaFolder.EnumerateFiles()
|
||||
.Where(f => Consts.SupportedBSAs.Contains(f.Extension))
|
||||
.Select(nm => new object[] {nm});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(BSAs), DynamicDataSourceType.Method)]
|
||||
public async Task BSACompressionRecompression(string bsa)
|
||||
public async Task BSACompressionRecompression(AbsolutePath bsa)
|
||||
{
|
||||
TestContext.WriteLine($"From {bsa}");
|
||||
TestContext.WriteLine("Cleaning Output Dir");
|
||||
if (Directory.Exists(_tempDir)) Utils.DeleteDirectory(_tempDir);
|
||||
Directory.CreateDirectory(_tempDir);
|
||||
|
||||
_tempDir.DeleteDirectory();
|
||||
_tempDir.CreateDirectory();
|
||||
|
||||
TestContext.WriteLine($"Reading {bsa}");
|
||||
string tempFile = Path.Combine("tmp.bsa");
|
||||
var size = File.GetSize(bsa);
|
||||
var tempFile = ((RelativePath)"tmp.bsa").RelativeToEntryPoint();
|
||||
var size = bsa.Size;
|
||||
using (var a = BSADispatch.OpenRead(bsa))
|
||||
{
|
||||
await a.Files.PMap(Queue, file =>
|
||||
{
|
||||
var absName = Path.Combine(_tempDir, file.Path);
|
||||
var absName = _tempDir.Combine(file.Path);
|
||||
ViaJson(file.State);
|
||||
|
||||
if (!Directory.Exists(Path.GetDirectoryName(absName)))
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(absName));
|
||||
|
||||
|
||||
using (var fs = File.Open(absName, FileMode.Create))
|
||||
absName.Parent.CreateDirectory();
|
||||
using (var fs = absName.Create())
|
||||
{
|
||||
file.CopyDataTo(fs);
|
||||
}
|
||||
|
||||
Assert.AreEqual(file.Size, new FileInfo(absName).Length);
|
||||
Assert.AreEqual(file.Size, absName.Size);
|
||||
});
|
||||
|
||||
Console.WriteLine($"Building {bsa}");
|
||||
@ -125,8 +118,8 @@ namespace Compression.BSA.Test
|
||||
{
|
||||
var streams = await a.Files.PMap(Queue, file =>
|
||||
{
|
||||
var absPath = Path.Combine(_tempDir, file.Path);
|
||||
var str = File.OpenRead(absPath);
|
||||
var absPath = _tempDir.Combine(file.Path);
|
||||
var str = absPath.OpenRead();
|
||||
w.AddFile(ViaJson(file.State), str);
|
||||
return str;
|
||||
});
|
||||
|
@ -1,17 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Wabbajack.Common;
|
||||
using Xunit;
|
||||
|
||||
namespace Wabbajack.Test
|
||||
namespace Wabbajack.Common.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class AsyncLockTests
|
||||
{
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public async Task Typical()
|
||||
{
|
||||
var asyncLock = new AsyncLock();
|
||||
@ -29,20 +24,20 @@ namespace Wabbajack.Test
|
||||
await Task.Delay(200);
|
||||
using (await asyncLock.Wait())
|
||||
{
|
||||
Assert.IsTrue(firstRun);
|
||||
Assert.True(firstRun);
|
||||
}
|
||||
});
|
||||
await Task.WhenAll(first, second);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public async Task Exception()
|
||||
{
|
||||
var asyncLock = new AsyncLock();
|
||||
bool firstRun = false;
|
||||
bool secondRun = false;
|
||||
// Throw exception inside a lock
|
||||
await Assert.ThrowsExceptionAsync<Exception>(() =>
|
||||
await Assert.ThrowsAsync<Exception>(() =>
|
||||
{
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
@ -62,7 +57,7 @@ namespace Wabbajack.Test
|
||||
await Task.Delay(200);
|
||||
using (await asyncLock.Wait())
|
||||
{
|
||||
Assert.IsTrue(firstRun);
|
||||
Assert.True(firstRun);
|
||||
secondRun = true;
|
||||
}
|
||||
}),
|
@ -1,18 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Wabbajack.Common;
|
||||
using Xunit;
|
||||
|
||||
namespace Wabbajack.Test
|
||||
namespace Wabbajack.Common.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class EncryptedDataTests
|
||||
{
|
||||
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public async Task CanDetectNewEncryptedData()
|
||||
{
|
||||
var test_string = Guid.NewGuid().ToString();
|
||||
@ -28,7 +24,7 @@ namespace Wabbajack.Test
|
||||
test_string.ToEcryptedJson(test_string);
|
||||
await Task.Delay(100);
|
||||
|
||||
CollectionAssert.Contains(data, test_string);
|
||||
Assert.Contains(test_string, data);
|
||||
|
||||
|
||||
}
|
@ -1,18 +1,17 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Xunit;
|
||||
|
||||
namespace Wabbajack.Test
|
||||
namespace Wabbajack.Common.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpClientTests
|
||||
{
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public async Task DoesntReuseHttpMessages()
|
||||
{
|
||||
var client = new Common.Http.Client();
|
||||
// If we reuse the HTTP message this will throw a invalid operation exception
|
||||
await Assert.ThrowsExceptionAsync<HttpRequestException>(async () => await client.GetAsync("http://blerg.blaz.bloz.buz"));
|
||||
await Assert.ThrowsAsync<HttpRequestException>(async () => await client.GetAsync("http://blerg.blaz.bloz.buz"));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,25 +1,23 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Wabbajack.Common;
|
||||
using Xunit;
|
||||
|
||||
namespace Wabbajack.Test
|
||||
namespace Wabbajack.Common.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class IniTests
|
||||
{
|
||||
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void TestByteArrayParsing()
|
||||
{
|
||||
Assert.AreEqual("bar", @"[General]
|
||||
Assert.Equal("bar", @"[General]
|
||||
foo = bar".LoadIniString().General.foo);
|
||||
|
||||
Assert.AreEqual("baz\\bar", @"[General]
|
||||
Assert.Equal("baz\\bar", @"[General]
|
||||
foo = baz\\bar".LoadIniString().General.foo);
|
||||
|
||||
Assert.AreEqual("bar", @"[General]
|
||||
Assert.Equal("bar", @"[General]
|
||||
foo = @ByteArray(bar)".LoadIniString().General.foo);
|
||||
|
||||
Assert.AreEqual("foo\\h̴̹͚̎é̶̘͙̐l̶͕̔͑p̴̯̋͂m̶̞̮͘͠e̸͉͙͆̄\\baz", @"[General]
|
||||
Assert.Equal("foo\\h̴̹͚̎é̶̘͙̐l̶͕̔͑p̴̯̋͂m̶̞̮͘͠e̸͉͙͆̄\\baz", @"[General]
|
||||
foo = @ByteArray(foo\\\x68\xcc\xb4\xcc\x8e\xcc\xb9\xcd\x9a\x65\xcc\xb6\xcd\x81\xcc\x90\xcc\x98\xcd\x99\x6c\xcc\xb6\xcc\x94\xcd\x91\xcd\x95\x70\xcc\xb4\xcc\x8b\xcd\x82\xcc\xaf\x6d\xcc\xb6\xcd\x98\xcd\xa0\xcc\x9e\xcc\xae\x65\xcc\xb8\xcd\x86\xcc\x84\xcd\x89\xcd\x99\\baz)".LoadIniString().General.foo);
|
||||
}
|
||||
|
31
Wabbajack.Common.Test/MiscTests.cs
Normal file
31
Wabbajack.Common.Test/MiscTests.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System.Threading.Tasks;
|
||||
using Alphaleonis.Win32.Filesystem;
|
||||
using Xunit;
|
||||
|
||||
namespace Wabbajack.Common.Test
|
||||
{
|
||||
public class MiscTests
|
||||
{
|
||||
[Fact]
|
||||
public void TestDiskSpeed()
|
||||
{
|
||||
using (var queue = new WorkQueue())
|
||||
{
|
||||
var speed = Utils.TestDiskSpeed(queue, @".\");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestHash()
|
||||
{
|
||||
var testFile = ((RelativePath)"text.data").RelativeToEntryPoint();
|
||||
const string data = "Cheese for Everyone!";
|
||||
await testFile.WriteAllTextAsync(data);
|
||||
File.WriteAllText("test.data", data);
|
||||
Assert.Equal(Hash.FromBase64("eSIyd+KOG3s="), testFile.FileHashCached());
|
||||
Assert.True(Utils.TryGetHashCache(testFile, out var fileHash));
|
||||
Assert.Equal(Hash.FromBase64("eSIyd+KOG3s="), fileHash);
|
||||
Assert.NotEqual("eSIyd+KOG3s=", await testFile.WithExtension(Consts.HashFileExtension).ReadAllTextAsync());
|
||||
}
|
||||
}
|
||||
}
|
206
Wabbajack.Common.Test/PMapTests.cs
Normal file
206
Wabbajack.Common.Test/PMapTests.cs
Normal file
@ -0,0 +1,206 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Wabbajack.Common.Test
|
||||
{
|
||||
public class PMapTests
|
||||
{
|
||||
const int TypicalThreadCount = 6;
|
||||
const int TypicalDelayMS = 50;
|
||||
const int TimeoutSeconds = 15;
|
||||
|
||||
[Fact]
|
||||
public async Task Typical_Action()
|
||||
{
|
||||
using var queue = new WorkQueue(TypicalThreadCount);
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var output = new List<int>();
|
||||
var workTask = Utils.PMap(Enumerable.Range(0, TypicalThreadCount * 2), queue, (item) =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
Thread.Sleep(TypicalDelayMS);
|
||||
lock (output)
|
||||
{
|
||||
output.Add(item);
|
||||
}
|
||||
});
|
||||
await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.True(input.SequenceEqual(output.OrderBy(i => i)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Typical_Func()
|
||||
{
|
||||
using var queue = new WorkQueue(TypicalThreadCount);
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var workTask = Utils.PMap(Enumerable.Range(0, TypicalThreadCount * 2), queue, (item) =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
Thread.Sleep(TypicalDelayMS);
|
||||
return item.ToString();
|
||||
});
|
||||
var results = await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.True(input.Select(i => i.ToString()).SequenceEqual(results));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Typical_Task()
|
||||
{
|
||||
using var queue = new WorkQueue(TypicalThreadCount);
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var output = new List<int>();
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
await Task.Delay(TypicalDelayMS);
|
||||
lock (output)
|
||||
{
|
||||
output.Add(item);
|
||||
}
|
||||
});
|
||||
await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.True(input.SequenceEqual(output.OrderBy(i => i)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Typical_TaskReturn()
|
||||
{
|
||||
using var queue = new WorkQueue(TypicalThreadCount);
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
await Task.Delay(TypicalDelayMS);
|
||||
return item.ToString();
|
||||
});
|
||||
var results = await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.True(input.Select(i => i.ToString()).SequenceEqual(results));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NestedAction()
|
||||
{
|
||||
using var queue = new WorkQueue(TypicalThreadCount);
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var inputConstructedResults = input.SelectMany(i => Enumerable.Range(i * 100, TypicalThreadCount * 2));
|
||||
var output = new List<int>();
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
await Enumerable.Range(item * 100, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (subItem) =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
Thread.Sleep(TypicalDelayMS);
|
||||
lock (output)
|
||||
{
|
||||
output.Add(subItem);
|
||||
}
|
||||
});
|
||||
});
|
||||
await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.True(inputConstructedResults.SequenceEqual(output.OrderBy(i => i)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Nested_Func()
|
||||
{
|
||||
using var queue = new WorkQueue(TypicalThreadCount);
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var inputConstructedResults = input.SelectMany(i => Enumerable.Range(i * 100, TypicalThreadCount * 2));
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
return await Utils.PMap(Enumerable.Range(item * 100, TypicalThreadCount * 2), queue, (subItem) =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
Thread.Sleep(TypicalDelayMS);
|
||||
return subItem;
|
||||
});
|
||||
});
|
||||
var results = await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.True(inputConstructedResults.SequenceEqual(results.SelectMany(i => i)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Nested_Task()
|
||||
{
|
||||
using var queue = new WorkQueue(TypicalThreadCount);
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var inputConstructedResults = input.SelectMany(i => Enumerable.Range(i * 100, TypicalThreadCount * 2));
|
||||
var output = new List<int>();
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
await Enumerable.Range(item * 100, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (subItem) =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
await Task.Delay(TypicalDelayMS);
|
||||
lock (output)
|
||||
{
|
||||
output.Add(subItem);
|
||||
}
|
||||
});
|
||||
});
|
||||
await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.True(inputConstructedResults.SequenceEqual(output.OrderBy(i => i)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Nested_TaskReturn()
|
||||
{
|
||||
using var queue = new WorkQueue(TypicalThreadCount);
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var inputConstructedResults = input.SelectMany(i => Enumerable.Range(i * 100, TypicalThreadCount * 2));
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
return await Enumerable.Range(item * 100, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (subItem) =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
await Task.Delay(TypicalDelayMS);
|
||||
return subItem;
|
||||
});
|
||||
});
|
||||
var results = await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.True(inputConstructedResults.SequenceEqual(results.SelectMany(i => i)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Nested_BackgroundThreadsInvolved()
|
||||
{
|
||||
using var queue = new WorkQueue(TypicalThreadCount);
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var inputConstructedResults = input.SelectMany(i => Enumerable.Range(i * 100, TypicalThreadCount * 2));
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
return await Enumerable.Range(item * 100, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (subItem) =>
|
||||
{
|
||||
return await Task.Run(async () =>
|
||||
{
|
||||
Assert.True(WorkQueue.WorkerThread);
|
||||
await Task.Delay(TypicalDelayMS);
|
||||
return subItem;
|
||||
});
|
||||
});
|
||||
});
|
||||
var results = await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.True(inputConstructedResults.SequenceEqual(results.SelectMany(i => i)));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Xunit;
|
||||
|
||||
namespace Wabbajack.Test
|
||||
namespace Wabbajack.Common.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class TaskExtTests
|
||||
{
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public async Task TimeoutButContinue_Typical()
|
||||
{
|
||||
bool timedOut = false;
|
||||
await Task.Delay(100).TimeoutButContinue(TimeSpan.FromSeconds(1), () => timedOut = true);
|
||||
Assert.IsFalse(timedOut);
|
||||
Assert.False(timedOut);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public async Task TimeoutButContinue_TimedOut()
|
||||
{
|
||||
bool timedOut = false;
|
||||
await Task.Delay(300).TimeoutButContinue(TimeSpan.FromMilliseconds(100), () => timedOut = true);
|
||||
Assert.IsTrue(timedOut);
|
||||
Assert.True(timedOut);
|
||||
}
|
||||
}
|
||||
}
|
24
Wabbajack.Common.Test/TestUtils.cs
Normal file
24
Wabbajack.Common.Test/TestUtils.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace Wabbajack.Common.Test
|
||||
{
|
||||
public static class TestUtils
|
||||
{
|
||||
private static Random _random = new Random();
|
||||
|
||||
public static byte[] RandomData(int? size = null, int maxSize = 1024)
|
||||
{
|
||||
if (size == null)
|
||||
size = _random.Next(1, maxSize);
|
||||
var arr = new byte[(int) size];
|
||||
_random.NextBytes(arr);
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static object RandomOne(params object[] opts)
|
||||
{
|
||||
return opts[_random.Next(0, opts.Length)];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -2,33 +2,29 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Wabbajack.Common;
|
||||
using Xunit;
|
||||
|
||||
namespace Wabbajack.Test
|
||||
namespace Wabbajack.Common.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class UtilsTests
|
||||
{
|
||||
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void IsInPathTests()
|
||||
{
|
||||
Assert.IsTrue("c:\\foo\\bar.exe".IsInPath("c:\\foo"));
|
||||
Assert.IsFalse("c:\\foo\\bar.exe".IsInPath("c:\\fo"));
|
||||
Assert.IsTrue("c:\\Foo\\bar.exe".IsInPath("c:\\foo"));
|
||||
Assert.IsTrue("c:\\foo\\bar.exe".IsInPath("c:\\Foo"));
|
||||
Assert.IsTrue("c:\\foo\\bar.exe".IsInPath("c:\\fOo"));
|
||||
Assert.IsTrue("c:\\foo\\bar.exe".IsInPath("c:\\foo\\"));
|
||||
Assert.IsTrue("c:\\foo\\bar\\".IsInPath("c:\\foo\\"));
|
||||
Assert.True("c:\\foo\\bar.exe".IsInPath("c:\\foo"));
|
||||
Assert.False("c:\\foo\\bar.exe".IsInPath("c:\\fo"));
|
||||
Assert.True("c:\\Foo\\bar.exe".IsInPath("c:\\foo"));
|
||||
Assert.True("c:\\foo\\bar.exe".IsInPath("c:\\Foo"));
|
||||
Assert.True("c:\\foo\\bar.exe".IsInPath("c:\\fOo"));
|
||||
Assert.True("c:\\foo\\bar.exe".IsInPath("c:\\foo\\"));
|
||||
Assert.True("c:\\foo\\bar\\".IsInPath("c:\\foo\\"));
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
[DataTestMethod]
|
||||
[DynamicData(nameof(PatchData), DynamicDataSourceType.Method)]
|
||||
[Theory]
|
||||
[ClassData(typeof(PatchData))]
|
||||
public async Task DiffCreateAndApply(byte[] src, byte[] dest, DiffMethod method)
|
||||
{
|
||||
await using var ms = new MemoryStream();
|
||||
@ -51,7 +47,7 @@ namespace Wabbajack.Test
|
||||
var patch = ms.ToArray();
|
||||
await using var resultStream = new MemoryStream();
|
||||
Utils.ApplyPatch(new MemoryStream(src), () => new MemoryStream(patch), resultStream);
|
||||
CollectionAssert.AreEqual(dest, resultStream.ToArray());
|
||||
Assert.Equal(dest, resultStream.ToArray());
|
||||
}
|
||||
|
||||
|
||||
@ -61,10 +57,18 @@ namespace Wabbajack.Test
|
||||
BSDiff,
|
||||
OctoDiff
|
||||
}
|
||||
public static IEnumerable<object[]> PatchData()
|
||||
public class PatchData : TheoryData<byte[], byte[], DiffMethod>
|
||||
{
|
||||
var maxSize = 1024 * 1024 * 8;
|
||||
return Enumerable.Range(0, 10).Select(x => new[] {TestUtils.RandomData(maxSize:maxSize), TestUtils.RandomData(maxSize:maxSize), TestUtils.RandomeOne(DiffMethod.Default, DiffMethod.OctoDiff, DiffMethod.BSDiff)});
|
||||
public PatchData()
|
||||
{
|
||||
var maxSize = 64;
|
||||
Enumerable.Range(0, 10).Do(x =>
|
||||
|
||||
{
|
||||
Add(TestUtils.RandomData(maxSize: maxSize), TestUtils.RandomData(maxSize: maxSize),
|
||||
(DiffMethod)TestUtils.RandomOne(DiffMethod.Default, DiffMethod.OctoDiff, DiffMethod.BSDiff));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
20
Wabbajack.Common.Test/Wabbajack.Common.Test.csproj
Normal file
20
Wabbajack.Common.Test/Wabbajack.Common.Test.csproj
Normal file
@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Wabbajack.Common\Wabbajack.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,17 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Wabbajack.Common;
|
||||
using Xunit;
|
||||
|
||||
namespace Wabbajack.Test
|
||||
namespace Wabbajack.Common.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class WorkQueueTests
|
||||
{
|
||||
#region DynamicNumThreads
|
||||
@ -20,144 +16,144 @@ namespace Wabbajack.Test
|
||||
const int Small = 4;
|
||||
public TimeSpan PollMS => TimeSpan.FromSeconds(1);
|
||||
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void DynamicNumThreads_Typical()
|
||||
{
|
||||
using (var queue = new WorkQueue())
|
||||
{
|
||||
Assert.AreEqual(Environment.ProcessorCount, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Environment.ProcessorCount, queue._tasks.Count);
|
||||
Assert.Equal(Environment.ProcessorCount, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Environment.ProcessorCount, queue._tasks.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void DynamicNumThreads_Increased()
|
||||
{
|
||||
var subj = new BehaviorSubject<int>(Small);
|
||||
using (var queue = new WorkQueue(subj))
|
||||
{
|
||||
Assert.AreEqual(Small, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Small, queue._tasks.Count);
|
||||
Assert.Equal(Small, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Small, queue._tasks.Count);
|
||||
subj.OnNext(Large);
|
||||
Assert.AreEqual(Large, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public void DynamicNumThreads_EmptyObs()
|
||||
{
|
||||
using (var queue = new WorkQueue(Observable.Empty<int>()))
|
||||
{
|
||||
Assert.AreEqual(0, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(0, queue._tasks.Count);
|
||||
Assert.Equal(0, queue.DesiredNumWorkers);
|
||||
Assert.Equal(0, queue._tasks.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public async Task DynamicNumThreads_Decreased()
|
||||
{
|
||||
var subj = new BehaviorSubject<int>(Large);
|
||||
using (var queue = new WorkQueue(subj))
|
||||
{
|
||||
Assert.AreEqual(Large, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
subj.OnNext(Small);
|
||||
Assert.AreEqual(Small, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Small, queue.DesiredNumWorkers);
|
||||
// Tasks don't go down immediately
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
// After things re-poll, they should be cleaned
|
||||
await Task.Delay(PollMS * 2);
|
||||
Assert.AreEqual(Small, queue._tasks.Count);
|
||||
Assert.Equal(Small, queue._tasks.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public async Task DynamicNumThreads_IncreasedWhileWorking()
|
||||
{
|
||||
var subj = new BehaviorSubject<int>(Small);
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
using (var queue = new WorkQueue(subj))
|
||||
{
|
||||
Assert.AreEqual(Small, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Small, queue._tasks.Count);
|
||||
Assert.Equal(Small, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Small, queue._tasks.Count);
|
||||
Enumerable.Range(0, Small).Do(_ => queue.QueueTask(() => tcs.Task));
|
||||
subj.OnNext(Large);
|
||||
Assert.AreEqual(Large, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
Task.Run(() => tcs.SetResult(true)).FireAndForget();
|
||||
Assert.AreEqual(Large, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
await Task.Delay(PollMS * 2);
|
||||
Assert.AreEqual(Large, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public async Task DynamicNumThreads_DecreasedWhileWorking()
|
||||
{
|
||||
var subj = new BehaviorSubject<int>(Large);
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
using (var queue = new WorkQueue(subj))
|
||||
{
|
||||
Assert.AreEqual(Large, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
Enumerable.Range(0, Large).Do(_ => queue.QueueTask(() => tcs.Task));
|
||||
subj.OnNext(Small);
|
||||
Assert.AreEqual(Small, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Small, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
// After things re-poll, they should still be working at max
|
||||
await Task.Delay(PollMS * 2);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
// Complete, repoll, and check again
|
||||
Task.Run(() => tcs.SetResult(true)).FireAndForget();
|
||||
await Task.Delay(PollMS * 2);
|
||||
Assert.AreEqual(Small, queue._tasks.Count);
|
||||
Assert.Equal(Small, queue._tasks.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public async Task DynamicNumThreads_IncreasedThenDecreased()
|
||||
{
|
||||
var subj = new BehaviorSubject<int>(Small);
|
||||
using (var queue = new WorkQueue(subj))
|
||||
{
|
||||
Assert.AreEqual(Small, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Small, queue._tasks.Count);
|
||||
Assert.Equal(Small, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Small, queue._tasks.Count);
|
||||
subj.OnNext(Large);
|
||||
Assert.AreEqual(Large, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
subj.OnNext(Small);
|
||||
// Still large number of threads, as not immediate
|
||||
Assert.AreEqual(Small, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Small, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
// After things re-poll, they should still be working at max
|
||||
await Task.Delay(PollMS * 2);
|
||||
Assert.AreEqual(Small, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Small, queue._tasks.Count);
|
||||
Assert.Equal(Small, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Small, queue._tasks.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public async Task DynamicNumThreads_DecreasedThenIncreased()
|
||||
{
|
||||
var subj = new BehaviorSubject<int>(Large);
|
||||
using (var queue = new WorkQueue(subj))
|
||||
{
|
||||
Assert.AreEqual(Large, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
subj.OnNext(Small);
|
||||
Assert.AreEqual(Small, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Small, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
subj.OnNext(Large);
|
||||
// New threads allocated immediately
|
||||
Assert.AreEqual(Large, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
// After things re-poll, still here
|
||||
await Task.Delay(PollMS * 2);
|
||||
Assert.AreEqual(Large, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@ -172,7 +168,7 @@ namespace Wabbajack.Test
|
||||
/// The solution to this is just make sure that any work done relating to WorkQueue be done within its own Task.Run() call, so that if it that thread
|
||||
/// "takes over" a workqueue loop, it doesn't matter as it was a threadpool thread anyway.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
[Fact]
|
||||
public async Task Deadlock()
|
||||
{
|
||||
var task = Task.Run(async () =>
|
||||
@ -186,8 +182,8 @@ namespace Wabbajack.Test
|
||||
tcs.SetResult(true);
|
||||
}
|
||||
});
|
||||
var completed = Task.WhenAny(Task.Delay(3000), task);
|
||||
Assert.ReferenceEquals(completed, task);
|
||||
var completed = await Task.WhenAny(Task.Delay(3000), task);
|
||||
Assert.Equal(completed, task);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -218,8 +214,8 @@ namespace Wabbajack.Test
|
||||
object lockObj = new object();
|
||||
using (var queue = new WorkQueue(subj))
|
||||
{
|
||||
Assert.AreEqual(Large, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
|
||||
bool[] workStartedArray = new bool[Large];
|
||||
async Task Job(int num, bool[] b)
|
||||
@ -240,7 +236,7 @@ namespace Wabbajack.Test
|
||||
// Show that all jobs are started
|
||||
lock (lockObj)
|
||||
{
|
||||
Assert.AreEqual(Large, workStartedArray.Where(i => i).Count());
|
||||
Assert.Equal(Large, workStartedArray.Where(i => i).Count());
|
||||
}
|
||||
|
||||
await Task.Delay(15000);
|
||||
@ -251,8 +247,8 @@ namespace Wabbajack.Test
|
||||
// that kicked it off and is in charge of the continuation tasks.
|
||||
// Parallel worker Tasks have now coalesced into a single thread
|
||||
Task.Run(() => tcs.SetResult(true)).FireAndForget();
|
||||
Assert.AreEqual(Large, queue.DesiredNumWorkers);
|
||||
Assert.AreEqual(Large, queue._tasks.Count);
|
||||
Assert.Equal(Large, queue.DesiredNumWorkers);
|
||||
Assert.Equal(Large, queue._tasks.Count);
|
||||
|
||||
await Task.Delay(10000);
|
||||
|
||||
@ -264,7 +260,7 @@ namespace Wabbajack.Test
|
||||
// Show that only one job was started/worked on (by our one coalesced worker thread)
|
||||
lock (lockObj)
|
||||
{
|
||||
Assert.AreEqual(1, secondWorkStartedArray.Where(i => i).Count());
|
||||
Assert.Equal(1, secondWorkStartedArray.Where(i => i).Count());
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ namespace Wabbajack.Common
|
||||
{
|
||||
public class WorkQueue : IDisposable
|
||||
{
|
||||
internal AsyncBlockingCollection<Func<Task>> Queue = new AsyncBlockingCollection<Func<Task>>();
|
||||
internal BlockingCollection<Func<Task>> Queue = new BlockingCollection<Func<Task>>(new ConcurrentStack<Func<Task>>());
|
||||
|
||||
public const int UnassignedCpuId = 0;
|
||||
|
||||
@ -31,7 +31,8 @@ namespace Wabbajack.Common
|
||||
public IObservable<CPUStatus> Status => _Status;
|
||||
|
||||
private int _nextCpuID = 1; // Start at 1, as 0 is "Unassigned"
|
||||
internal Dictionary<int, Task> _tasks = new Dictionary<int, Task>();
|
||||
// Public for testing reasons
|
||||
public Dictionary<int, Task> _tasks = new Dictionary<int, Task>();
|
||||
public int DesiredNumWorkers { get; private set; } = 0;
|
||||
|
||||
private CancellationTokenSource _shutdown = new CancellationTokenSource();
|
||||
@ -50,7 +51,7 @@ namespace Wabbajack.Common
|
||||
|
||||
private readonly Subject<IObservable<int>> _activeNumThreadsObservable = new Subject<IObservable<int>>();
|
||||
|
||||
public TimeSpan PollMS = TimeSpan.FromMilliseconds(200);
|
||||
public const int PollMS = 200;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a WorkQueue with the given number of threads
|
||||
@ -124,7 +125,7 @@ namespace Wabbajack.Common
|
||||
bool got;
|
||||
try
|
||||
{
|
||||
(got, f) = await Queue.TryTake(PollMS, _shutdown.Token);
|
||||
got = Queue.TryTake(out f, PollMS, _shutdown.Token);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
@ -4,7 +4,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Lib;
|
||||
using Wabbajack.Lib.LibCefHelpers;
|
||||
using Wabbajack.Util;
|
||||
|
||||
namespace Wabbajack.Test
|
||||
{
|
||||
|
@ -1,31 +0,0 @@
|
||||
using Alphaleonis.Win32.Filesystem;
|
||||
using Wabbajack.Common;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Utils = Wabbajack.Common.Utils;
|
||||
|
||||
namespace Wabbajack.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class MiscTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestDiskSpeed()
|
||||
{
|
||||
using (var queue = new WorkQueue())
|
||||
{
|
||||
var speed = Utils.TestDiskSpeed(queue, @".\");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestHash()
|
||||
{
|
||||
const string data = "Cheese for Everyone!";
|
||||
File.WriteAllText("test.data", data);
|
||||
Assert.AreEqual("eSIyd+KOG3s=", "test.data".FileHashCached(), "Hash is cached");
|
||||
Assert.IsTrue(Utils.TryGetHashCache("test.data", out var fileHash), "New caching method is invoked");
|
||||
Assert.AreEqual("eSIyd+KOG3s=", fileHash, "The correct hash value is cached");
|
||||
Assert.AreNotEqual("eSIyd+KOG3s=", File.ReadAllText("test.data" + Consts.HashFileExtension), "We don't store the hash in plaintext");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,230 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Wabbajack.Common;
|
||||
|
||||
namespace Wabbajack.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class PMapTests
|
||||
{
|
||||
const int TypicalThreadCount = 6;
|
||||
const int TypicalDelayMS = 50;
|
||||
const int TimeoutSeconds = 15;
|
||||
|
||||
[TestMethod]
|
||||
public async Task Typical_Action()
|
||||
{
|
||||
using (var queue = new WorkQueue(TypicalThreadCount))
|
||||
{
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var output = new List<int>();
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, (item) =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
Thread.Sleep(TypicalDelayMS);
|
||||
lock (output)
|
||||
{
|
||||
output.Add(item);
|
||||
}
|
||||
});
|
||||
await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.IsTrue(input.SequenceEqual(output.OrderBy(i => i)));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Typical_Func()
|
||||
{
|
||||
using (var queue = new WorkQueue(TypicalThreadCount))
|
||||
{
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, (item) =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
Thread.Sleep(TypicalDelayMS);
|
||||
return item.ToString();
|
||||
});
|
||||
var results = await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.IsTrue(input.Select(i => i.ToString()).SequenceEqual(results));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Typical_Task()
|
||||
{
|
||||
using (var queue = new WorkQueue(TypicalThreadCount))
|
||||
{
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var output = new List<int>();
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
await Task.Delay(TypicalDelayMS);
|
||||
lock (output)
|
||||
{
|
||||
output.Add(item);
|
||||
}
|
||||
});
|
||||
await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.IsTrue(input.SequenceEqual(output.OrderBy(i => i)));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Typical_TaskReturn()
|
||||
{
|
||||
using (var queue = new WorkQueue(TypicalThreadCount))
|
||||
{
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
await Task.Delay(TypicalDelayMS);
|
||||
return item.ToString();
|
||||
});
|
||||
var results = await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.IsTrue(input.Select(i => i.ToString()).SequenceEqual(results));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task NestedAction()
|
||||
{
|
||||
using (var queue = new WorkQueue(TypicalThreadCount))
|
||||
{
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var inputConstructedResults = input.SelectMany(i => Enumerable.Range(i * 100, TypicalThreadCount * 2));
|
||||
var output = new List<int>();
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
await Enumerable.Range(item * 100, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (subItem) =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
Thread.Sleep(TypicalDelayMS);
|
||||
lock (output)
|
||||
{
|
||||
output.Add(subItem);
|
||||
}
|
||||
});
|
||||
});
|
||||
await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.IsTrue(inputConstructedResults.SequenceEqual(output.OrderBy(i => i)));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Nested_Func()
|
||||
{
|
||||
using (var queue = new WorkQueue(TypicalThreadCount))
|
||||
{
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var inputConstructedResults = input.SelectMany(i => Enumerable.Range(i * 100, TypicalThreadCount * 2));
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
return await Enumerable.Range(item * 100, TypicalThreadCount * 2)
|
||||
.PMap(queue, (subItem) =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
Thread.Sleep(TypicalDelayMS);
|
||||
return subItem;
|
||||
});
|
||||
});
|
||||
var results = await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.IsTrue(inputConstructedResults.SequenceEqual(results.SelectMany(i => i)));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Nested_Task()
|
||||
{
|
||||
using (var queue = new WorkQueue(TypicalThreadCount))
|
||||
{
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var inputConstructedResults = input.SelectMany(i => Enumerable.Range(i * 100, TypicalThreadCount * 2));
|
||||
var output = new List<int>();
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
await Enumerable.Range(item * 100, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (subItem) =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
await Task.Delay(TypicalDelayMS);
|
||||
lock (output)
|
||||
{
|
||||
output.Add(subItem);
|
||||
}
|
||||
});
|
||||
});
|
||||
await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.IsTrue(inputConstructedResults.SequenceEqual(output.OrderBy(i => i)));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Nested_TaskReturn()
|
||||
{
|
||||
using (var queue = new WorkQueue(TypicalThreadCount))
|
||||
{
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var inputConstructedResults = input.SelectMany(i => Enumerable.Range(i * 100, TypicalThreadCount * 2));
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
return await Enumerable.Range(item * 100, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (subItem) =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
await Task.Delay(TypicalDelayMS);
|
||||
return subItem;
|
||||
});
|
||||
});
|
||||
var results = await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.IsTrue(inputConstructedResults.SequenceEqual(results.SelectMany(i => i)));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Nested_BackgroundThreadsInvolved()
|
||||
{
|
||||
using (var queue = new WorkQueue(TypicalThreadCount))
|
||||
{
|
||||
var input = Enumerable.Range(0, TypicalThreadCount * 2).ToArray();
|
||||
var inputConstructedResults = input.SelectMany(i => Enumerable.Range(i * 100, TypicalThreadCount * 2));
|
||||
var workTask = Enumerable.Range(0, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (item) =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
return await Enumerable.Range(item * 100, TypicalThreadCount * 2)
|
||||
.PMap(queue, async (subItem) =>
|
||||
{
|
||||
return await Task.Run(async () =>
|
||||
{
|
||||
Assert.IsTrue(WorkQueue.WorkerThread);
|
||||
await Task.Delay(TypicalDelayMS);
|
||||
return subItem;
|
||||
});
|
||||
});
|
||||
});
|
||||
var results = await workTask.TimeoutButContinue(TimeSpan.FromSeconds(TimeoutSeconds), () => throw new TimeoutException());
|
||||
Assert.IsTrue(inputConstructedResults.SequenceEqual(results.SelectMany(i => i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Alphaleonis.Win32.Filesystem;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Wabbajack.Common;
|
||||
@ -22,37 +23,37 @@ namespace Wabbajack.Test
|
||||
WorkingDirectory = Path.Combine(Directory.GetCurrentDirectory(), "tmp_data");
|
||||
}
|
||||
|
||||
public string WorkingDirectory { get;}
|
||||
public AbsolutePath WorkingDirectory { get;}
|
||||
public string ID { get; }
|
||||
public Random RNG => _rng;
|
||||
|
||||
public Game Game { get; set; }
|
||||
|
||||
public string TestFolder => Path.Combine(WorkingDirectory, ID);
|
||||
public string GameFolder => Path.Combine(WorkingDirectory, ID, "game_folder");
|
||||
public AbsolutePath TestFolder => WorkingDirectory.Combine(ID);
|
||||
public AbsolutePath GameFolder => WorkingDirectory.Combine(ID, "game_folder");
|
||||
|
||||
public string MO2Folder => Path.Combine(WorkingDirectory, ID, "mo2_folder");
|
||||
public string ModsFolder => Path.Combine(MO2Folder, Consts.MO2ModFolderName);
|
||||
public string DownloadsFolder => Path.Combine(MO2Folder, "downloads");
|
||||
public AbsolutePath MO2Folder => WorkingDirectory.Combine(ID, "mo2_folder");
|
||||
public AbsolutePath ModsFolder => MO2Folder.Combine(Consts.MO2ModFolderName);
|
||||
public AbsolutePath DownloadsFolder => MO2Folder.Combine("downloads");
|
||||
|
||||
public string InstallFolder => Path.Combine(TestFolder, "installed");
|
||||
public AbsolutePath InstallFolder => TestFolder.Combine("installed");
|
||||
|
||||
public HashSet<string> Profiles = new HashSet<string>();
|
||||
|
||||
public List<string> Mods = new List<string>();
|
||||
|
||||
public void Configure()
|
||||
public async Task Configure()
|
||||
{
|
||||
File.WriteAllLines(Path.Combine(MO2Folder, "ModOrganizer.ini"), new []
|
||||
await MO2Folder.Combine("ModOrganizer.ini").WriteAllLinesAsync(new []
|
||||
{
|
||||
"[General]",
|
||||
$"gameName={Game.MetaData().MO2Name}",
|
||||
$"gamePath={GameFolder.Replace("\\", "\\\\")}",
|
||||
$"gamePath={((string)GameFolder).Replace("\\", "\\\\")}",
|
||||
$"download_directory={DownloadsFolder}"
|
||||
});
|
||||
|
||||
Directory.CreateDirectory(DownloadsFolder);
|
||||
Directory.CreateDirectory(Path.Combine(GameFolder, "Data"));
|
||||
DownloadsFolder.CreateDirectory();
|
||||
GameFolder.Combine("Data").CreateDirectory();
|
||||
|
||||
Profiles.Do(profile =>
|
||||
{
|
||||
@ -260,9 +261,6 @@ namespace Wabbajack.Test
|
||||
return full_path;
|
||||
}
|
||||
|
||||
public static object RandomeOne(params object[] opts)
|
||||
{
|
||||
return opts[_rng.Next(0, opts.Length)];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
@ -26,7 +26,6 @@
|
||||
<ProjectReference Include="..\Wabbajack.Common.CSP\Wabbajack.Common.CSP.csproj" />
|
||||
<ProjectReference Include="..\Wabbajack.Common\Wabbajack.Common.csproj" />
|
||||
<ProjectReference Include="..\Wabbajack.Lib\Wabbajack.Lib.csproj" />
|
||||
<ProjectReference Include="..\Wabbajack\Wabbajack.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -8,9 +8,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -38,6 +38,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wabbajack.CLI", "Wabbajack.
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wabbajack.Launcher", "Wabbajack.Launcher\Wabbajack.Launcher.csproj", "{D6856DBF-C959-4867-A8A8-343DA2D2715E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Common.Test", "Wabbajack.Common.Test\Wabbajack.Common.Test.csproj", "{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -76,12 +78,6 @@ Global
|
||||
{5D6A2EAF-6604-4C51-8AE2-A746B4BC5E3E}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{5D6A2EAF-6604-4C51-8AE2-A746B4BC5E3E}.Release|x64.ActiveCfg = Release|x64
|
||||
{5D6A2EAF-6604-4C51-8AE2-A746B4BC5E3E}.Release|x64.Build.0 = Release|x64
|
||||
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Debug|x64.Build.0 = Debug|x64
|
||||
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Release|x64.ActiveCfg = Release|x64
|
||||
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Release|x64.Build.0 = Release|x64
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
@ -128,6 +124,14 @@ Global
|
||||
{D6856DBF-C959-4867-A8A8-343DA2D2715E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D6856DBF-C959-4867-A8A8-343DA2D2715E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D6856DBF-C959-4867-A8A8-343DA2D2715E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{BA8A3E49-60D2-4BA2-B285-CB09FFDB6D32}.Debug|x64.Build.0 = Debug|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
Loading…
Reference in New Issue
Block a user