2020-06-18 01:04:40 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Linq; // welcome to the dark side
|
|
|
|
|
|
|
|
|
|
using Svelto.Tasks;
|
|
|
|
|
using Svelto.Tasks.Lean;
|
|
|
|
|
using Svelto.Tasks.Enumerators;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
using GamecraftModdingAPI.App;
|
|
|
|
|
using GamecraftModdingAPI.Tasks;
|
|
|
|
|
using GamecraftModdingAPI.Utility;
|
|
|
|
|
|
|
|
|
|
namespace GamecraftModdingAPI.Tests
|
|
|
|
|
{
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// API test system root class.
|
|
|
|
|
/// </summary>
|
2020-06-18 01:04:40 +00:00
|
|
|
|
public static class TestRoot
|
|
|
|
|
{
|
|
|
|
|
public static bool AutoShutdown = true;
|
|
|
|
|
|
|
|
|
|
public const string ReportFile = "GamecraftModdingAPI_tests.log";
|
|
|
|
|
|
|
|
|
|
private static bool _testsPassed = false;
|
|
|
|
|
|
|
|
|
|
private static uint _testsCount = 0;
|
|
|
|
|
|
|
|
|
|
private static uint _testsCountPassed = 0;
|
|
|
|
|
|
|
|
|
|
private static uint _testsCountFailed = 0;
|
|
|
|
|
|
|
|
|
|
private static string state = "StartingUp";
|
|
|
|
|
|
|
|
|
|
private static Stopwatch timer;
|
|
|
|
|
|
|
|
|
|
private static List<Type> testTypes = null;
|
|
|
|
|
|
|
|
|
|
public static bool TestsPassed
|
|
|
|
|
{
|
|
|
|
|
get => _testsPassed;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
_testsPassed = _testsPassed && value;
|
|
|
|
|
_testsCount++;
|
|
|
|
|
if (value)
|
|
|
|
|
{
|
|
|
|
|
_testsCountPassed++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_testsCountFailed++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void StartUp()
|
|
|
|
|
{
|
|
|
|
|
// init
|
|
|
|
|
timer = Stopwatch.StartNew();
|
|
|
|
|
_testsPassed = true;
|
|
|
|
|
_testsCount = 0;
|
|
|
|
|
_testsCountPassed = 0;
|
|
|
|
|
_testsCountFailed = 0;
|
|
|
|
|
// flow control
|
|
|
|
|
Game.Enter += (sender, args) => { GameTests().RunOn(RobocraftX.Schedulers.Lean.EveryFrameStepRunner_RUNS_IN_TIME_STOPPED_AND_RUNNING); };
|
|
|
|
|
Game.Exit += (s, a) => state = "ReturningFromGame";
|
|
|
|
|
Client.EnterMenu += (sender, args) =>
|
|
|
|
|
{
|
|
|
|
|
if (state == "EnteringMenu")
|
|
|
|
|
{
|
|
|
|
|
MenuTests().RunOn(Scheduler.leanRunner);
|
|
|
|
|
state = "EnteringGame";
|
|
|
|
|
}
|
|
|
|
|
if (state == "ReturningFromGame")
|
|
|
|
|
{
|
|
|
|
|
TearDown().RunOn(Scheduler.leanRunner);
|
|
|
|
|
state = "ShuttingDown";
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
// init tests here
|
|
|
|
|
foreach (Type t in testTypes)
|
|
|
|
|
{
|
|
|
|
|
foreach (MethodBase m in t.GetMethods())
|
|
|
|
|
{
|
|
|
|
|
if (m.GetCustomAttribute<APITestStartUpAttribute>() != null)
|
|
|
|
|
{
|
2020-07-01 00:43:14 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
m.Invoke(null, new object[0]);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Assert.Fail($"Start up method '{m}' raised an exception: {e.ToString()}");
|
|
|
|
|
}
|
2020-06-18 01:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
state = "EnteringMenu";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static IEnumerator<TaskContract> MenuTests()
|
|
|
|
|
{
|
|
|
|
|
yield return Yield.It;
|
|
|
|
|
// menu tests
|
|
|
|
|
foreach (Type t in testTypes)
|
|
|
|
|
{
|
|
|
|
|
foreach (MethodBase m in t.GetMethods())
|
|
|
|
|
{
|
|
|
|
|
APITestCaseAttribute a = m.GetCustomAttribute<APITestCaseAttribute>();
|
|
|
|
|
if (a != null && a.TestType == TestType.Menu)
|
|
|
|
|
{
|
2020-07-01 00:43:14 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
m.Invoke(null, new object[0]);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Assert.Fail($"Menu test '{m}' raised an exception: {e.ToString()}");
|
|
|
|
|
}
|
2020-06-18 01:04:40 +00:00
|
|
|
|
yield return Yield.It;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// load game
|
|
|
|
|
yield return GoToGameTests().Continue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static IEnumerator<TaskContract> GoToGameTests()
|
|
|
|
|
{
|
|
|
|
|
Client app = new Client();
|
|
|
|
|
int oldLength = 0;
|
|
|
|
|
while (app.MyGames.Length == 0 || oldLength != app.MyGames.Length)
|
|
|
|
|
{
|
|
|
|
|
oldLength = app.MyGames.Length;
|
|
|
|
|
yield return new WaitForSecondsEnumerator(1).Continue();
|
|
|
|
|
}
|
|
|
|
|
yield return Yield.It;
|
|
|
|
|
app.MyGames[0].EnterGame();
|
2020-07-19 20:39:35 +00:00
|
|
|
|
/*Game newGame = Game.NewGame();
|
|
|
|
|
yield return new WaitForSecondsEnumerator(5).Continue(); // wait for sync
|
|
|
|
|
newGame.EnterGame();*/
|
2020-06-18 01:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static IEnumerator<TaskContract> GameTests()
|
|
|
|
|
{
|
|
|
|
|
yield return Yield.It;
|
|
|
|
|
Game currentGame = Game.CurrentGame();
|
|
|
|
|
// in-game tests
|
|
|
|
|
yield return new WaitForSecondsEnumerator(5).Continue(); // wait for game to finish loading
|
|
|
|
|
foreach (Type t in testTypes)
|
|
|
|
|
{
|
|
|
|
|
foreach (MethodBase m in t.GetMethods())
|
|
|
|
|
{
|
|
|
|
|
APITestCaseAttribute a = m.GetCustomAttribute<APITestCaseAttribute>();
|
|
|
|
|
if (a != null && a.TestType == TestType.Game)
|
|
|
|
|
{
|
2020-07-01 00:43:14 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
m.Invoke(null, new object[0]);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Assert.Fail($"Game test '{m}' raised an exception: {e.ToString()}");
|
|
|
|
|
}
|
2020-06-18 01:04:40 +00:00
|
|
|
|
yield return Yield.It;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
currentGame.ToggleTimeMode();
|
|
|
|
|
yield return new WaitForSecondsEnumerator(5).Continue();
|
|
|
|
|
// simulation tests
|
|
|
|
|
foreach (Type t in testTypes)
|
|
|
|
|
{
|
|
|
|
|
foreach (MethodBase m in t.GetMethods())
|
|
|
|
|
{
|
|
|
|
|
APITestCaseAttribute a = m.GetCustomAttribute<APITestCaseAttribute>();
|
|
|
|
|
if (a != null && a.TestType == TestType.SimulationMode)
|
|
|
|
|
{
|
2020-07-01 00:43:14 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
m.Invoke(null, new object[0]);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Assert.Fail($"Simulation test '{m}' raised an exception: {e.ToString()}");
|
|
|
|
|
}
|
2020-06-18 01:04:40 +00:00
|
|
|
|
yield return Yield.It;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
currentGame.ToggleTimeMode();
|
|
|
|
|
yield return new WaitForSecondsEnumerator(5).Continue();
|
|
|
|
|
// build tests
|
|
|
|
|
foreach (Type t in testTypes)
|
|
|
|
|
{
|
|
|
|
|
foreach (MethodBase m in t.GetMethods())
|
|
|
|
|
{
|
|
|
|
|
APITestCaseAttribute a = m.GetCustomAttribute<APITestCaseAttribute>();
|
|
|
|
|
if (a != null && a.TestType == TestType.EditMode)
|
|
|
|
|
{
|
2020-07-01 00:43:14 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
m.Invoke(null, new object[0]);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Assert.Fail($"Build test '{m}' raised an exception: {e.ToString()}");
|
|
|
|
|
}
|
2020-08-03 16:45:38 +00:00
|
|
|
|
yield return Yield.It;
|
2020-06-18 01:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// exit game
|
|
|
|
|
yield return new WaitForSecondsEnumerator(5).Continue();
|
|
|
|
|
yield return ReturnToMenu().Continue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static IEnumerator<TaskContract> ReturnToMenu()
|
|
|
|
|
{
|
|
|
|
|
Logging.MetaLog("Returning to main menu");
|
|
|
|
|
yield return Yield.It;
|
|
|
|
|
Game.CurrentGame().ExitGame();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static IEnumerator<TaskContract> TearDown()
|
|
|
|
|
{
|
|
|
|
|
yield return new WaitForSecondsEnumerator(5).Continue();
|
|
|
|
|
Logging.MetaLog("Tearing down test run");
|
|
|
|
|
// dispose tests here
|
|
|
|
|
foreach (Type t in testTypes)
|
|
|
|
|
{
|
|
|
|
|
foreach (MethodBase m in t.GetMethods())
|
|
|
|
|
{
|
|
|
|
|
if (m.GetCustomAttribute<APITestTearDownAttribute>() != null)
|
|
|
|
|
{
|
2020-07-01 00:43:14 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
m.Invoke(null, new object[0]);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Assert.Warn($"Tear down method '{m}' raised an exception: {e.ToString()}");
|
|
|
|
|
}
|
2020-06-18 01:04:40 +00:00
|
|
|
|
yield return Yield.It;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// finish up
|
|
|
|
|
Assert.CallsComplete();
|
|
|
|
|
timer.Stop();
|
|
|
|
|
string verdict = _testsPassed ? "--- PASSED :) ---" : "--- FAILED :( ---";
|
|
|
|
|
Assert.Log($"VERDICT: {verdict} ({_testsCountPassed}/{_testsCountFailed}/{_testsCount} P/F/T in {timer.ElapsedMilliseconds}ms)");
|
|
|
|
|
yield return Yield.It;
|
|
|
|
|
// end game
|
|
|
|
|
Logging.MetaLog("Completed test run: " + verdict);
|
|
|
|
|
yield return Yield.It;
|
|
|
|
|
Assert.CloseLog();
|
|
|
|
|
if (AutoShutdown) Application.Quit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void FindTests(Assembly asm)
|
|
|
|
|
{
|
|
|
|
|
testTypes = new List<Type>();
|
|
|
|
|
foreach (Type t in asm.GetTypes())
|
|
|
|
|
{
|
|
|
|
|
if (t.GetCustomAttribute<APITestClassAttribute>() != null)
|
|
|
|
|
{
|
|
|
|
|
testTypes.Add(t);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Runs the tests.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="asm">Assembly to search for tests. When set to null, this uses the GamecraftModdingAPI assembly. </param>
|
2020-06-18 01:04:40 +00:00
|
|
|
|
public static void RunTests(Assembly asm = null)
|
|
|
|
|
{
|
|
|
|
|
if (asm == null) asm = Assembly.GetExecutingAssembly();
|
|
|
|
|
FindTests(asm);
|
|
|
|
|
Logging.MetaLog("Starting test run");
|
|
|
|
|
// log metadata
|
|
|
|
|
Assert.Log($"Unity {Application.unityVersion}");
|
|
|
|
|
Assert.Log($"Gamecraft {Application.version}");
|
|
|
|
|
Assert.Log($"GamecraftModdingAPI {Assembly.GetExecutingAssembly().GetName().Version}");
|
|
|
|
|
Assert.Log($"Testing {asm.GetName().Name} {asm.GetName().Version}");
|
|
|
|
|
Assert.Log($"START: --- {DateTime.Now.ToString()} --- ({testTypes.Count} tests classes detected)");
|
|
|
|
|
StartUp();
|
|
|
|
|
Logging.MetaLog("Test StartUp complete");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|