From ffec555118d6f45bc04c2de9108bcb93667d6b33 Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Tue, 18 Dec 2018 15:35:38 -0800 Subject: [PATCH] Added missed files --- .../Razor/IntermediateNodeSerializer.cs | 46 +++ .../Razor/IntermediateNodeVerifier.cs | 275 ++++++++++++++++++ .../Razor/RazorDiagnosticSerializer.cs | 13 + 3 files changed, 334 insertions(+) create mode 100644 src/Components/test/Microsoft.AspNetCore.Components.Build.Test/Razor/IntermediateNodeSerializer.cs create mode 100644 src/Components/test/Microsoft.AspNetCore.Components.Build.Test/Razor/IntermediateNodeVerifier.cs create mode 100644 src/Components/test/Microsoft.AspNetCore.Components.Build.Test/Razor/RazorDiagnosticSerializer.cs diff --git a/src/Components/test/Microsoft.AspNetCore.Components.Build.Test/Razor/IntermediateNodeSerializer.cs b/src/Components/test/Microsoft.AspNetCore.Components.Build.Test/Razor/IntermediateNodeSerializer.cs new file mode 100644 index 0000000000..00b1449d42 --- /dev/null +++ b/src/Components/test/Microsoft.AspNetCore.Components.Build.Test/Razor/IntermediateNodeSerializer.cs @@ -0,0 +1,46 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.IO; +using Microsoft.AspNetCore.Razor.Language.Intermediate; + +namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests +{ + public static class IntermediateNodeSerializer + { + public static string Serialize(IntermediateNode node) + { + using (var writer = new StringWriter()) + { + var walker = new Walker(writer); + walker.Visit(node); + + return writer.ToString(); + } + } + + private class Walker : IntermediateNodeWalker + { + private readonly IntermediateNodeWriter _visitor; + private readonly TextWriter _writer; + + public Walker(TextWriter writer) + { + _visitor = new IntermediateNodeWriter(writer); + _writer = writer; + } + + public TextWriter Writer { get; } + + public override void VisitDefault(IntermediateNode node) + { + _visitor.Visit(node); + _writer.WriteLine(); + + _visitor.Depth++; + base.VisitDefault(node); + _visitor.Depth--; + } + } + } +} \ No newline at end of file diff --git a/src/Components/test/Microsoft.AspNetCore.Components.Build.Test/Razor/IntermediateNodeVerifier.cs b/src/Components/test/Microsoft.AspNetCore.Components.Build.Test/Razor/IntermediateNodeVerifier.cs new file mode 100644 index 0000000000..f6b45c7b3a --- /dev/null +++ b/src/Components/test/Microsoft.AspNetCore.Components.Build.Test/Razor/IntermediateNodeVerifier.cs @@ -0,0 +1,275 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using Microsoft.AspNetCore.Razor.Language.Intermediate; +using Xunit; +using Xunit.Sdk; + +namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests +{ + public static class IntermediateNodeVerifier + { + public static void Verify(IntermediateNode node, string[] baseline) + { + var walker = new Walker(baseline); + walker.Visit(node); + walker.AssertReachedEndOfBaseline(); + } + + private class Walker : IntermediateNodeWalker + { + private readonly string[] _baseline; + private readonly IntermediateNodeWriter _visitor; + private readonly StringWriter _writer; + + private int _index; + + public Walker(string[] baseline) + { + _writer = new StringWriter(); + + _visitor = new IntermediateNodeWriter(_writer); + _baseline = baseline; + + } + + public TextWriter Writer { get; } + + public override void VisitDefault(IntermediateNode node) + { + var expected = _index < _baseline.Length ? _baseline[_index++] : null; + + // Write the node as text for comparison + _writer.GetStringBuilder().Clear(); + _visitor.Visit(node); + var actual = _writer.GetStringBuilder().ToString(); + + AssertNodeEquals(node, Ancestors, expected, actual); + + _visitor.Depth++; + base.VisitDefault(node); + _visitor.Depth--; + } + + public void AssertReachedEndOfBaseline() + { + // Since we're walking the nodes of our generated code there's the chance that our baseline is longer. + Assert.True(_baseline.Length == _index, "Not all lines of the baseline were visited!"); + } + + private void AssertNodeEquals(IntermediateNode node, IEnumerable ancestors, string expected, string actual) + { + if (string.Equals(expected, actual)) + { + // YAY!!! everything is great. + return; + } + + if (expected == null) + { + var message = "The node is missing from baseline."; + throw new IntermediateNodeBaselineException(node, Ancestors.ToArray(), expected, actual, message); + } + + int charsVerified = 0; + AssertNestingEqual(node, ancestors, expected, actual, ref charsVerified); + AssertNameEqual(node, ancestors, expected, actual, ref charsVerified); + AssertDelimiter(node, expected, actual, true, ref charsVerified); + AssertLocationEqual(node, ancestors, expected, actual, ref charsVerified); + AssertDelimiter(node, expected, actual, false, ref charsVerified); + AssertContentEqual(node, ancestors, expected, actual, ref charsVerified); + + throw new InvalidOperationException("We can't figure out HOW these two things are different. This is a bug."); + } + + private void AssertNestingEqual(IntermediateNode node, IEnumerable ancestors, string expected, string actual, ref int charsVerified) + { + var i = 0; + for (; i < expected.Length; i++) + { + if (expected[i] != ' ') + { + break; + } + } + + var failed = false; + var j = 0; + for (; j < i; j++) + { + if (actual.Length <= j || actual[j] != ' ') + { + failed = true; + break; + } + } + + if (actual.Length <= j + 1 || actual[j] == ' ') + { + failed = true; + } + + if (failed) + { + var message = "The node is at the wrong level of nesting. This usually means a child is missing."; + throw new IntermediateNodeBaselineException(node, ancestors.ToArray(), expected, actual, message); + } + + charsVerified = j; + } + + private void AssertNameEqual(IntermediateNode node, IEnumerable ancestors, string expected, string actual, ref int charsVerified) + { + var expectedName = GetName(expected, charsVerified); + var actualName = GetName(actual, charsVerified); + + if (!string.Equals(expectedName, actualName)) + { + var message = $"Node names are not equal."; + throw new IntermediateNodeBaselineException(node, ancestors.ToArray(), expected, actual, message); + } + + charsVerified += expectedName.Length; + } + + // Either both strings need to have a delimiter next or neither should. + private void AssertDelimiter(IntermediateNode node, string expected, string actual, bool required, ref int charsVerified) + { + if (charsVerified == expected.Length && required) + { + throw new InvalidOperationException($"Baseline text is not well-formed: '{expected}'."); + } + + if (charsVerified == actual.Length && required) + { + throw new InvalidOperationException($"Baseline text is not well-formed: '{actual}'."); + } + + if (charsVerified == expected.Length && charsVerified == actual.Length) + { + return; + } + + var expectedDelimiter = expected.IndexOf(" - ", charsVerified); + if (expectedDelimiter != charsVerified && expectedDelimiter != -1) + { + throw new InvalidOperationException($"Baseline text is not well-formed: '{actual}'."); + } + + var actualDelimiter = actual.IndexOf(" - ", charsVerified); + if (actualDelimiter != charsVerified && actualDelimiter != -1) + { + throw new InvalidOperationException($"Baseline text is not well-formed: '{actual}'."); + } + + Assert.Equal(expectedDelimiter, actualDelimiter); + + charsVerified += 3; + } + + private void AssertLocationEqual(IntermediateNode node, IEnumerable ancestors, string expected, string actual, ref int charsVerified) + { + var expectedLocation = GetLocation(expected, charsVerified); + var actualLocation = GetLocation(actual, charsVerified); + + if (!string.Equals(expectedLocation, actualLocation)) + { + var message = $"Locations are not equal."; + throw new IntermediateNodeBaselineException(node, ancestors.ToArray(), expected, actual, message); + } + + charsVerified += expectedLocation.Length; + } + + private void AssertContentEqual(IntermediateNode node, IEnumerable ancestors, string expected, string actual, ref int charsVerified) + { + var expectedContent = GetContent(expected, charsVerified); + var actualContent = GetContent(actual, charsVerified); + + if (!string.Equals(expectedContent, actualContent)) + { + var message = $"Contents are not equal."; + throw new IntermediateNodeBaselineException(node, ancestors.ToArray(), expected, actual, message); + } + + charsVerified += expectedContent.Length; + } + + private string GetName(string text, int start) + { + var delimiter = text.IndexOf(" - ", start); + if (delimiter == -1) + { + throw new InvalidOperationException($"Baseline text is not well-formed: '{text}'."); + } + + return text.Substring(start, delimiter - start); + } + + private string GetLocation(string text, int start) + { + var delimiter = text.IndexOf(" - ", start); + return delimiter == -1 ? text.Substring(start) : text.Substring(start, delimiter - start); + } + + private string GetContent(string text, int start) + { + return start == text.Length ? string.Empty : text.Substring(start); + } + + private class IntermediateNodeBaselineException : XunitException + { + public IntermediateNodeBaselineException(IntermediateNode node, IntermediateNode[] ancestors, string expected, string actual, string userMessage) + : base(Format(node, ancestors, expected, actual, userMessage)) + { + Node = node; + Expected = expected; + Actual = actual; + } + + public IntermediateNode Node { get; } + + public string Actual { get; } + + public string Expected { get; } + + private static string Format(IntermediateNode node, IntermediateNode[] ancestors, string expected, string actual, string userMessage) + { + var builder = new StringBuilder(); + builder.AppendLine(userMessage); + builder.AppendLine(); + + if (expected != null) + { + builder.Append("Expected: "); + builder.AppendLine(expected); + } + + if (actual != null) + { + builder.Append("Actual: "); + builder.AppendLine(actual); + } + + if (ancestors != null) + { + builder.AppendLine(); + builder.AppendLine("Path:"); + + foreach (var ancestor in ancestors) + { + builder.AppendLine(ancestor.ToString()); + } + } + + return builder.ToString(); + } + } + } + } +} \ No newline at end of file diff --git a/src/Components/test/Microsoft.AspNetCore.Components.Build.Test/Razor/RazorDiagnosticSerializer.cs b/src/Components/test/Microsoft.AspNetCore.Components.Build.Test/Razor/RazorDiagnosticSerializer.cs new file mode 100644 index 0000000000..aa5586e2bf --- /dev/null +++ b/src/Components/test/Microsoft.AspNetCore.Components.Build.Test/Razor/RazorDiagnosticSerializer.cs @@ -0,0 +1,13 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNetCore.Razor.Language +{ + public class RazorDiagnosticSerializer + { + public static string Serialize(RazorDiagnostic diagnostic) + { + return diagnostic.ToString(); + } + } +} \ No newline at end of file