/// <summary> /// Display the failure information for two IEnumerables that did not match. /// </summary> /// <param name="writer">The MessageWriter on which to display</param> /// <param name="expected">The expected enumeration.</param> /// <param name="actual">The actual enumeration</param> /// <param name="depth">The depth of this failure in a set of nested collections</param> private void DisplayEnumerableDifferences(MessageWriter writer, IEnumerable expected, IEnumerable actual, int depth) { DisplayTypesAndSizes(writer, expected, actual, depth); if (failurePoints.Count > depth) { FailurePoint failurePoint = failurePoints[depth]; DisplayFailurePoint(writer, expected, actual, failurePoint, depth); if (failurePoint.ExpectedHasData && failurePoint.ActualHasData) { DisplayDifferences( writer, failurePoint.ExpectedValue, failurePoint.ActualValue, ++depth); } else if (failurePoint.ActualHasData) { writer.Write($" Extra: < {MsgUtils.FormatValue(failurePoint.ActualValue)}, ... >"); } else { writer.Write($" Missing: < {MsgUtils.FormatValue(failurePoint.ExpectedValue)}, ... >"); } } }
private bool EnumerablesEqual(IEnumerable expected, IEnumerable actual, ref Tolerance tolerance) { if (_recursionDetector.CheckRecursion(expected, actual)) { return(false); } IEnumerator expectedEnum = expected.GetEnumerator(); IEnumerator actualEnum = actual.GetEnumerator(); int count; for (count = 0; ; count++) { bool expectedHasData = expectedEnum.MoveNext(); bool actualHasData = actualEnum.MoveNext(); if (!expectedHasData && !actualHasData) { return(true); } if (expectedHasData != actualHasData || !ObjectsEqual(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); } } }
/// <summary> /// Displays a single line showing the point in the expected and actual /// arrays at which the comparison failed. If the arrays have different /// structures or dimensions, both values are shown. /// </summary> /// <param name="writer">The MessageWriter on which to display</param> /// <param name="expected">The expected array</param> /// <param name="actual">The actual array</param> /// <param name="failurePoint">Index of the failure point in the underlying collections</param> /// <param name="indent">The indentation level for the message line</param> private void DisplayFailurePoint(MessageWriter writer, IEnumerable expected, IEnumerable actual, FailurePoint failurePoint, int indent) { Array expectedArray = expected as Array; Array actualArray = actual as Array; int expectedRank = expectedArray != null ? expectedArray.Rank : 1; int actualRank = actualArray != null ? actualArray.Rank : 1; bool useOneIndex = expectedRank == actualRank; if (expectedArray != null && actualArray != null) { for (int r = 1; r < expectedRank && useOneIndex; r++) { if (expectedArray.GetLength(r) != actualArray.GetLength(r)) { useOneIndex = false; } } } int[] expectedIndices = MsgUtils.GetArrayIndicesFromCollectionIndex(expected, (int)failurePoint.Position); if (useOneIndex) { writer.WriteMessageLine(indent, ValuesDiffer_1, MsgUtils.GetArrayIndicesAsString(expectedIndices)); } else { int[] actualIndices = MsgUtils.GetArrayIndicesFromCollectionIndex(actual, (int)failurePoint.Position); writer.WriteMessageLine(indent, ValuesDiffer_2, MsgUtils.GetArrayIndicesAsString(expectedIndices), MsgUtils.GetArrayIndicesAsString(actualIndices)); } }