|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- 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
- {
- /// <summary>
- /// API test system root class.
- /// </summary>
- 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)
- {
- try
- {
- m.Invoke(null, new object[0]);
- }
- catch (Exception e)
- {
- Assert.Fail($"Start up method '{m}' raised an exception: {e.ToString()}");
- }
- }
- }
- }
- 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)
- {
- try
- {
- m.Invoke(null, new object[0]);
- }
- catch (Exception e)
- {
- Assert.Fail($"Menu test '{m}' raised an exception: {e.ToString()}");
- }
- 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();
- /*Game newGame = Game.NewGame();
- yield return new WaitForSecondsEnumerator(5).Continue(); // wait for sync
- newGame.EnterGame();*/
- }
-
- 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)
- {
- try
- {
- m.Invoke(null, new object[0]);
- }
- catch (Exception e)
- {
- Assert.Fail($"Game test '{m}' raised an exception: {e.ToString()}");
- }
- 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)
- {
- try
- {
- m.Invoke(null, new object[0]);
- }
- catch (Exception e)
- {
- Assert.Fail($"Simulation test '{m}' raised an exception: {e.ToString()}");
- }
- 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)
- {
- try
- {
- m.Invoke(null, new object[0]);
- }
- catch (Exception e)
- {
- Assert.Fail($"Build test '{m}' raised an exception: {e.ToString()}");
- }
- yield return Yield.It;
- }
- }
- }
- // 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)
- {
- try
- {
- m.Invoke(null, new object[0]);
- }
- catch (Exception e)
- {
- Assert.Warn($"Tear down method '{m}' raised an exception: {e.ToString()}");
- }
- 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);
- }
- }
- }
-
- /// <summary>
- /// Runs the tests.
- /// </summary>
- /// <param name="asm">Assembly to search for tests. When set to null, this uses the GamecraftModdingAPI assembly. </param>
- 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");
- }
- }
- }
|