Example #1
0
        private Failure Validate()
        {
            while (!subjectIterator.IsEndOfDocument && !expectationIterator.IsEndOfDocument)
            {
                if (subjectIterator.NodeType != expectationIterator.NodeType)
                {
                    return(new Failure("Expected node of type {0} at {1}{reason}, but found {2}.",
                                       expectationIterator.NodeType, currentNode.GetXPath(), subjectIterator.NodeType));
                }

                Failure failure = null;

                switch (subjectIterator.NodeType)
                {
                case XmlNodeType.Element:
                    failure = ValidateStartElement();
                    if (failure != null)
                    {
                        return(failure);
                    }

                    // starting new element, add local name to location stack
                    // to build XPath info
                    currentNode = currentNode.Push(subjectIterator.LocalName);

                    failure = ValidateAttributes();

                    if (subjectIterator.IsEmptyElement)
                    {
                        // The element is already complete. (We will NOT get an EndElement node.)
                        // Update node information.
                        currentNode = currentNode.Parent;
                    }

                    // check whether empty element and self-closing element needs to be synchronized
                    if (subjectIterator.IsEmptyElement && !expectationIterator.IsEmptyElement)
                    {
                        expectationIterator.MoveToEndElement();
                    }
                    else if (expectationIterator.IsEmptyElement && !subjectIterator.IsEmptyElement)
                    {
                        subjectIterator.MoveToEndElement();
                    }

                    break;

                case XmlNodeType.EndElement:
                    // No need to verify end element, if it doesn't match
                    // the start element it isn't valid XML, so the parser
                    // would handle that.
                    currentNode.Pop();
                    currentNode = currentNode.Parent;
                    break;

                case XmlNodeType.Text:
                    failure = ValidateText();
                    break;

                default:
                    throw new NotSupportedException($"{subjectIterator.NodeType} found at {currentNode.GetXPath()} is not supported for equivalency comparison.");
                }

                if (failure != null)
                {
                    return(failure);
                }

                subjectIterator.Read();
                expectationIterator.Read();
            }

            if (!expectationIterator.IsEndOfDocument)
            {
                return(new Failure("Expected {0}{reason}, but found end of document.",
                                   expectationIterator.LocalName));
            }

            if (!subjectIterator.IsEndOfDocument)
            {
                return(new Failure("Expected end of document{reason}, but found {0}.",
                                   subjectIterator.LocalName));
            }

            return(null);
        }
        private Failure Validate()
        {
            if (subjectReader is null && expectationReader is null)
            {
                return(null);
            }

            Failure failure = ValidateAgainstNulls();

            if (failure is not null)
            {
                return(failure);
            }

            subjectIterator     = new XmlIterator(subjectReader);
            expectationIterator = new XmlIterator(expectationReader);

            while (!subjectIterator.IsEndOfDocument && !expectationIterator.IsEndOfDocument)
            {
                if (subjectIterator.NodeType != expectationIterator.NodeType)
                {
                    var expectation = expectationIterator.NodeType == XmlNodeType.Text
                        ? $"content \"{expectationIterator.Value}\""
                        : $"{expectationIterator.NodeType} \"{expectationIterator.LocalName}\"";
                    var subject = subjectIterator.NodeType == XmlNodeType.Text
                        ? $"content \"{subjectIterator.Value}\""
                        : $"{subjectIterator.NodeType} \"{subjectIterator.LocalName}\"";
                    return(new Failure(
                               $"Expected {expectation} in {{context:subject}} at {{0}}{{reason}}, but found {subject}.",
                               currentNode.GetXPath()));
                }

                failure = null;

#pragma warning disable IDE0010 // The default case handles the many missing cases
                switch (expectationIterator.NodeType)
#pragma warning restore IDE0010
                {
                case XmlNodeType.Element:
                    failure = ValidateStartElement();
                    if (failure is not null)
                    {
                        return(failure);
                    }

                    // starting new element, add local name to location stack
                    // to build XPath info
                    currentNode = currentNode.Push(expectationIterator.LocalName);

                    failure = ValidateAttributes();

                    if (expectationIterator.IsEmptyElement)
                    {
                        // The element is already complete. (We will NOT get an EndElement node.)
                        // Update node information.
                        currentNode = currentNode.Parent;
                    }

                    // check whether empty element and self-closing element needs to be synchronized
                    if (subjectIterator.IsEmptyElement && !expectationIterator.IsEmptyElement)
                    {
                        expectationIterator.MoveToEndElement();
                    }
                    else if (expectationIterator.IsEmptyElement && !subjectIterator.IsEmptyElement)
                    {
                        subjectIterator.MoveToEndElement();
                    }

                    break;

                case XmlNodeType.EndElement:
                    // No need to verify end element, if it doesn't match
                    // the start element it isn't valid XML, so the parser
                    // would handle that.
                    currentNode.Pop();
                    currentNode = currentNode.Parent;
                    break;

                case XmlNodeType.Text:
                    failure = ValidateText();
                    break;

                default:
                    throw new NotSupportedException(
                              $"{expectationIterator.NodeType} found at {currentNode.GetXPath()} is not supported for equivalency comparison.");
                }

                if (failure is not null)
                {
                    return(failure);
                }

                subjectIterator.Read();
                expectationIterator.Read();
            }

            if (!expectationIterator.IsEndOfDocument)
            {
                return(new Failure(
                           "Expected {0} in {context:subject}{reason}, but found end of document.",
                           expectationIterator.LocalName));
            }

            if (!subjectIterator.IsEndOfDocument)
            {
                return(new Failure(
                           "Expected end of document in {context:subject}{reason}, but found {0}.",
                           subjectIterator.LocalName));
            }

            return(null);
        }