public void TestModesCanOnlyBeUsedOnce() { var tolerance = new Tolerance(5); Assert.That(() => tolerance.Percent.Ulps, Throws.TypeOf<InvalidOperationException>().With.Message.ContainsSubstring("multiple tolerance modes")); }
public void SetUp() { tenPercent = new Tolerance(10.0).Percent; zeroTolerance = new Tolerance(0); }
public void SetUp() { tenPercent = new Tolerance(10.0).Percent; zeroTolerance = Tolerance.Exact; }
/// <summary> /// Test two numeric values for equality, performing the usual numeric /// conversions and using a provided or default tolerance. If the tolerance /// provided is Empty, this method may set it to a default tolerance. /// </summary> /// <param name="expected">The expected value</param> /// <param name="actual">The actual value</param> /// <param name="tolerance">A reference to the tolerance in effect</param> /// <returns>True if the values are equal</returns> public static bool AreEqual( object expected, object actual, ref Tolerance tolerance ) { if ( expected is double || actual is double ) return AreEqual( Convert.ToDouble(expected), Convert.ToDouble(actual), ref tolerance ); if ( expected is float || actual is float ) return AreEqual( Convert.ToSingle(expected), Convert.ToSingle(actual), ref tolerance ); if (tolerance.Mode == ToleranceMode.Ulps) throw new InvalidOperationException("Ulps may only be specified for floating point arguments"); if ( expected is decimal || actual is decimal ) return AreEqual( Convert.ToDecimal(expected), Convert.ToDecimal(actual), tolerance ); if (expected is ulong || actual is ulong) return AreEqual(Convert.ToUInt64(expected), Convert.ToUInt64(actual), tolerance ); if ( expected is long || actual is long ) return AreEqual( Convert.ToInt64(expected), Convert.ToInt64(actual), tolerance ); if ( expected is uint || actual is uint ) return AreEqual( Convert.ToUInt32(expected), Convert.ToUInt32(actual), tolerance ); return AreEqual( Convert.ToInt32(expected), Convert.ToInt32(actual), tolerance ); }
/// <summary> /// Construct an EqualConstraintResult /// </summary> public EqualConstraintResult(EqualConstraint constraint, object actual, bool hasSucceeded) : base(constraint, actual, hasSucceeded) { this.expectedValue = constraint.Arguments[0]; this.tolerance = constraint.Tolerance; this.caseInsensitive = constraint.CaseInsensitive; this.clipStrings = constraint.ClipStrings; this.failurePoints = constraint.FailurePoints; }
private bool ObjectsEqual(object expected, object actual, ref Tolerance tolerance) { if (expected == null && actual == null) { return(true); } if (expected == null || actual == null) { return(false); } if (object.ReferenceEquals(expected, actual)) { return(true); } Type xType = expected.GetType(); Type yType = actual.GetType(); EqualityAdapter externalComparer = GetExternalComparer(expected, actual); if (externalComparer != null) { return(externalComparer.AreEqual(expected, actual)); } if (xType.IsArray && yType.IsArray && !compareAsCollection) { return(ArraysEqual((Array)expected, (Array)actual, ref tolerance)); } if (expected is IDictionary && actual is IDictionary) { return(DictionariesEqual((IDictionary)expected, (IDictionary)actual, ref tolerance)); } // Issue #70 - EquivalentTo isn't compatible with IgnoreCase for dictionaries if (expected is DictionaryEntry && actual is DictionaryEntry) { return(DictionaryEntriesEqual((DictionaryEntry)expected, (DictionaryEntry)actual, ref tolerance)); } #if CLR_2_0 || CLR_4_0 // IDictionary<,> will eventually try to compare it's key value pairs when using CollectionTally if (xType.IsGenericType && xType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>) && yType.IsGenericType && yType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>)) { Tolerance keyTolerance = new Tolerance(0); object xKey = xType.GetProperty("Key").GetValue(expected, null); object yKey = yType.GetProperty("Key").GetValue(actual, null); object xValue = xType.GetProperty("Value").GetValue(expected, null); object yValue = yType.GetProperty("Value").GetValue(actual, null); return(AreEqual(xKey, yKey, ref keyTolerance) && AreEqual(xValue, yValue, ref tolerance)); } #endif if (expected is IEnumerable && actual is IEnumerable && !(expected is string && actual is string)) { return(EnumerablesEqual((IEnumerable)expected, (IEnumerable)actual, ref tolerance)); } if (expected is string && actual is string) { return(StringsEqual((string)expected, (string)actual)); } if (expected is Stream && actual is Stream) { return(StreamsEqual((Stream)expected, (Stream)actual)); } if (expected is char && actual is char) { return(CharsEqual((char)expected, (char)actual)); } if (expected is DirectoryInfo && actual is DirectoryInfo) { return(DirectoriesEqual((DirectoryInfo)expected, (DirectoryInfo)actual)); } if (Numerics.IsNumericType(expected) && Numerics.IsNumericType(actual)) { return(Numerics.AreEqual(expected, actual, ref tolerance)); } if (tolerance != null && tolerance.Value is TimeSpan) { TimeSpan amount = (TimeSpan)tolerance.Value; if (expected is DateTime && actual is DateTime) { return(((DateTime)expected - (DateTime)actual).Duration() <= amount); } #if CLR_2_0 || CLR_4_0 if (expected is DateTimeOffset && actual is DateTimeOffset) { return(((DateTimeOffset)expected - (DateTimeOffset)actual).Duration() <= amount); } #endif if (expected is TimeSpan && actual is TimeSpan) { return(((TimeSpan)expected - (TimeSpan)actual).Duration() <= amount); } } #if CLR_2_0 || CLR_4_0 if (FirstImplementsIEquatableOfSecond(xType, yType)) { return(InvokeFirstIEquatableEqualsSecond(expected, actual)); } else if (FirstImplementsIEquatableOfSecond(yType, xType)) { return(InvokeFirstIEquatableEqualsSecond(actual, expected)); } #endif return(expected.Equals(actual)); }
/// <summary> /// Compares two collection members for equality /// </summary> protected bool ItemsEqual(object x, object y) { Tolerance tolerance = Tolerance.Zero; return(comparer.AreEqual(x, y, ref tolerance)); }
public override void DisplayDifferences(object expected, object actual, Tolerance tolerance) { this.expected = expected; this.actual = actual; this.tolerance = tolerance; }
private bool DictionaryEntriesEqual(DictionaryEntry x, DictionaryEntry y, ref Tolerance tolerance) { var keyTolerance = Tolerance.Exact; return(AreEqual(x.Key, y.Key, ref keyTolerance) && AreEqual(x.Value, y.Value, ref tolerance)); }
/// <summary> /// Test two numeric values for equality, performing the usual numeric /// conversions and using a provided or default tolerance. If the tolerance /// provided is Empty, this method may set it to a default tolerance. /// </summary> /// <param name="expected">The expected value</param> /// <param name="actual">The actual value</param> /// <param name="tolerance">A reference to the tolerance in effect</param> /// <returns>True if the values are equal</returns> public static bool AreEqual(object expected, object actual, ref Tolerance tolerance) { bool _double = (expected is double || actual is double); #if XAMCORE_2_0 && (MONOTOUCH || MONOMAC) if (!_double && (IntPtr.Size == 8)) _double = (expected is nfloat || actual is nfloat); #endif if (_double) return AreEqual(Convert.ToDouble(expected), Convert.ToDouble(actual), ref tolerance); bool _float = (expected is float || actual is float); #if XAMCORE_2_0 && (MONOTOUCH || MONOMAC) if (!_float && (IntPtr.Size == 4)) _float = (expected is nfloat || actual is nfloat); #endif if (_float) return AreEqual(Convert.ToSingle(expected), Convert.ToSingle(actual), ref tolerance); if (tolerance.Mode == ToleranceMode.Ulps) throw new InvalidOperationException("Ulps may only be specified for floating point arguments"); if (expected is decimal || actual is decimal) return AreEqual(Convert.ToDecimal(expected), Convert.ToDecimal(actual), tolerance); bool _ulong = (expected is ulong || actual is ulong); #if XAMCORE_2_0 && (MONOTOUCH || MONOMAC) if (!_ulong && (IntPtr.Size == 8)) _ulong = (expected is nuint || actual is nuint); #endif if (_ulong) return AreEqual(Convert.ToUInt64(expected), Convert.ToUInt64(actual), tolerance); bool _long = (expected is long || actual is long); #if XAMCORE_2_0 && (MONOTOUCH || MONOMAC) if (!_long && (IntPtr.Size == 8)) _long = (expected is nint || actual is nint); #endif if (_long) return AreEqual(Convert.ToInt64(expected), Convert.ToInt64(actual), tolerance); bool _uint = (expected is uint || actual is uint); #if XAMCORE_2_0 && (MONOTOUCH || MONOMAC) if (!_uint && (IntPtr.Size == 4)) _uint = (expected is nuint || actual is nuint); #endif if (_uint) return AreEqual(Convert.ToUInt32(expected), Convert.ToUInt32(actual), tolerance); // int or nint on 32bits archs return AreEqual(Convert.ToInt32(expected), Convert.ToInt32(actual), tolerance); }
/// <summary> /// Display Expected and Actual lines for given values, including /// a tolerance value on the expected line. /// </summary> /// <param name="expected">The expected value</param> /// <param name="actual">The actual value causing the failure</param> /// <param name="tolerance">The tolerance within which the test was made</param> public override void DisplayDifferences(object expected, object actual, Tolerance tolerance) { WriteExpectedLine(expected, tolerance); WriteActualLine(actual); }
/// <summary> /// Compares two objects for equality within a tolerance. /// </summary> public bool AreEqual(object x, object y, ref Tolerance tolerance) { return(AreEqual(x, y, ref tolerance, new ComparisonState(true))); }
private static bool AreEqual(decimal expected, decimal actual, Tolerance tolerance) { switch (tolerance.Mode) { case ToleranceMode.Unset: return expected.Equals(actual); case ToleranceMode.Linear: decimal decimalTolerance = Convert.ToDecimal(tolerance.Value); if (decimalTolerance > 0m) return Math.Abs(expected - actual) <= decimalTolerance; return expected.Equals(actual); case ToleranceMode.Percent: if (expected == 0m) return expected.Equals(actual); double relativeError = Math.Abs( (double)(expected - actual) / (double)expected); return (relativeError <= Convert.ToDouble(tolerance.Value) / 100.0); default: throw new ArgumentException("Unknown tolerance mode specified", "mode"); } }
/// <summary> /// Compares two objects for equality within a tolerance. /// </summary> public bool AreEqual(object x, object y, ref Tolerance tolerance, bool topLevelComparison) { return(AreEqual(x, y, ref tolerance, new ComparisonState(topLevelComparison))); }
/// <summary> /// Compares two objects for equality within a tolerance. /// </summary> public bool AreEqual(object x, object y, ref Tolerance tolerance) { return(AreEqual(x, y, ref tolerance, true)); }
/// <summary> /// Test two numeric values for equality, performing the usual numeric /// conversions and using a provided or default tolerance. If the tolerance /// provided is Empty, this method may set it to a default tolerance. /// </summary> /// <param name="expected">The expected value</param> /// <param name="actual">The actual value</param> /// <param name="tolerance">A reference to the tolerance in effect</param> /// <returns>True if the values are equal</returns> public static bool AreEqual(object expected, object actual, ref Tolerance tolerance) { bool _double = (expected is double || actual is double); if (!_double && (IntPtr.Size == 8)) { _double = (expected.GetType() == nfloatType || actual.GetType() == nfloatType); } if (_double) { return(AreEqual(Convert.ToDouble(expected), Convert.ToDouble(actual), ref tolerance)); } bool _float = (expected is float || actual is float); if (!_float && (IntPtr.Size == 4)) { _float = (expected.GetType() == nfloatType || actual.GetType() == nfloatType); } if (_float) { return(AreEqual(Convert.ToSingle(expected), Convert.ToSingle(actual), ref tolerance)); } if (tolerance.Mode == ToleranceMode.Ulps) { throw new InvalidOperationException("Ulps may only be specified for floating point arguments"); } if (expected is decimal || actual is decimal) { return(AreEqual(Convert.ToDecimal(expected), Convert.ToDecimal(actual), tolerance)); } bool _ulong = (expected is ulong || actual is ulong); if (!_ulong && (IntPtr.Size == 8)) { _ulong = (expected.GetType() == nuintType || actual.GetType() == nuintType); } if (_ulong) { return(AreEqual(Convert.ToUInt64(expected), Convert.ToUInt64(actual), tolerance)); } bool _long = (expected is long || actual is long); if (!_long && (IntPtr.Size == 8)) { _long = (expected.GetType() == nintType || actual.GetType() == nintType); } if (_long) { return(AreEqual(Convert.ToInt64(expected), Convert.ToInt64(actual), tolerance)); } bool _uint = (expected is uint || actual is uint); if (!_uint && (IntPtr.Size == 4)) { _uint = (expected.GetType() == nuintType || actual.GetType() == nuintType); } if (_uint) { return(AreEqual(Convert.ToUInt32(expected), Convert.ToUInt32(actual), tolerance)); } // int or nint on 32bits archs return(AreEqual(Convert.ToInt32(expected), Convert.ToInt32(actual), tolerance)); }
public void SetUp() { absoluteTolerance = new Tolerance(0.1); tenPercent = new Tolerance(10.0).Percent; zeroTolerance = Tolerance.Exact; }
/// <summary> /// Display Expected and Actual lines for given values, including /// a tolerance value on the Expected line. /// </summary> /// <param name="expected">The expected value</param> /// <param name="actual">The actual value causing the failure</param> /// <param name="tolerance">The tolerance within which the test was made</param> public abstract void DisplayDifferences(object expected, object actual, Tolerance tolerance);
public void TestNumericToleranceRequired() { var tolerance = new Tolerance("Five"); Assert.That(() => tolerance.Percent, Throws.TypeOf<InvalidOperationException>().With.Message.ContainsSubstring("numeric tolerance is required")); }
public void SetUp() { tolerance = Tolerance.Empty; comparer = new NUnitComparer(); }
public void Setup() { tolerance = Tolerance.Empty; }
private static bool AreEqual(int expected, int actual, Tolerance tolerance) { switch (tolerance.Mode) { case ToleranceMode.None: return expected.Equals(actual); case ToleranceMode.Linear: int intTolerance = Convert.ToInt32(tolerance.Value); if (intTolerance > 0) return Math.Abs(expected - actual) <= intTolerance; return expected.Equals(actual); case ToleranceMode.Percent: if (expected == 0) return expected.Equals(actual); double relativeError = Math.Abs( (double)(expected - actual) / (double)expected); return (relativeError <= Convert.ToDouble(tolerance.Value) / 100.0); default: throw new ArgumentException("Unknown tolerance mode specified", "mode"); } }
/// <summary> /// Protected function overridden by derived class to actually perform the comparison /// </summary> protected abstract bool PerformComparison(ComparisonAdapter comparer, object actual, object expected, Tolerance tolerance);
/// <summary> /// Compares two objects for equality within a tolerance. /// </summary> public bool AreEqual(object x, object y, ref Tolerance tolerance) { this.failurePoints = new List <FailurePoint>(); if (x == null && y == null) { return(true); } if (x == null || y == null) { return(false); } if (object.ReferenceEquals(x, y)) { return(true); } Type xType = x.GetType(); Type yType = y.GetType(); Type xGenericTypeDefinition = xType.GetTypeInfo().IsGenericType ? xType.GetGenericTypeDefinition() : null; Type yGenericTypeDefinition = yType.GetTypeInfo().IsGenericType ? yType.GetGenericTypeDefinition() : null; EqualityAdapter externalComparer = GetExternalComparer(x, y); if (externalComparer != null) { return(externalComparer.AreEqual(x, y)); } if (xType.IsArray && yType.IsArray && !compareAsCollection) { return(ArraysEqual((Array)x, (Array)y, ref tolerance)); } if (x is IDictionary && y is IDictionary) { return(DictionariesEqual((IDictionary)x, (IDictionary)y, ref tolerance)); } // Issue #70 - EquivalentTo isn't compatible with IgnoreCase for dictionaries if (x is DictionaryEntry && y is DictionaryEntry) { return(DictionaryEntriesEqual((DictionaryEntry)x, (DictionaryEntry)y, ref tolerance)); } // IDictionary<,> will eventually try to compare it's key value pairs when using CollectionTally if (xGenericTypeDefinition == typeof(KeyValuePair <,>) && yGenericTypeDefinition == typeof(KeyValuePair <,>)) { var keyTolerance = Tolerance.Exact; object xKey = xType.GetProperty("Key").GetValue(x, null); object yKey = yType.GetProperty("Key").GetValue(y, null); object xValue = xType.GetProperty("Value").GetValue(x, null); object yValue = yType.GetProperty("Value").GetValue(y, null); return(AreEqual(xKey, yKey, ref keyTolerance) && AreEqual(xValue, yValue, ref tolerance)); } if (x is string && y is string) { return(StringsEqual((string)x, (string)y)); } if (x is Stream && y is Stream) { return(StreamsEqual((Stream)x, (Stream)y)); } if (x is char && y is char) { return(CharsEqual((char)x, (char)y)); } #if !PORTABLE if (x is DirectoryInfo && y is DirectoryInfo) { return(DirectoriesEqual((DirectoryInfo)x, (DirectoryInfo)y)); } #endif if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) { return(Numerics.AreEqual(x, y, ref tolerance)); } if (x is DateTimeOffset && y is DateTimeOffset) { bool result; DateTimeOffset xAsOffset = (DateTimeOffset)x; DateTimeOffset yAsOffset = (DateTimeOffset)y; if (tolerance != null && tolerance.Amount is TimeSpan) { TimeSpan amount = (TimeSpan)tolerance.Amount; result = (xAsOffset - yAsOffset).Duration() <= amount; } else { result = xAsOffset == yAsOffset; } if (result && WithSameOffset) { result = xAsOffset.Offset == yAsOffset.Offset; } return(result); } if (tolerance != null && tolerance.Amount is TimeSpan) { TimeSpan amount = (TimeSpan)tolerance.Amount; if (x is DateTime && y is DateTime) { return(((DateTime)x - (DateTime)y).Duration() <= amount); } if (x is TimeSpan && y is TimeSpan) { return(((TimeSpan)x - (TimeSpan)y).Duration() <= amount); } } if (!compareAsCollection) { MethodInfo equals = FirstImplementsIEquatableOfSecond(xType, yType); if (equals != null) { return(InvokeFirstIEquatableEqualsSecond(x, y, equals)); } if (xType != yType && (equals = FirstImplementsIEquatableOfSecond(yType, xType)) != null) { return(InvokeFirstIEquatableEqualsSecond(y, x, equals)); } } if (x is IEnumerable && y is IEnumerable) { return(EnumerablesEqual((IEnumerable)x, (IEnumerable)y, ref tolerance)); } return(x.Equals(y)); }
/// <summary> /// Perform the comparison /// </summary> protected override bool PerformComparison(ComparisonAdapter comparer, object actual, object expected, Tolerance tolerance) { return(comparer.Compare(actual, tolerance.ApplyToValue(expected).LowerBound) > 0); }
private bool ObjectsEqual(object expected, object actual, ref Tolerance tolerance) { if (expected == null && actual == null) { return(true); } if (expected == null || actual == null) { return(false); } if (object.ReferenceEquals(expected, actual)) { return(true); } Type xType = expected.GetType(); Type yType = actual.GetType(); EqualityAdapter externalComparer = GetExternalComparer(expected, actual); if (externalComparer != null) { return(externalComparer.AreEqual(expected, actual)); } if (xType.IsArray && yType.IsArray && !compareAsCollection) { return(ArraysEqual((Array)expected, (Array)actual, ref tolerance)); } if (expected is IDictionary && actual is IDictionary) { return(DictionariesEqual((IDictionary)expected, (IDictionary)actual, ref tolerance)); } if (expected is IEnumerable && actual is IEnumerable && !(expected is string && actual is string)) { return(EnumerablesEqual((IEnumerable)expected, (IEnumerable)actual, ref tolerance)); } if (expected is string && actual is string) { return(StringsEqual((string)expected, (string)actual)); } if (expected is Stream && actual is Stream) { return(StreamsEqual((Stream)expected, (Stream)actual)); } #if !PORTABLE if (expected is DirectoryInfo && actual is DirectoryInfo) { return(DirectoriesEqual((DirectoryInfo)expected, (DirectoryInfo)actual)); } #endif if (Numerics.IsNumericType(expected) && Numerics.IsNumericType(actual)) { return(Numerics.AreEqual(expected, actual, ref tolerance)); } if (tolerance != null && tolerance.Value is TimeSpan) { TimeSpan amount = (TimeSpan)tolerance.Value; if (expected is DateTime && actual is DateTime) { return(((DateTime)expected - (DateTime)actual).Duration() <= amount); } if (expected is TimeSpan && actual is TimeSpan) { return(((TimeSpan)expected - (TimeSpan)actual).Duration() <= amount); } } #if (CLR_2_0 || CLR_4_0) && !NETCF if (FirstImplementsIEquatableOfSecond(xType, yType)) { return(InvokeFirstIEquatableEqualsSecond(expected, actual)); } else if (FirstImplementsIEquatableOfSecond(yType, xType)) { return(InvokeFirstIEquatableEqualsSecond(actual, expected)); } #endif return(expected.Equals(actual)); }
/// <summary> /// Compares two objects for equality within a tolerance. /// </summary> public bool AreEqual(object x, object y, ref Tolerance tolerance) { this.failurePoints = new ObjectList(); if (x == null && y == null) { return(true); } if (x == null || y == null) { return(false); } if (object.ReferenceEquals(x, y)) { return(true); } Type xType = x.GetType(); Type yType = y.GetType(); EqualityAdapter externalComparer = GetExternalComparer(x, y); if (externalComparer != null) { return(externalComparer.AreEqual(x, y)); } if (xType.IsArray && yType.IsArray && !compareAsCollection) { return(ArraysEqual((Array)x, (Array)y, ref tolerance)); } if (x is IDictionary && y is IDictionary) { return(DictionariesEqual((IDictionary)x, (IDictionary)y, ref tolerance)); } //if (x is ICollection && y is ICollection) // return CollectionsEqual((ICollection)x, (ICollection)y, ref tolerance); if (x is IEnumerable && y is IEnumerable && !(x is string && y is string)) { return(EnumerablesEqual((IEnumerable)x, (IEnumerable)y, ref tolerance)); } if (x is string && y is string) { return(StringsEqual((string)x, (string)y)); } if (x is Stream && y is Stream) { return(StreamsEqual((Stream)x, (Stream)y)); } if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) { return(Numerics.AreEqual(x, y, ref tolerance)); } if (tolerance != null && tolerance.Value is TimeSpan) { TimeSpan amount = (TimeSpan)tolerance.Value; if (x is DateTime && y is DateTime) { return(((DateTime)x - (DateTime)y).Duration() <= amount); } if (x is TimeSpan && y is TimeSpan) { return(((TimeSpan)x - (TimeSpan)y).Duration() <= amount); } } #if (CLR_2_0 || CLR_4_0) && !NETCF if (FirstImplementsIEquatableOfSecond(xType, yType)) { return(InvokeFirstIEquatableEqualsSecond(x, y)); } else if (FirstImplementsIEquatableOfSecond(yType, xType)) { return(InvokeFirstIEquatableEqualsSecond(y, x)); } #endif return(x.Equals(y)); }
/// <summary> /// Write the generic 'Expected' line for a given value /// and tolerance. /// </summary> /// <param name="expected">The expected value</param> /// <param name="tolerance">The tolerance within which the test was made</param> private void WriteExpectedLine(object expected, Tolerance tolerance) { Write(Pfx_Expected); Write(MsgUtils.FormatValue(expected)); if (tolerance != null && !tolerance.IsEmpty) { Write(" +/- "); Write(MsgUtils.FormatValue(tolerance.Value)); if (tolerance.Mode != ToleranceMode.Linear) Write(" {0}", tolerance.Mode); } WriteLine(); }
/// <summary> /// Compares two objects for equality within a tolerance. /// </summary> public bool AreEqual(object x, object y, ref Tolerance tolerance) { this.failurePoints = new List<FailurePoint>(); if (x == null && y == null) return true; if (x == null || y == null) return false; if (object.ReferenceEquals(x, y)) return true; Type xType = x.GetType(); Type yType = y.GetType(); EqualityAdapter externalComparer = GetExternalComparer(x, y); if (externalComparer != null) return externalComparer.AreEqual(x, y); if (xType.IsArray && yType.IsArray && !compareAsCollection) return ArraysEqual((Array)x, (Array)y, ref tolerance); if (x is IDictionary && y is IDictionary) return DictionariesEqual((IDictionary)x, (IDictionary)y, ref tolerance); // Issue #70 - EquivalentTo isn't compatible with IgnoreCase for dictionaries if (x is DictionaryEntry && y is DictionaryEntry) return DictionaryEntriesEqual((DictionaryEntry)x, (DictionaryEntry)y, ref tolerance); // IDictionary<,> will eventually try to compare it's key value pairs when using CollectionTally if (xType.IsGenericType && xType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>) && yType.IsGenericType && yType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>)) { var keyTolerance = Tolerance.Exact; object xKey = xType.GetProperty("Key").GetValue(x, null); object yKey = yType.GetProperty("Key").GetValue(y, null); object xValue = xType.GetProperty("Value").GetValue(x, null); object yValue = yType.GetProperty("Value").GetValue(y, null); return AreEqual(xKey, yKey, ref keyTolerance) && AreEqual(xValue, yValue, ref tolerance); } //if (x is ICollection && y is ICollection) // return CollectionsEqual((ICollection)x, (ICollection)y, ref tolerance); if (x is IEnumerable && y is IEnumerable && !(x is string && y is string)) return EnumerablesEqual((IEnumerable)x, (IEnumerable)y, ref tolerance); if (x is string && y is string) return StringsEqual((string)x, (string)y); if (x is Stream && y is Stream) return StreamsEqual((Stream)x, (Stream)y); if ( x is char && y is char ) return CharsEqual( (char)x, (char)y ); if (x is DirectoryInfo && y is DirectoryInfo) return DirectoriesEqual((DirectoryInfo)x, (DirectoryInfo)y); if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) return Numerics.AreEqual(x, y, ref tolerance); if (tolerance != null && tolerance.Value is TimeSpan) { TimeSpan amount = (TimeSpan)tolerance.Value; if (x is DateTime && y is DateTime) return ((DateTime)x - (DateTime)y).Duration() <= amount; #if !NETCF if (x is DateTimeOffset && y is DateTimeOffset) return ((DateTimeOffset)x - (DateTimeOffset)y).Duration() <= amount; #endif if (x is TimeSpan && y is TimeSpan) return ((TimeSpan)x - (TimeSpan)y).Duration() <= amount; } if (FirstImplementsIEquatableOfSecond(xType, yType)) return InvokeFirstIEquatableEqualsSecond(x, y); else if (xType != yType && FirstImplementsIEquatableOfSecond(yType, xType)) return InvokeFirstIEquatableEqualsSecond(y, x); return x.Equals(y); }
private bool ItemsEqual(object expected, object actual) { Tolerance tolerance = Tolerance.Empty; return(comparer.AreEqual(expected, actual, ref tolerance)); }
/// <summary> /// Compares two objects for equality within a tolerance. /// </summary> public bool AreEqual(object x, object y, ref Tolerance tolerance) { this.failurePoints = new List<FailurePoint>(); if (x == null && y == null) return true; if (x == null || y == null) return false; if (object.ReferenceEquals(x, y)) return true; Type xType = x.GetType(); Type yType = y.GetType(); EqualityAdapter externalComparer = GetExternalComparer(x, y); if (externalComparer != null) return externalComparer.AreEqual(x, y); if (xType.IsArray && yType.IsArray && !compareAsCollection) return ArraysEqual((Array)x, (Array)y, ref tolerance); if (x is IDictionary && y is IDictionary) return DictionariesEqual((IDictionary)x, (IDictionary)y, ref tolerance); //if (x is ICollection && y is ICollection) // return CollectionsEqual((ICollection)x, (ICollection)y, ref tolerance); if (x is IEnumerable && y is IEnumerable && !(x is string && y is string)) return EnumerablesEqual((IEnumerable)x, (IEnumerable)y, ref tolerance); if (x is string && y is string) return StringsEqual((string)x, (string)y); if (x is Stream && y is Stream) return StreamsEqual((Stream)x, (Stream)y); if (x is DirectoryInfo && y is DirectoryInfo) return DirectoriesEqual((DirectoryInfo)x, (DirectoryInfo)y); if (Numerics.IsNumericType(x) && Numerics.IsNumericType(y)) return Numerics.AreEqual(x, y, ref tolerance); if (tolerance != null && tolerance.Value is TimeSpan) { TimeSpan amount = (TimeSpan)tolerance.Value; if (x is DateTime && y is DateTime) return ((DateTime)x - (DateTime)y).Duration() <= amount; if (x is TimeSpan && y is TimeSpan) return ((TimeSpan)x - (TimeSpan)y).Duration() <= amount; } if (FirstImplementsIEquatableOfSecond(xType, yType)) return InvokeFirstIEquatableEqualsSecond(x, y); else if (xType != yType && FirstImplementsIEquatableOfSecond(yType, xType)) return InvokeFirstIEquatableEqualsSecond(y, x); return x.Equals(y); }
private bool DictionaryEntriesEqual(DictionaryEntry x, DictionaryEntry y, ref Tolerance tolerance) { Tolerance keyTolerance = new Tolerance(0); return(AreEqual(x.Key, y.Key, ref keyTolerance) && AreEqual(x.Value, y.Value, ref tolerance)); }
private bool DictionariesEqual(IDictionary x, IDictionary y, ref Tolerance tolerance) { if (x.Count != y.Count) return false; CollectionTally tally = new CollectionTally(this, x.Keys); if (!tally.TryRemove(y.Keys) || tally.Count > 0) return false; foreach (object key in x.Keys) if (!AreEqual(x[key], y[key], ref tolerance)) return false; return true; }
private bool CollectionsEqual(ICollection x, ICollection y, ref Tolerance tolerance) { IEnumerator expectedEnum = null; IEnumerator actualEnum = null; try { expectedEnum = x.GetEnumerator(); actualEnum = y.GetEnumerator(); int count; for (count = 0; ; count++) { bool expectedHasData = expectedEnum.MoveNext(); bool actualHasData = actualEnum.MoveNext(); if (!expectedHasData && !actualHasData) return true; if (expectedHasData != actualHasData || !AreEqual(expectedEnum.Current, actualEnum.Current, ref tolerance)) { FailurePoint fp = new FailurePoint(); fp.Position = count; fp.ExpectedHasData = expectedHasData; if (expectedHasData) fp.ExpectedValue = expectedEnum.Current; fp.ActualHasData = actualHasData; if (actualHasData) fp.ActualValue = actualEnum.Current; failurePoints.Insert(0, fp); return false; } } } finally { var expectedDisposable = expectedEnum as IDisposable; if (expectedDisposable != null) expectedDisposable.Dispose(); var actualDisposable = actualEnum as IDisposable; if (actualDisposable != null) actualDisposable.Dispose(); } }
private bool DictionaryEntriesEqual(DictionaryEntry x, DictionaryEntry y, ref Tolerance tolerance) { var keyTolerance = Tolerance.Exact; return AreEqual(x.Key, y.Key, ref keyTolerance) && AreEqual(x.Value, y.Value, ref tolerance); }
/// <summary> /// Display Expected and Actual lines for given _values, including /// a tolerance value on the expected line. /// </summary> /// <param name="expected">The expected value</param> /// <param name="actual">The actual value causing the failure</param> /// <param name="tolerance">The tolerance within which the test was made</param> public override void DisplayDifferences(object expected, object actual, Tolerance tolerance) { if (expected != null && actual != null && expected.GetType() != actual.GetType() && MsgUtils.FormatValue(expected) == MsgUtils.FormatValue(actual) ) { _sameValDiffTypes = true; ResolveTypeNameDifference(expected, actual, out _expectedType, out _actualType); } WriteExpectedLine(expected, tolerance); WriteActualLine(actual); }
/// <summary> /// Helper method to compare two arrays /// </summary> private bool ArraysEqual(Array x, Array y, ref Tolerance tolerance) { int rank = x.Rank; if (rank != y.Rank) return false; for (int r = 1; r < rank; r++) if (x.GetLength(r) != y.GetLength(r)) return false; return EnumerablesEqual((IEnumerable)x, (IEnumerable)y, ref tolerance); }
/// <summary> /// Write the generic 'Expected' line for a given value /// and tolerance. /// </summary> /// <param name="expected">The expected value</param> /// <param name="tolerance">The tolerance within which the test was made</param> private void WriteExpectedLine(object expected, Tolerance tolerance) { Write(Pfx_Expected); Write(MsgUtils.FormatValue(expected)); if (_sameValDiffTypes) { Write(_expectedType); } if (tolerance != null && !tolerance.IsUnsetOrDefault) { Write(" +/- "); Write(MsgUtils.FormatValue(tolerance.Value)); if (tolerance.Mode != ToleranceMode.Linear) Write(" {0}", tolerance.Mode); } WriteLine(); }
private bool EnumerablesEqual(IEnumerable x, IEnumerable y, ref Tolerance tolerance) { IEnumerator expectedEnum = x.GetEnumerator(); IEnumerator actualEnum = y.GetEnumerator(); int count; for (count = 0; ; count++) { bool expectedHasData = expectedEnum.MoveNext(); bool actualHasData = actualEnum.MoveNext(); if (!expectedHasData && !actualHasData) return true; if (expectedHasData != actualHasData || !AreEqual(expectedEnum.Current, actualEnum.Current, ref tolerance)) { FailurePoint fp = new FailurePoint(); fp.Position = count; fp.ExpectedHasData = expectedHasData; if (expectedHasData) fp.ExpectedValue = expectedEnum.Current; fp.ActualHasData = actualHasData; if (actualHasData) fp.ActualValue = actualEnum.Current; failurePoints.Insert(0, fp); return false; } } }
public void Setup() { tolerance = Tolerance.Zero; comparer = new NUnitEqualityComparer(); }
/// <summary> /// Write the generic 'Expected' line for a given value /// and tolerance. /// </summary> /// <param name="expected">The expected value</param> /// <param name="tolerance">The tolerance within which the test was made</param> private void WriteExpectedLine(object expected, Tolerance tolerance) { Write(Pfx_Expected); WriteExpectedValue(expected); if (tolerance != null && !tolerance.IsEmpty) { WriteConnector("+/-"); WriteExpectedValue(tolerance.Value); } WriteLine(); }
private static bool AreEqual(float expected, float actual, ref Tolerance tolerance) { if (float.IsNaN(expected) && float.IsNaN(actual)) return true; // handle infinity specially since subtracting two infinite _values gives // NaN and the following test fails. mono also needs NaN to be handled // specially although ms.net could use either method. if (float.IsInfinity(expected) || float.IsNaN(expected) || float.IsNaN(actual)) { return expected.Equals(actual); } if (tolerance.IsEmpty && GlobalSettings.DefaultFloatingPointTolerance > 0.0d) tolerance = new Tolerance(GlobalSettings.DefaultFloatingPointTolerance); switch (tolerance.Mode) { case ToleranceMode.None: return expected.Equals(actual); case ToleranceMode.Linear: return Math.Abs(expected - actual) <= Convert.ToDouble(tolerance.Value); case ToleranceMode.Percent: if (expected == 0.0f) return expected.Equals(actual); float relativeError = Math.Abs((expected - actual) / expected); return (relativeError <= Convert.ToSingle(tolerance.Value) / 100.0f); case ToleranceMode.Ulps: return FloatingPointNumerics.AreAlmostEqualUlps( expected, actual, Convert.ToInt32(tolerance.Value)); default: throw new ArgumentException("Unknown tolerance mode specified", "mode"); } }
private static bool AreEqual(uint expected, uint actual, Tolerance tolerance) { switch (tolerance.Mode) { case ToleranceMode.None: return expected.Equals(actual); case ToleranceMode.Linear: uint uintTolerance = Convert.ToUInt32(tolerance.Value); if (uintTolerance > 0) { uint diff = expected >= actual ? expected - actual : actual - expected; return diff <= uintTolerance; } return expected.Equals(actual); case ToleranceMode.Percent: if (expected == 0u) return expected.Equals(actual); // Can't do a simple Math.Abs() here since it's unsigned uint difference = Math.Max(expected, actual) - Math.Min(expected, actual); double relativeError = Math.Abs((double)difference / (double)expected); return (relativeError <= Convert.ToDouble(tolerance.Value) / 100.0); default: throw new ArgumentException("Unknown tolerance mode specified", "mode"); } }