EqualNumericWithoutUsingConstraint<T>
EqualNumericConstraint is able to compare an actual value with the
expected value provided in its constructor. Two objects are
considered equal if both are null, or if both have the same
value. NUnit has special semantics for some object types.
using System;
using System.Runtime.CompilerServices;
using System.Text;
namespace NUnit.Framework.Constraints
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public class EqualNumericWithoutUsingConstraint<[System.Runtime.CompilerServices.Nullable(0)] T> : Constraint where T : struct
{
[System.Runtime.CompilerServices.Nullable(0)]
private readonly T _expected;
private Tolerance _tolerance = Tolerance.Default;
public override string DisplayName => "Equal";
[System.Runtime.CompilerServices.Nullable(0)]
public T Expected {
[System.Runtime.CompilerServices.NullableContext(0)]
get {
return _expected;
}
}
public Tolerance Tolerance => _tolerance;
[System.Runtime.CompilerServices.Nullable(new byte[] {
1,
0
})]
public EqualNumericWithoutUsingConstraint<T> Ulps {
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
1,
0
})]
get {
_tolerance = _tolerance.Ulps;
return this;
}
}
[System.Runtime.CompilerServices.Nullable(new byte[] {
1,
0
})]
public EqualNumericWithoutUsingConstraint<T> Percent {
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
1,
0
})]
get {
_tolerance = _tolerance.Percent;
return this;
}
}
public override string Description {
get {
StringBuilder stringBuilder = new StringBuilder(MsgUtils.FormatValue(_expected));
if (_tolerance != null && _tolerance.HasVariance) {
stringBuilder.Append(" +/- ");
stringBuilder.Append(MsgUtils.FormatValue(_tolerance.Amount));
if (_tolerance.Mode != ToleranceMode.Linear) {
stringBuilder.Append(" ");
stringBuilder.Append(_tolerance.Mode.ToString());
}
}
return stringBuilder.ToString();
}
}
[System.Runtime.CompilerServices.NullableContext(0)]
public EqualNumericWithoutUsingConstraint(T expected)
: base(expected)
{
Guard.ArgumentValid(Numerics.IsNumericType(typeof(T)), "EqualNumericWithoutUsingConstraint<T> may only be used with numeric types.", "T");
_expected = expected;
}
[System.Runtime.CompilerServices.NullableContext(0)]
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
1,
0
})]
public EqualNumericWithoutUsingConstraint<T> Within(T amount)
{
if (!_tolerance.IsUnsetOrDefault)
throw new InvalidOperationException("Within modifier may appear only once in a constraint expression");
_tolerance = new Tolerance(amount);
return this;
}
[System.Runtime.CompilerServices.NullableContext(0)]
[return: System.Runtime.CompilerServices.Nullable(1)]
public ConstraintResult ApplyTo(T actual)
{
bool hasSucceeded = Numerics.AreEqual((object)_expected, (object)actual, ref _tolerance);
return ConstraintResult(actual, hasSucceeded);
}
public override ConstraintResult ApplyTo<[System.Runtime.CompilerServices.Nullable(2)] TActual>(TActual actual)
{
bool hasSucceeded;
if (actual == null)
hasSucceeded = false;
else if (((object)actual) is T) {
T val = actual as T;
hasSucceeded = Numerics.AreEqual((object)this._expected, (object)val, ref this._tolerance);
} else {
IEquatable<T> equatable = actual as IEquatable<T>;
if (equatable != null) {
if (!this._tolerance.IsUnsetOrDefault)
throw new InvalidOperationException("Cannot use Tolerance with IEquatable<>.");
hasSucceeded = equatable.Equals(this._expected);
} else {
if (!Numerics.IsNumericType(typeof(TActual)))
return ((Constraint)new EqualConstraint(this._expected)).ApplyTo<TActual>(actual);
hasSucceeded = Numerics.AreEqual((object)actual, (object)this._expected, ref this._tolerance);
}
}
return ConstraintResult(actual, hasSucceeded);
}
private ConstraintResult ConstraintResult<[System.Runtime.CompilerServices.Nullable(2)] TActual>(TActual actual, bool hasSucceeded)
{
return new EqualConstraintResult(this, actual, this._tolerance, hasSucceeded);
}
}
}