Ejemplo n.º 1
0
        protected void AssertCSharpDocumentMatchesBaseline(RazorCodeDocument codeDocument)
        {
            var document = codeDocument.GetCSharpDocument();

            // Normalize newlines to match those in the baseline.
            var actualCode = document.GeneratedCode.Replace("\r", "").Replace("\n", "\r\n");

            var baselineFilePath            = GetBaselineFilePath(codeDocument, ".codegen.cs");
            var baselineDiagnosticsFilePath = GetBaselineFilePath(codeDocument, ".diagnostics.txt");
            var baselineMappingsFilePath    = GetBaselineFilePath(codeDocument, ".mappings.txt");

            var serializedMappings = SourceMappingsSerializer.Serialize(document, codeDocument.Source);

            if (GenerateBaselines)
            {
                var baselineFullPath = Path.Combine(TestProjectRoot, baselineFilePath);
                Directory.CreateDirectory(Path.GetDirectoryName(baselineFullPath));
                WriteBaseline(actualCode, baselineFullPath);

                var baselineDiagnosticsFullPath = Path.Combine(TestProjectRoot, baselineDiagnosticsFilePath);
                var lines = document.Diagnostics.Select(RazorDiagnosticSerializer.Serialize).ToArray();
                if (lines.Any())
                {
                    WriteBaseline(lines, baselineDiagnosticsFullPath);
                }
                else if (File.Exists(baselineDiagnosticsFullPath))
                {
                    File.Delete(baselineDiagnosticsFullPath);
                }

                var baselineMappingsFullPath = Path.Combine(TestProjectRoot, baselineMappingsFilePath);
                var text = SourceMappingsSerializer.Serialize(document, codeDocument.Source);
                if (!string.IsNullOrEmpty(text))
                {
                    WriteBaseline(text, baselineMappingsFullPath);
                }
                else if (File.Exists(baselineMappingsFullPath))
                {
                    File.Delete(baselineMappingsFullPath);
                }

                return;
            }

            var codegenFile = TestFile.Create(baselineFilePath, GetType().Assembly);

            if (!codegenFile.Exists())
            {
                throw new XunitException($"The resource {baselineFilePath} was not found.");
            }

            var baseline = codegenFile.ReadAllText();

            Assert.Equal(baseline, actualCode);

            var baselineDiagnostics = string.Empty;
            var diagnosticsFile     = TestFile.Create(baselineDiagnosticsFilePath, GetType().Assembly);

            if (diagnosticsFile.Exists())
            {
                baselineDiagnostics = diagnosticsFile.ReadAllText();
            }

            var actualDiagnostics = string.Concat(document.Diagnostics.Select(d => RazorDiagnosticSerializer.Serialize(d) + "\r\n"));

            Assert.Equal(baselineDiagnostics, actualDiagnostics);

            var baselineMappings = string.Empty;
            var mappingsFile     = TestFile.Create(baselineMappingsFilePath, GetType().Assembly);

            if (mappingsFile.Exists())
            {
                baselineMappings = mappingsFile.ReadAllText();
            }

            var actualMappings = SourceMappingsSerializer.Serialize(document, codeDocument.Source);

            actualMappings = actualMappings.Replace("\r", "").Replace("\n", "\r\n");
            Assert.Equal(baselineMappings, actualMappings);

            AssertLinePragmas(codeDocument);
        }
        protected void AssertSourceMappingsMatchBaseline(RazorCodeDocument codeDocument)
        {
            if (FileName == null)
            {
                var message = $"{nameof(AssertSourceMappingsMatchBaseline)} should only be called from an integration test ({nameof(FileName)} is null).";
                throw new InvalidOperationException(message);
            }

            var csharpDocument = codeDocument.GetCSharpDocument();

            Assert.NotNull(csharpDocument);

            var baselineFileName   = Path.ChangeExtension(FileName, ".mappings.txt");
            var serializedMappings = SourceMappingsSerializer.Serialize(csharpDocument, codeDocument.Source);

            if (GenerateBaselines)
            {
                var baselineFullPath = Path.Combine(TestProjectRoot, baselineFileName);
                File.WriteAllText(baselineFullPath, serializedMappings);
                return;
            }

            var testFile = TestFile.Create(baselineFileName, GetType().GetTypeInfo().Assembly);

            if (!testFile.Exists())
            {
                throw new XunitException($"The resource {baselineFileName} was not found.");
            }

            var baseline = testFile.ReadAllText();

            // Normalize newlines to match those in the baseline.
            var actualBaseline = serializedMappings.Replace("\r", "").Replace("\n", "\r\n");

            Assert.Equal(baseline, actualBaseline);

            var syntaxTree = codeDocument.GetSyntaxTree();
            var visitor    = new CodeSpanVisitor();

            visitor.Visit(syntaxTree.Root);

            var charBuffer = new char[codeDocument.Source.Length];

            codeDocument.Source.CopyTo(0, charBuffer, 0, codeDocument.Source.Length);
            var sourceContent = new string(charBuffer);

            var spans = visitor.CodeSpans;

            for (var i = 0; i < spans.Count; i++)
            {
                var span       = spans[i];
                var sourceSpan = span.GetSourceSpan(codeDocument.Source);
                if (sourceSpan == null)
                {
                    // Not in the main file, skip.
                    continue;
                }

                var expectedSpan = sourceContent.Substring(sourceSpan.AbsoluteIndex, sourceSpan.Length);

                // See #2593
                if (string.IsNullOrWhiteSpace(expectedSpan))
                {
                    // For now we don't verify whitespace inside of a directive. We know that directives cheat
                    // with how they bound whitespace/C#/markup to make completion work.
                    if (span.FirstAncestorOrSelf <RazorDirectiveSyntax>() != null)
                    {
                        continue;
                    }
                }

                // See #2594
                if (string.Equals("@", expectedSpan))
                {
                    // For now we don't verify an escaped transition. In some cases one of the @ tokens in @@foo
                    // will be mapped as C# but will not be present in the output buffer because it's not actually C#.
                    continue;
                }

                var found = false;
                for (var j = 0; j < csharpDocument.SourceMappings.Count; j++)
                {
                    var mapping = csharpDocument.SourceMappings[j];
                    if (mapping.OriginalSpan == sourceSpan)
                    {
                        var actualSpan = csharpDocument.GeneratedCode.Substring(
                            mapping.GeneratedSpan.AbsoluteIndex,
                            mapping.GeneratedSpan.Length);

                        if (!string.Equals(expectedSpan, actualSpan, StringComparison.Ordinal))
                        {
                            throw new XunitException(
                                      $"Found the span {sourceSpan} in the output mappings but it contains " +
                                      $"'{EscapeWhitespace(actualSpan)}' instead of '{EscapeWhitespace(expectedSpan)}'.");
                        }

                        found = true;
                        break;
                    }
                }

                if (!found)
                {
                    throw new XunitException(
                              $"Could not find the span {sourceSpan} - containing '{EscapeWhitespace(expectedSpan)}' " +
                              $"in the output.");
                }
            }
        }