|
- using System;
- using System.Collections.Concurrent;
- using System.IO;
- using System.Runtime.CompilerServices;
-
- using Unity.Mathematics;
-
- namespace GamecraftModdingAPI.Tests
- {
- /// <summary>
- /// API test system assertion utilities.
- /// </summary>
- public static class Assert
- {
- private static StreamWriter logFile = null;
-
- private static ConcurrentDictionary<string, string> callbacks = new ConcurrentDictionary<string, string>();
-
- private const string PASS = "SUCCESS: ";
-
- private const string FAIL = "FAILURE: ";
-
- private const string WARN = "WARNING: ";
-
- private const string INFO = "DEBUG: ";
-
- /// <summary>
- /// Log a message to the test log.
- /// </summary>
- /// <param name="msg">Message.</param>
- /// <param name="end">Message ending.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void Log(string msg, string end = "\n")
- {
- if (logFile == null) openTestLog();
- logFile.Write(msg + end);
- logFile.Flush();
- }
-
- /// <summary>
- /// Asserts that the event receives a callback... eventually.
- /// Add the eventhandler returned by this method to the relevant event.
- /// This does not assert that the callback happens under that event's intended circumstances.
- /// Add another event handler to assert specific circumstance requirements.
- /// </summary>
- /// <returns>The callback event handler.</returns>
- /// <param name="eventName">Event name.</param>
- /// <param name="eventMsg">Event error message.</param>
- /// <typeparam name="T">The event handler callback argument object.</typeparam>
- public static EventHandler<T> CallsBack<T>(string eventName, string eventMsg = null)
- {
- if (eventMsg == null) eventMsg = $"expected callback to {eventName} but it never occurred...";
- callbacks[eventName] = eventMsg;
-
- return (sender, args) =>
- {
- string value = null;
- if (!callbacks.TryRemove(eventName, out value)) { Log(WARN + $"callback to {eventName} occurred again or a related error occurred... (Received '{args.ToString()}' from '{(sender == null ? (string)sender : sender.ToString())}')"); }
- Log(PASS + $"callback to {eventName} occurred... (Received '{args.ToString()}' from '{(sender == null ? (string)sender : sender.ToString())}')");
- TestRoot.TestsPassed = true;
- };
- }
-
- public static bool NotNull<T>(T obj, string err = null, string success = null)
- {
- if (err == null) err = $"{nameof(T)} object was null.";
- if (success == null) success = $"{nameof(T)} '{obj}' not null";
- if (obj == null)
- {
- Log(FAIL + err);
- TestRoot.TestsPassed = false;
- return false;
- }
- else
- {
- Log(PASS + success);
- TestRoot.TestsPassed = true;
- return true;
- }
- }
-
- public static bool Equal<T>(T obj1, T obj2, string err = null, string success = null)
- {
- if (err == null) err = $"{nameof(T)} '{obj1}' is not equal to '{obj2}'.";
- if (success == null) success = $"{nameof(T)} '{obj1}' is equal to '{obj2}'.";
- if (obj1 == null && obj2 == null)
- {
- // pass
- Log(PASS + success);
- TestRoot.TestsPassed = true;
- return true;
- }
- else if (!(obj1 == null && obj2 == null) && obj1.Equals(obj2) && obj2.Equals(obj1))
- {
- // pass
- Log(PASS + success);
- TestRoot.TestsPassed = true;
- return true;
- }
- else if (obj1 != null && (obj1 != null && !obj1.Equals(obj2)))
- {
- // pass
- Log(PASS + success);
- TestRoot.TestsPassed = true;
- return true;
- }
- else if (obj2 != null && !obj2.Equals(obj1))
- {
- // pass
- Log(PASS + success);
- TestRoot.TestsPassed = true;
- return true;
- }
- else
- {
- // fail
- Log(FAIL + err);
- TestRoot.TestsPassed = false;
- return false;
- }
- }
-
- public static bool Errorless(Action tryThis, string err = null, string success = null)
- {
- if (err == null) err = $"{tryThis} raised an exception: ";
- if (success == null) success = $"{tryThis} completed without raising an exception.";
- try
- {
- tryThis();
- }
- catch (Exception e)
- {
- Log(FAIL + err + e);
- TestRoot.TestsPassed = false;
- return false;
- }
- TestRoot.TestsPassed = true;
- Log(PASS + success);
- return true;
- }
-
- public static bool CloseTo(float a, float b, string err = null, string success = null, float delta = float.Epsilon)
- {
- if (err == null) err = $"{a} is not within {delta} of {b}.";
- if (success == null) success = $"{a} is close enough to {b}.";
- if (Math.Abs(a - b) > delta)
- {
- Log(FAIL + err);
- TestRoot.TestsPassed = false;
- return false;
- }
- else
- {
- TestRoot.TestsPassed = true;
- Log(PASS + success);
- return true;
- }
- }
-
- public static bool CloseTo(double a, double b, string err = null, string success = null, double delta = double.Epsilon)
- {
- if (err == null) err = $"{a} is not within {delta} of {b}.";
- if (success == null) success = $"{a} is close enough to {b}.";
- if (Math.Abs(a - b) > delta)
- {
- Log(FAIL + err);
- TestRoot.TestsPassed = false;
- return false;
- }
- else
- {
- TestRoot.TestsPassed = true;
- Log(PASS + success);
- return true;
- }
- }
-
- public static bool CloseTo(float3 a, float3 b, string err = null, string success = null, float delta = float.Epsilon)
- {
- if (err == null) err = $"{a} is not within {delta} of {b} in every direction.";
- if (success == null) success = $"{a} is close enough to {b}.";
- bool xClose = CloseTo(a.x, b.x, err, success, delta);
- bool yClose = CloseTo(a.y, b.y, err, success, delta);
- bool zClose = CloseTo(a.z, b.z, err, success, delta);
- if (xClose && yClose && zClose)
- {
- //TestRoot.TestsPassed = true;
- //Log(PASS + success);
- return true;
- }
- else
- {
- //Log(FAIL + err);
- //TestRoot.TestsPassed = false;
- return false;
- }
- }
-
- public static void Fail(string msg = null)
- {
- if (msg == null) msg = $"Manual test failure with no message provided.";
- Log(FAIL + msg);
- TestRoot.TestsPassed = false;
- }
-
- public static void Pass(string msg = null)
- {
- if (msg == null) msg = $"Manual test pass with no message provided.";
- Log(PASS + msg);
- TestRoot.TestsPassed = true;
- }
-
- public static void Warn(string msg = null)
- {
- if (msg == null) msg = $"Manual test warning with no message provided.";
- Log(WARN + msg);
- TestRoot.TestsPassed = true;
- }
-
- internal static void CallsComplete()
- {
- foreach(string key in callbacks.Keys)
- {
- Log(FAIL + callbacks[key]);
- TestRoot.TestsPassed = false;
- }
- }
-
- internal static void CloseLog()
- {
- if (logFile != null) logFile.Close();
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void openTestLog()
- {
- logFile = File.CreateText(TestRoot.ReportFile);
- }
- }
- }
|