Exemplo n.º 1
0
        /// <summary>
        /// Verify that two strings of code are equal. Agnostic to end of line characters.
        /// </summary>
        /// <param name="expected">The expected code.</param>
        /// <param name="actual">The actual code.</param>
        /// <param name="messageHeader">The first line to add to the exception message on error.</param>
        internal static void AreEqual(string expected, string actual, string messageHeader)
        {
            var expectedPos = 0;
            var actualPos   = 0;
            var line        = 1;

            while (expectedPos < expected.Length && actualPos < actual.Length)
            {
                var ec = expected[expectedPos];
                var ac = actual[actualPos];
                if (ec == '\r' || ac == '\r')
                {
                    if (ec == '\r')
                    {
                        expectedPos++;
                    }

                    if (ac == '\r')
                    {
                        actualPos++;
                    }

                    continue;
                }

                if (ec != ac)
                {
                    if (IsAt(expected, expectedPos, "\\r") ||
                        IsAt(actual, actualPos, "\\r"))
                    {
                        if (IsAt(expected, expectedPos, "\\r"))
                        {
                            expectedPos += 2;
                        }

                        if (IsAt(actual, actualPos, "\\r"))
                        {
                            actualPos += 2;
                        }

                        continue;
                    }

                    var errorBuilder = StringBuilderPool.Borrow();
                    if (messageHeader != null)
                    {
                        errorBuilder.AppendLine(messageHeader);
                    }

                    if (!IsSingleLine(expected) ||
                        !IsSingleLine(actual))
                    {
                        errorBuilder.AppendLine(
                            CodeReader.TryGetFileName(expected, out var fileName)
                                ? $"Mismatch on line {line} of file {fileName}."
                                : $"Mismatch on line {line}.");
                    }

                    var expectedLine = expected.Split('\n')[line - 1].Trim('\r');
                    var actualLine   = actual.Split('\n')[line - 1].Trim('\r');
                    var diffPos      = DiffPos(expectedLine, actualLine);

                    errorBuilder.AppendLine($"Expected: {expectedLine}")
                    .AppendLine($"Actual:   {actualLine}")
                    .AppendLine($"          {new string(' ', diffPos)}^");

                    if (!IsSingleLine(expected) ||
                        !IsSingleLine(actual))
                    {
                        errorBuilder.AppendLine("Expected:")
                        .Append(expected)
                        .AppendLine()
                        .AppendLine("Actual:")
                        .Append(actual)
                        .AppendLine();
                    }

                    throw new AssertException(errorBuilder.Return());
                }

                if (ec == '\n')
                {
                    line++;
                }

                expectedPos++;
                actualPos++;
            }

            while (expectedPos < expected.Length && expected[expectedPos] == '\r')
            {
                expectedPos++;
            }

            while (actualPos < actual.Length && actual[actualPos] == '\r')
            {
                actualPos++;
            }

            if (expectedPos == expected.Length && actualPos == actual.Length)
            {
                return;
            }

            var messageBuilder = StringBuilderPool.Borrow();

            if (messageHeader != null)
            {
                messageBuilder.AppendLine(messageHeader);
            }

            messageBuilder.AppendLine(CodeReader.TryGetFileName(expected, out var name) ? $"Mismatch at end of file {name}." : "Mismatch at end.")
            .Append("Expected: ").AppendLine(GetEnd(expected))
            .Append("Actual:   ").AppendLine(GetEnd(actual))
            .AppendLine($"          {new string(' ', DiffPos(GetEnd(expected), GetEnd(actual)))}^");

            if (!IsSingleLine(expected) ||
                !IsSingleLine(actual))
            {
                messageBuilder.AppendLine("Expected:")
                .Append(expected)
                .AppendLine()
                .AppendLine("Actual:")
                .Append(actual)
                .AppendLine();
            }

            throw new AssertException(messageBuilder.Return());

            bool IsSingleLine(string text)
            {
                bool foundNewLine = false;

                foreach (var c in text)
                {
                    switch (c)
                    {
                    case '\r':
                    case '\n':
                        foundNewLine = true;
                        break;

                    default:
                        if (foundNewLine)
                        {
                            return(false);
                        }

                        break;
                    }
                }

                return(true);
            }

            int DiffPos(string expectedLine, string actualLine)
            {
                var diffPos = Math.Min(expectedLine.Length, actualLine.Length);

                for (var i = 0; i < Math.Min(expectedLine.Length, actualLine.Length); i++)
                {
                    if (expectedLine[i] != actualLine[i])
                    {
                        diffPos = i;
                        break;
                    }
                }

                return(diffPos);
            }

            string GetEnd(string text)
            {
                bool lastLine = false;
                var  builder  = StringBuilderPool.Borrow();

                for (var i = text.Length - 1; i >= 0; i--)
                {
                    switch (text[i])
                    {
                    case '\r':
                        if (lastLine)
                        {
                            return(builder.Return());
                        }

                        builder.Insert(0, "\\r");
                        break;

                    case '\n':
                        if (lastLine)
                        {
                            return(builder.Return());
                        }

                        builder.Insert(0, "\\n");
                        break;

                    default:
                        lastLine = true;
                        builder.Insert(0, text[i]);
                        break;
                    }
                }

                return(builder.Return());
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Verify that two strings of code are equal. Agnostic to end of line characters.
        /// </summary>
        /// <param name="expected">The expected code.</param>
        /// <param name="actual">The actual code.</param>
        /// <param name="messageHeader">The first line to add to the exception message on error.</param>
        internal static void AreEqual(string expected, string actual, string?messageHeader)
        {
            var expectedPos = 0;
            var actualPos   = 0;
            var line        = 1;

            while (expectedPos < expected.Length && actualPos < actual.Length)
            {
                var ec = expected[expectedPos];
                var ac = actual[actualPos];
                if (ec == '\r' || ac == '\r')
                {
                    if (ec == '\r')
                    {
                        expectedPos++;
                    }

                    if (ac == '\r')
                    {
                        actualPos++;
                    }

                    continue;
                }

                if (ec != ac)
                {
                    if (IsAt(expected, expectedPos, "\\r") ||
                        IsAt(actual, actualPos, "\\r"))
                    {
                        if (IsAt(expected, expectedPos, "\\r"))
                        {
                            expectedPos += 2;
                        }

                        if (IsAt(actual, actualPos, "\\r"))
                        {
                            actualPos += 2;
                        }

                        continue;
                    }

                    var errorBuilder = StringBuilderPool.Borrow();
                    if (messageHeader != null)
                    {
                        errorBuilder.AppendLine(messageHeader);
                    }

                    if (!IsSingleLine(expected) ||
                        !IsSingleLine(actual))
                    {
                        errorBuilder.AppendLine(
                            CodeReader.TryGetFileName(expected, out var fileName)
                                ? $"Mismatch on line {line} of file {fileName}."
                                : $"Mismatch on line {line}.");
                    }

                    var expectedLine = expected.Split('\n')[line - 1].Trim('\r');
                    var actualLine   = actual.Split('\n')[line - 1].Trim('\r');
                    var diffPos      = DiffPos(expectedLine, actualLine);

                    errorBuilder.AppendLine($"Expected: {expectedLine}")
                    .AppendLine($"Actual:   {actualLine}")
                    .AppendLine($"          {new string(' ', diffPos)}^");

                    if (!IsSingleLine(expected) ||
                        !IsSingleLine(actual))
                    {
                        errorBuilder.AppendLine("Expected:")
                        .Append(expected)
                        .AppendLine()
                        .AppendLine("Actual:")
                        .Append(actual)
                        .AppendLine();
                    }

                    throw new AssertException(errorBuilder.Return());
                }

                if (ec == '\n')
                {
                    line++;
                }

                expectedPos++;
                actualPos++;
            }

            while (expectedPos < expected.Length && expected[expectedPos] == '\r')
            {
                expectedPos++;
            }

            while (actualPos < actual.Length && actual[actualPos] == '\r')
            {
                actualPos++;
            }

            if (expectedPos == expected.Length && actualPos == actual.Length)
            {
                return;
            }

            var messageBuilder = StringBuilderPool.Borrow();

            if (messageHeader != null)
            {
                messageBuilder.AppendLine(messageHeader);
            }

            messageBuilder.AppendLine(CodeReader.TryGetFileName(expected, out var name) ? $"Mismatch at end of file {name}." : "Mismatch at end.")
            .Append("Expected: ").AppendLine(GetEnd(expected))
            .Append("Actual:   ").AppendLine(GetEnd(actual))
            .AppendLine($"          {new string(' ', DiffPos(GetEnd(expected), GetEnd(actual)))}^");

            if (!IsSingleLine(expected) ||
                !IsSingleLine(actual))
            {
                messageBuilder.AppendLine("Expected:")
                .Append(expected)
                .AppendLine()
                .AppendLine("Actual:")
                .Append(actual)
                .AppendLine();
            }

            throw new AssertException(messageBuilder.Return());