/// <summary> /// Checks that the current effective property value matches the expected value. /// </summary> /// <param name="styledElement"></param> /// <param name="unstyledElement"></param> /// <param name="dp"></param> /// <param name="skipProps"></param> public static void CheckExpectedPropertyValue(DependencyObject styledElement, DependencyObject unstyledElement, DependencyProperty dp, Dictionary <string, PropertyToIgnore> skipProps) { Type type = styledElement.GetType(); bool isSameValue = true; object styledValue = styledElement.GetValue(dp); object localValue = unstyledElement.GetValue(dp); TreeCompareResult result = TreeComparer.CompareLogical(styledValue, localValue, skipProps); isSameValue = (CompareResult.Equivalent == result.Result); if (!isSameValue) { throw new TestValidationException("Unexpected '" + dp.Name + "' value on element '" + type.Name + "'."); } }
/// <summary> /// Compare two object trees. If all the descendant logical nodes /// are equivalent, return true, otherwise, return false. /// </summary> /// <param name="firstTree">The root for the first tree.</param> /// <param name="secondTree">The root for the second tree.</param> /// <param name="propertiesToIgnore">Custom list of properties to ignore.</param> /// <remarks> /// Compares every event and property for each the node. /// </remarks> /// <returns> /// A structure containing result. If the returned variable name is result. /// result.Result is CompareResult.Equivalent in the case two nodes are equivalent, /// and CompareResult.Different otherwise. /// </returns> public static TreeCompareResult CompareLogical( Object firstTree, Object secondTree, Dictionary <string, PropertyToIgnore> propertiesToIgnore) { if (propertiesToIgnore == null) { throw new ArgumentNullException("propertiesToIgnore", "Argument must be a non-null Dictionary."); } TreeCompareResult result = new TreeCompareResult(); result.Result = CompareResult.Equivalent; // Validate parameters, both objects are null if (null == firstTree && null == secondTree) { return(result); } result.Result = CompareResult.Different; // Validate parameters, only one object is null if (null == firstTree || null == secondTree) { return(result); } // Compare the types if (!firstTree.GetType().Equals(secondTree.GetType())) { SendCompareMessage("Two nodes have different types: '" + firstTree.GetType().FullName + "' vs. '" + secondTree.GetType().FullName + "'."); Break(); return(result); } bool same = false; lock (_objectsInTree) { // Create hashtables that will contain objects in the trees. // This is used to break loops. _objectsInTree[0] = new List <int>(); _objectsInTree[1] = new List <int>(); _skipProperties = propertiesToIgnore; // Include default skip properties if necessary. if (_skipProperties != _skipPropertiesDefault) { _MergeDictionaries(_skipProperties, _skipPropertiesDefault); } try { // cast roots to LogicalTreeNodes DependencyObject firstLogicalTreeNode = firstTree as DependencyObject; DependencyObject secondLogicalTreeNode = secondTree as DependencyObject; //Both are not logical tree node if ((null == firstLogicalTreeNode) && (null == secondLogicalTreeNode)) { same = CompareObjects(firstTree, secondTree); } else { _objectsInTree[0].Add(firstTree.GetHashCode()); _objectsInTree[1].Add(secondTree.GetHashCode()); same = CompareLogicalTree(firstLogicalTreeNode, secondLogicalTreeNode); } } finally { _objectsInTree[0] = null; _objectsInTree[1] = null; _skipProperties = null; } } // Two trees are equivalent if (same) { result.Result = CompareResult.Equivalent; } return(result); }