// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
#pragma warning disable 1591
namespace FlaxEngine.Assertions
{
///
/// The Assert class contains assertion methods for setting invariants in the code.
///
[DebuggerStepThrough]
[HideInEditor]
public static class Assert
{
///
/// Should an exception be thrown on a failure.
///
public static bool RaiseExceptions = true;
///
/// Asserts that the values are approximately equal. An absolute error check is used for approximate equality check
/// (|a-b| < tolerance). Default tolerance is 0.00001f.
/// Note: Every time you call the method with tolerance specified, a new instance of Assertions.Comparers.FloatComparer
/// is created. For performance reasons you might want to instance your own comparer and pass it to the AreEqual method.
/// If the tolerance is not specifies, a default comparer is used and the issue does not occur.
///
///
///
[Conditional("FLAX_ASSERTIONS")]
public static void AreApproximatelyEqual(float expected, float actual)
{
AreEqual(expected, actual, null, FloatComparer.ComparerWithDefaultTolerance);
}
///
/// Asserts that the values are approximately equal. An absolute error check is used for approximate equality check
/// (|a-b| < tolerance). Default tolerance is 0.00001f.
/// Note: Every time you call the method with tolerance specified, a new instance of Assertions.Comparers.FloatComparer
/// is created. For performance reasons you might want to instance your own comparer and pass it to the AreEqual method.
/// If the tolerance is not specifies, a default comparer is used and the issue does not occur.
///
///
///
///
[Conditional("FLAX_ASSERTIONS")]
public static void AreApproximatelyEqual(float expected, float actual, string message)
{
AreEqual(expected, actual, message, FloatComparer.ComparerWithDefaultTolerance);
}
///
/// Asserts that the values are approximately equal. An absolute error check is used for approximate equality check
/// (|a-b| < tolerance). Default tolerance is 0.00001f.
/// Note: Every time you call the method with tolerance specified, a new instance of Assertions.Comparers.FloatComparer
/// is created. For performance reasons you might want to instance your own comparer and pass it to the AreEqual method.
/// If the tolerance is not specifies, a default comparer is used and the issue does not occur.
///
/// Tolerance of approximation.
///
///
[Conditional("FLAX_ASSERTIONS")]
public static void AreApproximatelyEqual(float expected, float actual, float tolerance)
{
AreApproximatelyEqual(expected, actual, tolerance, null);
}
///
/// Asserts that the values are approximately equal. An absolute error check is used for approximate equality check
/// (|a-b| < tolerance). Default tolerance is 0.00001f.
/// Note: Every time you call the method with tolerance specified, a new instance of Assertions.Comparers.FloatComparer
/// is created. For performance reasons you might want to instance your own comparer and pass it to the AreEqual method.
/// If the tolerance is not specifies, a default comparer is used and the issue does not occur.
///
/// Tolerance of approximation.
///
///
///
[Conditional("FLAX_ASSERTIONS")]
public static void AreApproximatelyEqual(float expected, float actual, float tolerance, string message)
{
AreEqual(expected, actual, message, new FloatComparer(tolerance));
}
///
/// Asserts that the values are approximately equal.
///
/// The value type.
/// The expected value.
/// The actual value.
[Conditional("FLAX_ASSERTIONS")]
public static void AreEqual(T expected, T actual)
{
AreEqual(expected, actual, null);
}
///
/// Asserts that the values are approximately equal.
///
/// The value type.
/// The expected value.
/// The actual value.
/// The error message.
[Conditional("FLAX_ASSERTIONS")]
public static void AreEqual(T expected, T actual, string message)
{
AreEqual(expected, actual, message, EqualityComparer.Default);
}
///
/// Asserts that the values are approximately equal.
///
/// The value type.
/// The expected value.
/// The actual value.
/// The error message.
/// The equality comparer.
[Conditional("FLAX_ASSERTIONS")]
public static void AreEqual(T expected, T actual, string message, IEqualityComparer comparer)
{
if (typeof(Object).IsAssignableFrom(typeof(T)))
{
AreEqual((object)expected as Object, (object)actual as Object, message);
return;
}
if (!comparer.Equals(actual, expected))
Fail(GetEqualityMessage(actual, expected, true), message);
}
///
/// Asserts that the values are approximately equal.
///
/// The expected value.
/// The actual value.
/// The error message.
[Conditional("FLAX_ASSERTIONS")]
public static void AreEqual(Object expected, Object actual, string message)
{
if (actual != expected)
Fail(GetEqualityMessage(actual, expected, true), message);
}
///
/// Asserts that the values are approximately not equal. An absolute error check is used for approximate equality check
/// (|a-b| < tolerance). Default tolerance is 0.00001f.
///
///
///
[Conditional("FLAX_ASSERTIONS")]
public static void AreNotApproximatelyEqual(float expected, float actual)
{
AreNotEqual(expected, actual, null, FloatComparer.ComparerWithDefaultTolerance);
}
///
/// Asserts that the values are approximately not equal. An absolute error check is used for approximate equality check
/// (|a-b| < tolerance). Default tolerance is 0.00001f.
///
///
///
///
[Conditional("FLAX_ASSERTIONS")]
public static void AreNotApproximatelyEqual(float expected, float actual, string message)
{
AreNotEqual(expected, actual, message, FloatComparer.ComparerWithDefaultTolerance);
}
///
/// Asserts that the values are approximately not equal. An absolute error check is used for approximate equality check
/// (|a-b| < tolerance). Default tolerance is 0.00001f.
///
/// Tolerance of approximation.
///
///
[Conditional("FLAX_ASSERTIONS")]
public static void AreNotApproximatelyEqual(float expected, float actual, float tolerance)
{
AreNotApproximatelyEqual(expected, actual, tolerance, null);
}
///
/// Asserts that the values are approximately not equal. An absolute error check is used for approximate equality check
/// (|a-b| < tolerance). Default tolerance is 0.00001f.
///
/// Tolerance of approximation.
///
///
///
[Conditional("FLAX_ASSERTIONS")]
public static void AreNotApproximatelyEqual(float expected, float actual, float tolerance, string message)
{
AreNotEqual(expected, actual, message, new FloatComparer(tolerance));
}
[Conditional("FLAX_ASSERTIONS")]
public static void AreNotEqual(T expected, T actual)
{
AreNotEqual(expected, actual, null);
}
[Conditional("FLAX_ASSERTIONS")]
public static void AreNotEqual(T expected, T actual, string message)
{
AreNotEqual(expected, actual, message, EqualityComparer.Default);
}
[Conditional("FLAX_ASSERTIONS")]
public static void AreNotEqual(T expected, T actual, string message, IEqualityComparer comparer)
{
if (typeof(Object).IsAssignableFrom(typeof(T)))
{
AreNotEqual((object)expected as Object, (object)actual as Object, message);
return;
}
if (comparer.Equals(actual, expected))
Fail(GetEqualityMessage(actual, expected, false), message);
}
[Conditional("FLAX_ASSERTIONS")]
public static void AreNotEqual(Object expected, Object actual, string message)
{
if (actual == expected)
Fail(GetEqualityMessage(actual, expected, false), message);
}
public static void Fail(string message = "", string userMessage = "")
{
if (RaiseExceptions)
throw new AssertionException(message, userMessage);
if (message == null)
message = "Assertion has failed\n";
if (userMessage != null)
message = string.Concat(userMessage, '\n', message);
Debug.LogAssertion(message);
}
///
/// Asserts that the condition is false.
///
///
[Conditional("FLAX_ASSERTIONS")]
public static void IsFalse(bool condition)
{
IsFalse(condition, null);
}
///
/// Asserts that the condition is false.
///
///
///
[Conditional("FLAX_ASSERTIONS")]
public static void IsFalse(bool condition, string message)
{
if (condition)
Fail(BooleanFailureMessage(false), message);
}
[Conditional("FLAX_ASSERTIONS")]
public static void IsNotNull(T value)
where T : class
{
IsNotNull(value, null);
}
[Conditional("FLAX_ASSERTIONS")]
public static void IsNotNull(T value, string message)
where T : class
{
if (typeof(Object).IsAssignableFrom(typeof(T)))
IsNotNull((object)value as Object, message);
else if (value == null)
Fail(NullFailureMessage(null, false), message);
}
[Conditional("FLAX_ASSERTIONS")]
public static void IsNotNull(Object value, string message)
{
if (value == null)
Fail(NullFailureMessage(null, false), message);
}
[Conditional("FLAX_ASSERTIONS")]
public static void IsNull(T value)
where T : class
{
IsNull(value, null);
}
[Conditional("FLAX_ASSERTIONS")]
public static void IsNull(T value, string message)
where T : class
{
if (typeof(Object).IsAssignableFrom(typeof(T)))
IsNull((object)value as Object, message);
else if (value != null)
Fail(NullFailureMessage(value, true), message);
}
[Conditional("FLAX_ASSERTIONS")]
public static void IsNull(Object value, string message)
{
if (value != null)
Fail(NullFailureMessage(value, true), message);
}
///
/// Asserts that the condition is true.
///
///
[Conditional("FLAX_ASSERTIONS")]
public static void IsTrue(bool condition)
{
IsTrue(condition, null);
}
///
/// Asserts that the condition is true.
///
///
///
[Conditional("FLAX_ASSERTIONS")]
public static void IsTrue(bool condition, string message)
{
if (!condition)
Fail(BooleanFailureMessage(true), message);
}
///
/// Expect action to fail
///
/// Type of exception to expect
/// Action to expect
/// User custom message to display
[Conditional("FLAX_ASSERTIONS")]
public static void ExceptionExpected(Type exceptionType, Action action, string message = "")
{
try
{
action();
}
catch (Exception e)
{
if (exceptionType != e.GetType())
{
Fail(GetMessage("Expected exception of type " + exceptionType.FullName + " got " + e.GetType().FullName), message);
}
return;
}
Fail(GetMessage("Expected exception of type " + exceptionType.FullName), message);
}
public static string BooleanFailureMessage(bool expected)
{
return GetMessage(string.Concat("Value was ", !expected), expected.ToString());
}
public static string GetEqualityMessage(object actual, object expected, bool expectEqual)
{
string str = string.Format("Values are {0}equal.", new object[] { !expectEqual ? string.Empty : "not " });
object[] objArray =
{
actual,
expected,
null
};
objArray[2] = !expectEqual ? "!=" : "==";
return GetMessage(str, string.Format("{0} {2} {1}", objArray));
}
public static string GetMessage(string failureMessage)
{
return string.Format("{0} {1}", new object[]
{
"Assertion failed.",
failureMessage
});
}
public static string GetMessage(string failureMessage, string expected)
{
return GetMessage($"{failureMessage}\nExpected: {expected}");
}
public static string NullFailureMessage(object value, bool expectNull)
{
return GetMessage(string.Format("Value was {0}Null", new object[] { !expectNull ? string.Empty : "not " }), string.Format("Value was {0}Null", new object[] { !expectNull ? "not " : string.Empty }));
}
}
}