Tests: Add TestRunner configuration

This commit is contained in:
Katy Coe
2021-01-12 00:16:45 +01:00
parent 92451e26ef
commit 68d251926d
2 changed files with 102 additions and 56 deletions

View File

@@ -18,25 +18,10 @@ using NUnit.Framework;
namespace Il2CppInspector namespace Il2CppInspector
{ {
internal class Benchmark : IDisposable
{
private readonly Stopwatch timer = new Stopwatch();
private readonly string benchmarkName;
public Benchmark(string benchmarkName) {
this.benchmarkName = benchmarkName;
timer.Start();
}
public void Dispose() {
timer.Stop();
Console.WriteLine($"{benchmarkName}: {timer.Elapsed.TotalSeconds:N2} sec");
}
}
[TestFixture] [TestFixture]
public partial class TestRunner public partial class TestRunner
{ {
// Test runner
private async Task runTest(string testPath, LoadOptions loadOptions = null) { private async Task runTest(string testPath, LoadOptions loadOptions = null) {
// Android // Android
var testFile = testPath + @"\" + Path.GetFileName(testPath) + ".so"; var testFile = testPath + @"\" + Path.GetFileName(testPath) + ".so";
@@ -126,66 +111,81 @@ namespace Il2CppInspector
if (inspectors.Count == 0) if (inspectors.Count == 0)
throw new Exception("Could not find any images in the IL2CPP binary"); throw new Exception("Could not find any images in the IL2CPP binary");
// End if we were only testing file load
if (!GenerateCpp && !GenerateCS && !GenerateDLL && !GenerateJSON && !GeneratePython)
return;
// Dump each image in the binary separately // Dump each image in the binary separately
var imageTasks = inspectors.Select((il2cpp, i) => Task.Run(async () => var imageTasks = inspectors.Select((il2cpp, i) => Task.Run(async () =>
{ {
TypeModel model; TypeModel model;
using (new Benchmark("Create .NET type model")) using (new Benchmark("Create .NET type model"))
model = new TypeModel(il2cpp); model = new TypeModel(il2cpp);
var appModelTask = Task.Run(() => {
using (new Benchmark("Create application model")) Task<AppModel> appModelTask = null;
return new AppModel(model, makeDefaultBuild: false).Build(compiler: CppCompilerType.MSVC); if (GenerateCpp || GenerateJSON || GeneratePython)
}); appModelTask = Task.Run(() => {
using (new Benchmark("Create application model"))
return new AppModel(model, makeDefaultBuild: false).Build(compiler: CppCompilerType.MSVC);
});
var nameSuffix = i++ > 0 ? "-" + (i - 1) : ""; var nameSuffix = i++ > 0 ? "-" + (i - 1) : "";
var generateTasks = new List<Task>();
var compareTasks = new List<Task>(); var compareTasks = new List<Task>();
var csTask = Task.Run(() => { if (GenerateCS)
using (new Benchmark("Create C# code stubs")) generateTasks.Add(Task.Run(() => {
new CSharpCodeStubs(model) { using (new Benchmark("Create C# code stubs"))
ExcludedNamespaces = Constants.DefaultExcludedNamespaces, new CSharpCodeStubs(model) {
SuppressMetadata = false, ExcludedNamespaces = Constants.DefaultExcludedNamespaces,
MustCompile = true SuppressMetadata = false,
}.WriteSingleFile(testPath + $@"\test-result{nameSuffix}.cs"); MustCompile = true
}.WriteSingleFile(testPath + $@"\test-result{nameSuffix}.cs");
compareTasks.Add(Task.Run(() => compareFiles(testPath, nameSuffix + ".cs", $"test-result{nameSuffix}.cs"))); compareTasks.Add(Task.Run(() => compareFiles(testPath, nameSuffix + ".cs", $"test-result{nameSuffix}.cs")));
}); }));
var dllTask = Task.Run(() => { if (GenerateDLL)
using (new Benchmark("Create .NET assembly shims")) generateTasks.Add(Task.Run(() => {
new AssemblyShims(model).Write(testPath + $@"\test-dll-result{nameSuffix}"); using (new Benchmark("Create .NET assembly shims"))
new AssemblyShims(model).Write(testPath + $@"\test-dll-result{nameSuffix}");
compareTasks.Add(Task.Run(() => compareBinaryFiles(testPath + $@"\test-dll-result{nameSuffix}", compareTasks.Add(Task.Run(() => compareBinaryFiles(testPath + $@"\test-dll-result{nameSuffix}",
testPath + @"\..\..\TestExpectedResults\dll-" + Path.GetFileName(testPath) + nameSuffix))); testPath + @"\..\..\TestExpectedResults\dll-" + Path.GetFileName(testPath) + nameSuffix)));
}); }));
var appModel = await appModelTask; AppModel appModel = null;
if (appModelTask != null)
appModel = await appModelTask;
var jsonTask = Task.Run(() => { if (GenerateJSON || GeneratePython)
using (new Benchmark("Create JSON metadata")) generateTasks.Add(Task.Run(() => {
new JSONMetadata(appModel) using (new Benchmark("Create JSON metadata"))
.Write(testPath + $@"\test-result{nameSuffix}.json"); new JSONMetadata(appModel)
.Write(testPath + $@"\test-result{nameSuffix}.json");
compareTasks.Add(Task.Run(() => compareFiles(testPath, nameSuffix + ".json", $"test-result{nameSuffix}.json"))); compareTasks.Add(Task.Run(() => compareFiles(testPath, nameSuffix + ".json", $"test-result{nameSuffix}.json")));
}); }));
var cppTask = Task.Run(() => { if (GenerateCpp || GeneratePython)
using (new Benchmark("Create C++ scaffolding")) generateTasks.Add(Task.Run(() => {
new CppScaffolding(appModel) using (new Benchmark("Create C++ scaffolding"))
.Write(testPath + $@"\test-cpp-result{nameSuffix}"); new CppScaffolding(appModel)
.Write(testPath + $@"\test-cpp-result{nameSuffix}");
compareTasks.Add(Task.Run(() => compareFiles(testPath, nameSuffix + ".h", $@"test-cpp-result{nameSuffix}\appdata\il2cpp-types.h"))); compareTasks.Add(Task.Run(() => compareFiles(testPath, nameSuffix + ".h", $@"test-cpp-result{nameSuffix}\appdata\il2cpp-types.h")));
}); }));
var pyTask = Task.Run(() => { if (GeneratePython)
var python = new PythonScript(appModel); generateTasks.Add(Task.Run(() => {
foreach (var target in PythonScript.GetAvailableTargets()) var python = new PythonScript(appModel);
python.WriteScriptToFile(testPath + $@"\test-{target.ToLower()}{nameSuffix}.py", target, foreach (var target in PythonScript.GetAvailableTargets())
testPath + $@"\test-cpp-result{nameSuffix}\appdata\il2cpp-types.h", python.WriteScriptToFile(testPath + $@"\test-{target.ToLower()}{nameSuffix}.py", target,
testPath + $@"\test-result{nameSuffix}.json"); testPath + $@"\test-cpp-result{nameSuffix}\appdata\il2cpp-types.h",
}); testPath + $@"\test-result{nameSuffix}.json");
}));
await Task.WhenAll(csTask, dllTask, jsonTask, cppTask, pyTask); await Task.WhenAll(generateTasks);
await Task.WhenAll(compareTasks); await Task.WhenAll(compareTasks);
})); }));
await Task.WhenAll(imageTasks); await Task.WhenAll(imageTasks);
@@ -193,6 +193,10 @@ namespace Il2CppInspector
// Compare two folders full of binary files // Compare two folders full of binary files
private void compareBinaryFiles(string resultFolder, string expectedFolder) { private void compareBinaryFiles(string resultFolder, string expectedFolder) {
if (!EnableCompare)
return;
var expectedFiles = Directory.GetFiles(expectedFolder).Select(f => Path.GetFileName(f)); var expectedFiles = Directory.GetFiles(expectedFolder).Select(f => Path.GetFileName(f));
foreach (var file in expectedFiles) { foreach (var file in expectedFiles) {
@@ -215,6 +219,10 @@ namespace Il2CppInspector
// We have to pass testPath rather than storing it as a field so that tests can be parallelized // We have to pass testPath rather than storing it as a field so that tests can be parallelized
private void compareFiles(string testPath, string expectedFilenameSuffix, string actualFilename) { private void compareFiles(string testPath, string expectedFilenameSuffix, string actualFilename) {
if (!EnableCompare)
return;
var expected = File.ReadAllLines(testPath + @"\..\..\TestExpectedResults\" + Path.GetFileName(testPath) + expectedFilenameSuffix); var expected = File.ReadAllLines(testPath + @"\..\..\TestExpectedResults\" + Path.GetFileName(testPath) + expectedFilenameSuffix);
var actual = File.ReadAllLines(testPath + @"\" + actualFilename); var actual = File.ReadAllLines(testPath + @"\" + actualFilename);
@@ -240,4 +248,21 @@ namespace Il2CppInspector
} }
} }
} }
// Quick benchmarking tool
internal class Benchmark : IDisposable
{
private readonly Stopwatch timer = new Stopwatch();
private readonly string benchmarkName;
public Benchmark(string benchmarkName) {
this.benchmarkName = benchmarkName;
timer.Start();
}
public void Dispose() {
timer.Stop();
Console.WriteLine($"{benchmarkName}: {timer.Elapsed.TotalSeconds:N2} sec");
}
}
} }

View File

@@ -0,0 +1,21 @@
/*
Copyright 2019-2021 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
All rights reserved.
*/
namespace Il2CppInspector
{
// Configuration options for test runner
// Determines which integration tests to run
public partial class TestRunner
{
public const bool GenerateCS = true;
public const bool GenerateDLL = true;
public const bool GenerateJSON = true;
public const bool GenerateCpp = true;
public const bool GeneratePython = true;
public const bool EnableCompare = true;
}
}