示例#1
0
 /// <summary>
 /// Add difference and perform a callback
 /// </summary>
 private void AddDifference(Difference difference)
 {
     Differences.Add(difference);
     DifferenceCallback(difference);
 }
示例#2
0
        /// <summary>
        /// Compare two objects
        /// </summary>
        /// <param name="object1">The first object to compare</param>
        /// <param name="object2">The second object to compare</param>
        /// <param name="breadCrumb">Where we are in the object hiearchy</param>
        private void Compare(object object1, object object2, string breadCrumb)
        {
            //If both null return true
            if (object1 == null && object2 == null)
                return;

            //Check if one of them is null
            if (object1 == null)
            {
                Difference difference = new Difference
                    {
                        ExpectedName = ExpectedName,
                        ActualName = ActualName,
                        PropertyName = breadCrumb,
                        Object1Value = "(null)",
                        Object2Value = NiceString(object2),
                        Object1 = null,
                        Object2 = new WeakReference(object2)
                    };

                AddDifference(difference);
                return;
            }

            if (object2 == null)
            {
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = breadCrumb,
                    Object1Value = NiceString(object1),
                    Object2Value = "(null)",
                    Object1 = new WeakReference(object1),
                    Object2 = null
                };

                AddDifference(difference);
                return;
            }

            Type t1 = object1.GetType();
            Type t2 = object2.GetType();

            //Objects must be the same type
            if (t1 != t2 && !IgnoreObjectTypes)
            {
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = breadCrumb,
                    Object1Value = t1.FullName,
                    Object2Value = t2.FullName,
                    ChildPropertyName = "GetType()",
                    MessagePrefix = "Different Types",
                    Object1 = new WeakReference(object1),
                    Object2 = new WeakReference(object2)
                };

                AddDifference(difference);
                return;
            }

            if (IsUseCustomTypeComparer(t1))
            {
                CompareWithCustomComparer(object1, object2, breadCrumb);
            }
            else if (IsTypeOfType(t1))
            {
                CompareType(object1, object2, breadCrumb);
            }
            else if (IsIpEndPoint(t1))
            {
                CompareIpEndPoint(object1, object2, breadCrumb);
            }
            #if !SILVERLIGHT
            else if (IsDataset(t1))
            {
                CompareDataset(object1, object2, breadCrumb);
            }
            else if (IsDataTable(t1))
            {
                CompareDataTable(object1, object2, breadCrumb);
            }
            else if (IsDataRow(t1))
            {
                CompareDataRow(object1, object2, breadCrumb);
            }
            #endif
            else if (IsIList(t1)) //This will do arrays, multi-dimensional arrays and generic lists
            {
                CompareIList(object1, object2, breadCrumb);
            }
            else if (IsHashSet(t1))
            {
                CompareHashSet(object1,object2,breadCrumb);
            }
            else if (IsIDictionary(t1))
            {
                CompareIDictionary(object1, object2, breadCrumb);
            }
            else if (IsEnum(t1))
            {
                CompareEnum(object1, object2, breadCrumb);
            }
            else if (IsPointer(t1))
            {
                ComparePointer(object1, object2, breadCrumb);
            }
            else if (IsUri(t1))
            {
                CompareUri(object1, object2, breadCrumb);
            }
            else if (IsSimpleType(t1))
            {
                CompareSimpleType(object1, object2, breadCrumb);
            }
            else if (IsClass(t1))
            {
                CompareClass(object1, object2, breadCrumb);
            }
            else if (IsTimespan(t1))
            {
                CompareTimespan(object1, object2, breadCrumb);
            }
            else if (IsStruct(t1))
            {
                CompareStruct(object1, object2, breadCrumb);
            }
            else
            {
                throw new NotSupportedException("Cannot compare object of type " + t1.Name);
            }
        }
示例#3
0
        /// <summary>
        /// Compare all tables and all rows in all tables
        /// </summary>
        /// <param name="object1"></param>
        /// <param name="object2"></param>
        /// <param name="breadCrumb"></param>
        private void CompareDataset(object object1, object object2, string breadCrumb)
        {
            DataSet dataSet1 = object1 as DataSet;
            DataSet dataSet2 = object2 as DataSet;

            //This should never happen, null check happens one level up
            if (dataSet1 == null || dataSet2 == null)
                return;

            //There must be the same amount of tables in the dataset
            if (dataSet1.Tables.Count != dataSet2.Tables.Count)
            {
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = breadCrumb,
                    Object1Value = dataSet1.Tables.Count.ToString(CultureInfo.InvariantCulture),
                    Object2Value = dataSet2.Tables.Count.ToString(CultureInfo.InvariantCulture),
                    ChildPropertyName = "Tables.Count",
                    Object1 = new WeakReference(object1),
                    Object2 = new WeakReference(object2)
                };

                AddDifference(difference);

                if (Differences.Count >= MaxDifferences)
                    return;
            }

            for (int i = 0; i < Math.Min(dataSet1.Tables.Count,dataSet2.Tables.Count); i++)
            {
                string currentBreadCrumb = AddBreadCrumb(breadCrumb, "Tables", string.Empty, dataSet1.Tables[i].TableName);

                CompareDataTable(dataSet1.Tables[i], dataSet2.Tables[i], currentBreadCrumb);

                if (Differences.Count >= MaxDifferences)
                    return;
            }
        }
示例#4
0
        /// <summary>
        /// Compare all rows in a data table
        /// </summary>
        /// <param name="object1"></param>
        /// <param name="object2"></param>
        /// <param name="breadCrumb"></param>
        private void CompareDataTable(object object1, object object2, string breadCrumb)
        {
            DataTable dataTable1 = object1 as DataTable;
            DataTable dataTable2 = object2 as DataTable;

            //This should never happen, null check happens one level up
            if (dataTable1 == null || dataTable2 == null)
                return;

            //Only compare specific table names
            if (ElementsToInclude.Count > 0 && !ElementsToInclude.Contains(dataTable1.TableName))
                return;

            //If we should ignore it, skip it
            if (ElementsToInclude.Count == 0 && ElementsToIgnore.Contains(dataTable1.TableName))
                return;

            //There must be the same amount of rows in the datatable
            if (dataTable1.Rows.Count != dataTable2.Rows.Count)
            {
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = breadCrumb,
                    Object1Value = dataTable1.Rows.Count.ToString(CultureInfo.InvariantCulture),
                    Object2Value = dataTable2.Rows.Count.ToString(CultureInfo.InvariantCulture),
                    ChildPropertyName = "Rows.Count",
                    Object1 = new WeakReference(object1),
                    Object2 = new WeakReference(object2)
                };

                AddDifference(difference);

                if (Differences.Count >= MaxDifferences)
                    return;
            }

            //There must be the same amount of columns in the datatable
            if (dataTable1.Columns.Count != dataTable2.Columns.Count)
            {
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = breadCrumb,
                    Object1Value = dataTable1.Columns.Count.ToString(CultureInfo.InvariantCulture),
                    Object2Value = dataTable2.Columns.Count.ToString(CultureInfo.InvariantCulture),
                    ChildPropertyName = "Columns.Count",
                    Object1 = new WeakReference(object1),
                    Object2 = new WeakReference(object2)
                };

                AddDifference(difference);

                if (Differences.Count >= MaxDifferences)
                    return;
            }

            for (int i = 0; i < Math.Min(dataTable1.Rows.Count,dataTable2.Rows.Count); i++)
            {
                string currentBreadCrumb = AddBreadCrumb(breadCrumb, "Rows", string.Empty, i);

                CompareDataRow(dataTable1.Rows[i], dataTable2.Rows[i], currentBreadCrumb);

                if (Differences.Count >= MaxDifferences)
                    return;
            }
        }
示例#5
0
        /// <summary>
        /// Compare an object of type URI
        /// </summary>
        /// <param name="object1"></param>
        /// <param name="object2"></param>
        /// <param name="breadCrumb"></param>
        private void CompareUri(object object1, object object2, string breadCrumb)
        {
            Uri uri1 = object1 as Uri;
            Uri uri2 = object2 as Uri;

            //This should never happen, null check happens one level up
            if (uri1 == null || uri2 == null)
                return;

            if (uri1.OriginalString != uri2.OriginalString)
            {
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = breadCrumb,
                    Object1Value = NiceString(uri1.OriginalString),
                    Object2Value = NiceString(uri2.OriginalString),
                    ChildPropertyName = "OriginalString",
                    Object1 = new WeakReference(object1),
                    Object2 = new WeakReference(object2)
                };

                AddDifference(difference);
            }
        }
示例#6
0
        /// <summary>
        /// Compare all columns in a data row
        /// </summary>
        /// <param name="object1"></param>
        /// <param name="object2"></param>
        /// <param name="breadCrumb"></param>
        private void CompareDataRow(object object1, object object2, string breadCrumb)
        {
            DataRow dataRow1 = object1 as DataRow;
            DataRow dataRow2 = object2 as DataRow;

            //This should never happen, null check happens one level up
            if (dataRow1 == null || dataRow2 == null)
                return;

            for (int i = 0; i < dataRow1.Table.Columns.Count; i++)
            {
                //Only compare specific column names
                if (ElementsToInclude.Count > 0 && !ElementsToInclude.Contains(dataRow1.Table.Columns[i].ColumnName))
                    continue;

                //If we should ignore it, skip it
                if (ElementsToInclude.Count == 0 && ElementsToIgnore.Contains(dataRow1.Table.Columns[i].ColumnName))
                    continue;

                //If we should ignore read only, skip it
                if (!CompareReadOnly && dataRow1.Table.Columns[i].ReadOnly)
                    continue;

                //Both are null
                if (dataRow1.IsNull(i) && dataRow2.IsNull(i))
                    continue;

                string currentBreadCrumb = AddBreadCrumb(breadCrumb, string.Empty, string.Empty, dataRow1.Table.Columns[i].ColumnName);

                //Check if one of them is null
                if (dataRow1.IsNull(i))
                {
                    Difference difference = new Difference
                    {
                        ExpectedName = ExpectedName,
                        ActualName = ActualName,
                        PropertyName = currentBreadCrumb,
                        Object1Value = "(null)",
                        Object2Value = NiceString(object2),
                        Object1 = new WeakReference(object1),
                        Object2 = new WeakReference(object2)
                    };

                    AddDifference(difference);
                    return;
                }

                if (dataRow2.IsNull(i))
                {
                    Difference difference = new Difference
                    {
                        ExpectedName = ExpectedName,
                        ActualName = ActualName,
                        PropertyName = currentBreadCrumb,
                        Object1Value = NiceString(object1),
                        Object2Value = "(null)",
                        Object1 = new WeakReference(object1),
                        Object2 = new WeakReference(object2)
                    };

                    AddDifference(difference);
                    return;
                }

                //Check if one of them is deleted
                if (dataRow1.RowState == DataRowState.Deleted ^ dataRow2.RowState == DataRowState.Deleted)
                {
                    Difference difference = new Difference
                    {
                        ExpectedName = ExpectedName,
                        ActualName = ActualName,
                        PropertyName = currentBreadCrumb,
                        Object1Value = dataRow1.RowState.ToString(),
                        Object2Value = dataRow2.RowState.ToString(),
                        Object1 = new WeakReference(object1),
                        Object2 = new WeakReference(object2)
                    };

                    AddDifference(difference);
                    return;
                }

                Compare(dataRow1[i], dataRow2[i], currentBreadCrumb);

                if (Differences.Count >= MaxDifferences)
                    return;
            }
        }
示例#7
0
        /// <summary>
        /// Compare a timespan struct
        /// </summary>
        /// <param name="object1"></param>
        /// <param name="object2"></param>
        /// <param name="breadCrumb"></param>
        private void CompareTimespan(object object1, object object2, string breadCrumb)
        {
            if (((TimeSpan)object1).Ticks != ((TimeSpan)object2).Ticks)
            {
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = breadCrumb,
                    Object1Value = ((TimeSpan)object1).Ticks.ToString(CultureInfo.InvariantCulture),
                    Object2Value = ((TimeSpan)object1).Ticks.ToString(CultureInfo.InvariantCulture),
                    ChildPropertyName = "Ticks",
                    Object1 = new WeakReference(object1),
                    Object2 = new WeakReference(object2)
                };

                AddDifference(difference);
            }
        }
示例#8
0
        /// <summary>
        /// Compare an array or something that implements IList
        /// </summary>
        /// <param name="object1"></param>
        /// <param name="object2"></param>
        /// <param name="breadCrumb"></param>
        private void CompareIList(object object1, object object2, string breadCrumb)
        {
            IList ilist1 = object1 as IList;
            IList ilist2 = object2 as IList;

            //This should never happen, null check happens one level up
            if (ilist1 == null || ilist2 == null)
                return;

            try
            {
                AddParent(object1.GetHashCode());
                AddParent(object2.GetHashCode());

                //Objects must be the same length
                if (ilist1.Count != ilist2.Count)
                {
                    Difference difference = new Difference
                    {
                        ExpectedName = ExpectedName,
                        ActualName = ActualName,
                        PropertyName = breadCrumb,
                        Object1Value = ilist1.Count.ToString(CultureInfo.InvariantCulture),
                        Object2Value = ilist2.Count.ToString(CultureInfo.InvariantCulture),
                        ChildPropertyName = "Count",
                        Object1 = new WeakReference(ilist1),
                        Object2 = new WeakReference(ilist2)
                    };

                    AddDifference(difference);

                    if (Differences.Count >= MaxDifferences)
                        return;
                }

                IEnumerator enumerator1 = ilist1.GetEnumerator();
                IEnumerator enumerator2 = ilist2.GetEnumerator();
                int count = 0;

                if (IgnoreCollectionOrder)
                {
                    CompareEnumeratorIgnoreOrder(enumerator1, enumerator2, breadCrumb);
                }
                else
                {
                    while (enumerator1.MoveNext() && enumerator2.MoveNext())
                    {
                        string currentBreadCrumb = AddBreadCrumb(breadCrumb, string.Empty, string.Empty, count);

                        Compare(enumerator1.Current, enumerator2.Current, currentBreadCrumb);

                        if (Differences.Count >= MaxDifferences)
                            return;

                        count++;
                    }
                }
            }
            finally
            {
                RemoveParent(object1.GetHashCode());
                RemoveParent(object2.GetHashCode());
            }
        }
示例#9
0
        /// <summary>
        /// Compare a pointer struct
        /// </summary>
        /// <param name="object1"></param>
        /// <param name="object2"></param>
        /// <param name="breadCrumb"></param>
        private void ComparePointer(object object1, object object2, string breadCrumb)
        {
            if ((object1 is IntPtr && object2 is IntPtr && ((IntPtr)object1) != ((IntPtr)object2))
                || (object1 is UIntPtr && object2 is UIntPtr && ((UIntPtr)object1) != ((UIntPtr)object2)))
            {
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = breadCrumb,
                    Object1 = new WeakReference(object1),
                    Object2 = new WeakReference(object2)
                };

                AddDifference(difference);
            }
        }
示例#10
0
        /// <summary>
        /// Compare a simple type
        /// </summary>
        /// <param name="object1"></param>
        /// <param name="object2"></param>
        /// <param name="breadCrumb"></param>
        private void CompareSimpleType(object object1, object object2, string breadCrumb)
        {
            //This should never happen, null check happens one level up
            if (object2 == null || object1 == null)
                return;

            IComparable valOne = object1 as IComparable;

            if (valOne == null)
                throw new Exception("Expected value does not implement IComparable");

            if (valOne.CompareTo(object2) != 0)
            {
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = breadCrumb,
                    Object1Value = object1.ToString(),
                    Object2Value = object2.ToString(),
                    Object1 = new WeakReference(object1),
                    Object2 = new WeakReference(object2)
                };

                AddDifference(difference);
            }
        }
示例#11
0
        private void CompareIpEndPoint(object object1, object object2, string breadCrumb)
        {
            IPEndPoint ipEndPoint1 = object1 as IPEndPoint;
            IPEndPoint ipEndPoint2 = object2 as IPEndPoint;

            //Null check happens above
            if (ipEndPoint1 == null || ipEndPoint2 == null)
                return;

            if (ipEndPoint1.Port != ipEndPoint2.Port)
            {
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = breadCrumb,
                    Object1Value = ipEndPoint1.Port.ToString(CultureInfo.InvariantCulture),
                    Object2Value = ipEndPoint2.Port.ToString(CultureInfo.InvariantCulture),
                    ChildPropertyName = "Port",
                    Object1 = new WeakReference(ipEndPoint1),
                    Object2 = new WeakReference(ipEndPoint2)
                };

                AddDifference(difference);
            }

            if (Differences.Count >= MaxDifferences)
                return;

            if (ipEndPoint1.Address.ToString() != ipEndPoint2.Address.ToString())
            {
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = breadCrumb,
                    Object1Value = ipEndPoint1.Address.ToString(),
                    Object2Value = ipEndPoint2.Address.ToString(),
                    ChildPropertyName = "Address",
                    Object1 = new WeakReference(ipEndPoint1),
                    Object2 = new WeakReference(ipEndPoint2)
                };

                AddDifference(difference);
            }
        }
示例#12
0
        private void CompareIndexerIgnoreOrder(PropertyInfo info, object object1, object object2, string breadCrumb,
            int indexerCount1, int indexerCount2)
        {
            int i = 0;

            //if object2 holds more items than object1 we need to track, and then show diffs of the remaining
            //items
            var needTrackingOfObject2 = indexerCount2 > indexerCount1;
            var foundObject2Items = new List<int>();

            while (i < indexerCount1)
            {
                string currentCrumb = breadCrumb;
                object objectValue1 = info.GetValue(object1, new object[] { i });

                var found = false;

                // expect order, but don't assume it.  this improves performance
                // where the collections are ordered in sync (wittingly, or un-), but
                // requires some fancy logic to loop back from 0 to i
                var currentLimiter = indexerCount2;
                var j = (i >= indexerCount2) ? 0 : i;
                var loopedBack = false;
                bool needLoopBack = j > 0;

                while (j < currentLimiter)
                {
                    var clone = Clone();
                    clone.Differences = new List<Difference>();

                    currentCrumb = AddBreadCrumb(breadCrumb, "Current", string.Empty, i);

                    object objectValue2 = info.GetValue(object2, new object[] { j });

                    if (HasMatchingSpecEntry(objectValue1))
                    {
                        if (clone.MatchObjects(objectValue1, objectValue2, ref currentCrumb))
                        {
                            found = true;
                            Compare(objectValue1, objectValue2, currentCrumb);
                            foundObject2Items.Add(j);
                            break;
                        }

                        clone.Compare(objectValue1, objectValue2, currentCrumb);
                    }
                    else
                    {
                        clone.Compare(objectValue1, objectValue2, currentCrumb);
                    }

                    if (clone.Differences.Count == 0)
                    {
                        found = true;

                        if (needTrackingOfObject2)
                        {
                            foundObject2Items.Add(j);
                        }

                        break;
                    }

                    j++;
                    if (needLoopBack && j == currentLimiter && !loopedBack)
                    {
                        j = 0;
                        currentLimiter = i;
                        loopedBack = true;
                    }
                }

                if (!found)
                {
                    Difference difference = new Difference
                    {
                        ExpectedName = ExpectedName,
                        ActualName = ActualName,
                        PropertyName = currentCrumb,
                        Object1Value = NiceString(objectValue1),
                        Object2Value = "(null)",
                        ChildPropertyName = "Item",
                        Object1 = new WeakReference(objectValue1),
                        Object2 = null
                    };

                    AddDifference(difference);
                }

                if (Differences.Count >= MaxDifferences)
                    return;

                i++;
            }

            if (needTrackingOfObject2)
            {
                for (int j = 0; j < indexerCount2; j++)
                {
                    if (!foundObject2Items.Contains(j))
                    {
                        object objectValue2 = info.GetValue(object2, new object[] { j });
                        var matchingEntry = GetMatchingSpecEntry(objectValue2);
                        var currentCrumb = AddBreadCrumb(breadCrumb, string.Empty, (null == matchingEntry)? string.Empty: GetMatchPhrase(objectValue2), j);

                        Compare(null, objectValue2, currentCrumb);

                        if (Differences.Count >= MaxDifferences)
                            return;
                    }
                }
            }
        }
示例#13
0
        /// <summary>
        /// Compare an integer indexer
        /// </summary>
        /// <param name="info"></param>
        /// <param name="object1"></param>
        /// <param name="object2"></param>
        /// <param name="breadCrumb"></param>
        private void CompareIndexer(PropertyInfo info, object object1, object object2, string breadCrumb)
        {
            string currentCrumb;
            int indexerCount1 = (int)info.ReflectedType.GetProperty("Count").GetGetMethod().Invoke(object1, new object[] { });
            int indexerCount2 = (int)info.ReflectedType.GetProperty("Count").GetGetMethod().Invoke(object2, new object[] { });

            //Indexers must be the same length
            if (indexerCount1 != indexerCount2)
            {
                currentCrumb = AddBreadCrumb(breadCrumb, info.Name, string.Empty, -1);
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = currentCrumb,
                    Object1Value = indexerCount1.ToString(CultureInfo.InvariantCulture),
                    Object2Value = indexerCount2.ToString(CultureInfo.InvariantCulture),
                    ChildPropertyName = "Count",
                    Object1 = new WeakReference(object1),
                    Object2 = new WeakReference(object2)
                };

                AddDifference(difference);

                if (Differences.Count >= MaxDifferences)
                    return;
            }

            if (IgnoreCollectionOrder)
            {
                CompareIndexerIgnoreOrder(info, object1, object2, breadCrumb, indexerCount1, indexerCount2);
            }
            else
            {
                // Run on indexer
                for (int i = 0; i < indexerCount1; i++)
                {
                    currentCrumb = AddBreadCrumb(breadCrumb, info.Name, string.Empty, i);
                    object objectValue1 = info.GetValue(object1, new object[] { i });
                    object objectValue2 = null;

                    if (i < indexerCount2)
                        objectValue2 = info.GetValue(object2, new object[] { i });

                    Compare(objectValue1, objectValue2, currentCrumb);

                    if (Differences.Count >= MaxDifferences)
                        return;
                }

                if (indexerCount1 < indexerCount2)
                {
                    for (int j = indexerCount1; j < indexerCount2; j++)
                    {
                        currentCrumb = AddBreadCrumb(breadCrumb, info.Name, string.Empty, j);
                        object objectValue2 = info.GetValue(object2, new object[] { j });

                        Compare(null, objectValue2, currentCrumb);

                        if (Differences.Count >= MaxDifferences)
                            return;
                    }
                }
            }
        }
示例#14
0
        /// <summary>
        /// Compare an enumeration
        /// </summary>
        /// <param name="object1"></param>
        /// <param name="object2"></param>
        /// <param name="breadCrumb"></param>
        private void CompareEnum(object object1, object object2, string breadCrumb)
        {
            if (object1.ToString() != object2.ToString())
            {
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = breadCrumb,
                    Object1Value = object1.ToString(),
                    Object2Value = object2.ToString(),
                    Object1 = new WeakReference(object1),
                    Object2 = new WeakReference(object2)
                };

                AddDifference(difference);
            }
        }
示例#15
0
        /// <summary>
        /// Compare an object of type Type (Runtime type)
        /// </summary>
        /// <param name="object1"></param>
        /// <param name="object2"></param>
        /// <param name="breadCrumb"></param>
        private void CompareType(object object1, object object2, string breadCrumb)
        {
            Type t1 = (Type)object1;
            Type t2 = (Type)object2;

            if (t1.FullName != t2.FullName)
            {
                Difference difference = new Difference
                {
                    ExpectedName = ExpectedName,
                    ActualName = ActualName,
                    PropertyName = breadCrumb,
                    Object1Value = t1.FullName,
                    Object2Value = t2.FullName,
                    ChildPropertyName = "FullName",
                    Object1 = new WeakReference(object1),
                    Object2 = new WeakReference(object2)
                };

                AddDifference(difference);
            }
        }
示例#16
0
        private void CompareEnumeratorIgnoreOrder(IEnumerator enumerator1, IEnumerator enumerator2, string breadCrumb)
        {
            var loopedBack = false;
            var needLoopBack = false;
            var enumerator1Index = -1;
            var enumerator2Index = 0;
            int? limit = null;

            //if object2 holds more items than object1 we need to track, and then show diffs of the remaining
            //items
            var needTrackingOfObject2 = IsBigger(enumerator1, enumerator2);
            var foundObject2Items = new List<int>();

            while (enumerator1.MoveNext())
            {
                enumerator1Index++;
                var found = false;

                // expect order, but don't assume it.  this improves performance
                // where the collections are ordered in sync (wittingly, or un-), but
                // the logic is a bit different than the above index compare,

                var movedNext = enumerator2.MoveNext();

                if (!movedNext)
                {
                    enumerator2.Reset();
                    movedNext = enumerator2.MoveNext();
                    enumerator2Index = 0;
                }

                string currentBreadCrumb = breadCrumb;

                while (movedNext)
                {
                    var clone = Clone();
                    clone.Differences = new List<Difference>();

                    currentBreadCrumb = AddBreadCrumb(breadCrumb, "Current", string.Empty, enumerator1Index);

                    if (HasMatchingSpecEntry(enumerator1.Current))
                    {
                        if (clone.MatchObjects(enumerator1.Current, enumerator2.Current, ref currentBreadCrumb))
                        {
                            found = true;
                            Compare(enumerator1.Current, enumerator2.Current, currentBreadCrumb);
                            foundObject2Items.Add(enumerator2Index);
                            break;
                        }

                        clone.Compare(enumerator1.Current, enumerator2.Current, currentBreadCrumb);
                    }
                    else
                    {
                        clone.Compare(enumerator1.Current, enumerator2.Current, currentBreadCrumb);
                    }

                    if (clone.Differences.Count == 0)
                    {
                        found = true;

                        if (needTrackingOfObject2)
                        {
                            foundObject2Items.Add(enumerator2Index);
                        }

                        break;
                    }

                    movedNext = enumerator2.MoveNext();
                    enumerator2Index++;

                    if (enumerator2Index == limit)
                        break;

                    if (!movedNext && needLoopBack && !loopedBack)
                    {
                        enumerator2.Reset();
                        limit = enumerator2Index;
                        enumerator2Index = 0;
                        movedNext = enumerator2.MoveNext();
                        loopedBack = true;
                    }
                }

                if (!found)
                {
                    Difference difference = new Difference
                    {
                        ExpectedName = ExpectedName,
                        ActualName = ActualName,
                        PropertyName = currentBreadCrumb,
                        Object1Value = NiceString(enumerator1.Current),
                        Object2Value = "(null)",
                        ChildPropertyName = "Item",
                        Object1 = new WeakReference(enumerator1),
                        Object2 = null
                    };

                    AddDifference(difference);

                }

                if (Differences.Count >= MaxDifferences)
                    return;

                needLoopBack = true;
            }

            enumerator2.Reset();

            if (needTrackingOfObject2)
            {
                var j = 0;

                while (enumerator2.MoveNext())
                {
                    if (!foundObject2Items.Contains(j))
                    {
                        object objectValue2 = enumerator2.Current;
                        var matchingEntry = GetMatchingSpecEntry(objectValue2);
                        var currentCrumb = AddBreadCrumb(breadCrumb, string.Empty, (null == matchingEntry) ? string.Empty : GetMatchPhrase(objectValue2), j);

                        Compare(null, objectValue2, currentCrumb);

                        if (Differences.Count >= MaxDifferences)
                            return;
                    }

                    j++;
                }

            }
        }
示例#17
0
        /// <summary>
        /// Compare a HashSet
        /// </summary>
        /// <param name="object1"></param>
        /// <param name="object2"></param>
        /// <param name="breadCrumb"></param>
        private void CompareHashSet(object object1, object object2, string breadCrumb)
        {
            try
            {
                AddParent(object1.GetHashCode());
                AddParent(object2.GetHashCode());

                Type t1 = object1.GetType();

                //Get count by reflection since we can't cast it to HashSet<>
                int hashSet1Count = (int) GetPropertyValue(t1, object1, "Count");
                int hashSet2Count = (int) GetPropertyValue(t1, object2, "Count");

                //Objects must be the same length
                if (hashSet1Count != hashSet2Count)
                {
                    Difference difference = new Difference
                    {
                        ExpectedName = ExpectedName,
                        ActualName = ActualName,
                        PropertyName = breadCrumb,
                        Object1Value = hashSet1Count.ToString(CultureInfo.InvariantCulture),
                        Object2Value = hashSet2Count.ToString(CultureInfo.InvariantCulture),
                        ChildPropertyName = "Count",
                        Object1 = new WeakReference(hashSet1Count),
                        Object2 = new WeakReference(hashSet2Count)
                    };

                    AddDifference(difference);

                    if (Differences.Count >= MaxDifferences)
                        return;
                }

                //Get enumerators by reflection
                MethodInfo methodInfo = GetMethod(t1, "GetEnumerator");
                IEnumerator enumerator1 = (IEnumerator) methodInfo.Invoke(object1, null);
                IEnumerator enumerator2 = (IEnumerator) methodInfo.Invoke(object2, null);

                int count = 0;

                if (IgnoreCollectionOrder)
                {
                    CompareEnumeratorIgnoreOrder(enumerator1, enumerator2, breadCrumb);
                }
                else
                {
                    while (enumerator1.MoveNext() && enumerator2.MoveNext())
                    {
                        string currentBreadCrumb = AddBreadCrumb(breadCrumb, string.Empty, string.Empty, count);

                        Compare(enumerator1.Current, enumerator2.Current, currentBreadCrumb);

                        if (Differences.Count >= MaxDifferences)
                            return;

                        count++;
                    }
                }
            }
            finally
            {
                RemoveParent(object1.GetHashCode());
                RemoveParent(object2.GetHashCode());
            }
        }