From dcccea300488541adb2f3d165e8e186bb5c81bc3 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Wed, 24 May 2017 17:30:19 -0700 Subject: [PATCH] Add Checksum computation to RazorSourceDocument. - Renamed many of our `RazorSourceDocument` abstractions to not include the word `Razor`. - Added a `GetChecksum()` method to `RazorSourceDocument` to allow source documents to compute their own checksums. - Re-generated codegen tests that did not normalize new lines. Ones that did re-generate newlines converted from stream => string => normalized string and then ran the Razor parser. - Added tests to validate `GetChecksum` for all source document types. - Removed unused `LegacySourceDocument`. --- .../Intermediate/ChecksumIRNode.cs | 23 +-- ...Document.cs => LargeTextSourceDocument.cs} | 30 +++- .../Legacy/LegacySourceDocument.cs | 79 ---------- .../RazorSourceDocument.cs | 62 ++------ .../StreamSourceDocument.cs | 111 +++++++++++++ ...rceDocument.cs => StringSourceDocument.cs} | 28 +++- .../DefaultRazorTagHelperBinderPhaseTest.cs | 2 +- ...Test.cs => LargeTextSourceDocumentTest.cs} | 66 +++++++- .../RazorSourceDocumentTest.cs | 100 ++---------- .../StreamSourceDocumentTest.cs | 147 ++++++++++++++++++ ...entTest.cs => StringSourceDocumentTest.cs} | 105 +++++++++---- .../GenerateCodeWithBaseType.codegen.cs | 2 +- .../GenerateCodeWithConfigureClass.codegen.cs | 2 +- .../GenerateCodeWithDefaults.codegen.cs | 2 +- .../GenerateCodeWithSetNamespace.codegen.cs | 2 +- .../Langauge/TestRazorProjectItem.cs | 14 +- .../Langauge/TestRazorSourceDocument.cs | 4 +- 17 files changed, 497 insertions(+), 282 deletions(-) rename src/Microsoft.AspNetCore.Razor.Language/{LargeTextRazorSourceDocument.cs => LargeTextSourceDocument.cs} (76%) delete mode 100644 src/Microsoft.AspNetCore.Razor.Language/Legacy/LegacySourceDocument.cs create mode 100644 src/Microsoft.AspNetCore.Razor.Language/StreamSourceDocument.cs rename src/Microsoft.AspNetCore.Razor.Language/{DefaultRazorSourceDocument.cs => StringSourceDocument.cs} (66%) rename test/Microsoft.AspNetCore.Razor.Language.Test/{LargeTextRazorSourceDocumentTest.cs => LargeTextSourceDocumentTest.cs} (56%) create mode 100644 test/Microsoft.AspNetCore.Razor.Language.Test/StreamSourceDocumentTest.cs rename test/Microsoft.AspNetCore.Razor.Language.Test/{DefaultRazorSourceDocumentTest.cs => StringSourceDocumentTest.cs} (70%) diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ChecksumIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ChecksumIRNode.cs index cc3935c646..fd5dfe5593 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ChecksumIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/ChecksumIRNode.cs @@ -39,26 +39,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate Guid = Sha1AlgorithmId }; - var charBuffer = new char[sourceDocument.Length]; - sourceDocument.CopyTo(0, charBuffer, 0, sourceDocument.Length); - - var encoder = sourceDocument.Encoding.GetEncoder(); - var byteCount = encoder.GetByteCount(charBuffer, 0, charBuffer.Length, flush: true); - var checksumBytes = new byte[byteCount]; - encoder.GetBytes(charBuffer, 0, charBuffer.Length, checksumBytes, 0, flush: true); - - using (var hashAlgorithm = SHA1.Create()) + var checksum = sourceDocument.GetChecksum(); + var fileHashBuilder = new StringBuilder(checksum.Length * 2); + foreach (var value in checksum) { - var hashedBytes = hashAlgorithm.ComputeHash(checksumBytes); - var fileHashBuilder = new StringBuilder(hashedBytes.Length * 2); - foreach (var value in hashedBytes) - { - fileHashBuilder.Append(value.ToString("x2")); - } - - node.Bytes = fileHashBuilder.ToString(); + fileHashBuilder.Append(value.ToString("x2")); } + node.Bytes = fileHashBuilder.ToString(); + return node; } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/LargeTextRazorSourceDocument.cs b/src/Microsoft.AspNetCore.Razor.Language/LargeTextSourceDocument.cs similarity index 76% rename from src/Microsoft.AspNetCore.Razor.Language/LargeTextRazorSourceDocument.cs rename to src/Microsoft.AspNetCore.Razor.Language/LargeTextSourceDocument.cs index 988bd9bc70..8c1a5b3a0b 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/LargeTextRazorSourceDocument.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/LargeTextSourceDocument.cs @@ -4,11 +4,12 @@ using System; using System.Collections.Generic; using System.IO; +using System.Security.Cryptography; using System.Text; namespace Microsoft.AspNetCore.Razor.Language { - internal class LargeTextRazorSourceDocument : RazorSourceDocument + internal class LargeTextSourceDocument : RazorSourceDocument { private readonly List _chunks; @@ -17,8 +18,9 @@ namespace Microsoft.AspNetCore.Razor.Language private readonly RazorSourceLineCollection _lines; private readonly int _length; + private byte[] _checksum; - public LargeTextRazorSourceDocument(StreamReader reader, int chunkMaxLength, Encoding encoding, string fileName) + public LargeTextSourceDocument(StreamReader reader, int chunkMaxLength, Encoding encoding, string fileName) { if (reader == null) { @@ -101,6 +103,30 @@ namespace Microsoft.AspNetCore.Razor.Language } } + public override byte[] GetChecksum() + { + if (_checksum == null) + { + var charBuffer = new char[Length]; + CopyTo(0, charBuffer, 0, Length); + + var encoder = Encoding.GetEncoder(); + var byteCount = encoder.GetByteCount(charBuffer, 0, charBuffer.Length, flush: true); + var bytes = new byte[byteCount]; + encoder.GetBytes(charBuffer, 0, charBuffer.Length, bytes, 0, flush: true); + + using (var hashAlgorithm = SHA1.Create()) + { + _checksum = hashAlgorithm.ComputeHash(bytes); + } + } + + var copiedChecksum = new byte[_checksum.Length]; + _checksum.CopyTo(copiedChecksum, 0); + + return copiedChecksum; + } + private static void ReadChunks(StreamReader reader, int chunkMaxLength, out int length, out List chunks) { length = 0; diff --git a/src/Microsoft.AspNetCore.Razor.Language/Legacy/LegacySourceDocument.cs b/src/Microsoft.AspNetCore.Razor.Language/Legacy/LegacySourceDocument.cs deleted file mode 100644 index 3e00109ec4..0000000000 --- a/src/Microsoft.AspNetCore.Razor.Language/Legacy/LegacySourceDocument.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Text; -// 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 Microsoft.AspNetCore.Razor.Language; - -namespace Microsoft.AspNetCore.Razor.Language.Legacy -{ - internal class LegacySourceDocument : RazorSourceDocument - { - private readonly ITextBuffer _buffer; - private readonly string _filename; - private readonly RazorSourceLineCollection _lines; - - public static RazorSourceDocument Create(ITextBuffer buffer, string filename) - { - return new LegacySourceDocument(buffer, filename); - } - - private LegacySourceDocument(ITextBuffer buffer, string filename) - { - _buffer = buffer; - _filename = filename; - - _lines = new DefaultRazorSourceLineCollection(this); - } - - public override char this[int position] - { - get - { - _buffer.Position = position; - return (char)_buffer.Read(); - } - } - - public override Encoding Encoding => Encoding.UTF8; - - public override string FileName => _filename; - - public override int Length => _buffer.Length; - - public override RazorSourceLineCollection Lines => _lines; - - public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) - { - if (destination == null) - { - throw new ArgumentNullException(nameof(destination)); - } - - if (sourceIndex < 0) - { - throw new ArgumentOutOfRangeException(nameof(sourceIndex)); - } - - if (destinationIndex < 0) - { - throw new ArgumentOutOfRangeException(nameof(destinationIndex)); - } - - if (count < 0 || count > Length - sourceIndex || count > destination.Length - destinationIndex) - { - throw new ArgumentOutOfRangeException(nameof(count)); - } - - if (count == 0) - { - return; - } - - for (var i = 0; i < count; i++) - { - destination[destinationIndex + i] = this[sourceIndex + i]; - } - } - } -} diff --git a/src/Microsoft.AspNetCore.Razor.Language/RazorSourceDocument.cs b/src/Microsoft.AspNetCore.Razor.Language/RazorSourceDocument.cs index 92e9b8d39e..40d161c5ab 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/RazorSourceDocument.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/RazorSourceDocument.cs @@ -51,6 +51,12 @@ namespace Microsoft.AspNetCore.Razor.Language /// The number of characters in this instance to copy to destination. public abstract void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count); + /// + /// Calculates the checksum for the . + /// + /// The checksum. + public abstract byte[] GetChecksum(); + /// /// Reads the from the specified . /// @@ -64,7 +70,7 @@ namespace Microsoft.AspNetCore.Razor.Language throw new ArgumentNullException(nameof(stream)); } - return ReadFromInternal(stream, fileName, encoding: null); + return new StreamSourceDocument(stream, encoding: null, fileName: fileName); } /// @@ -86,7 +92,7 @@ namespace Microsoft.AspNetCore.Razor.Language throw new ArgumentNullException(nameof(encoding)); } - return ReadFromInternal(stream, fileName, encoding); + return new StreamSourceDocument(stream, encoding, fileName); } /// @@ -142,57 +148,7 @@ namespace Microsoft.AspNetCore.Razor.Language throw new ArgumentNullException(nameof(encoding)); } - return new DefaultRazorSourceDocument(content, encoding, fileName); - } - - private static RazorSourceDocument ReadFromInternal(Stream stream, string fileName, Encoding encoding) - { - var streamLength = (int)stream.Length; - var content = string.Empty; - var contentEncoding = encoding ?? Encoding.UTF8; - - if (streamLength > 0) - { - var bufferSize = Math.Min(streamLength, LargeObjectHeapLimitInChars); - - var reader = new StreamReader( - stream, - contentEncoding, - detectEncodingFromByteOrderMarks: true, - bufferSize: bufferSize, - leaveOpen: true); - - using (reader) - { - reader.Peek(); // Just to populate the encoding - - if (encoding == null) - { - contentEncoding = reader.CurrentEncoding; - } - else if (encoding != reader.CurrentEncoding) - { - throw new InvalidOperationException( - Resources.FormatMismatchedContentEncoding( - encoding.EncodingName, - reader.CurrentEncoding.EncodingName)); - } - - if (streamLength > LargeObjectHeapLimitInChars) - { - // If the resulting string would end up on the large object heap, then use LargeTextRazorSourceDocument. - return new LargeTextRazorSourceDocument( - reader, - LargeObjectHeapLimitInChars, - contentEncoding, - fileName); - } - - content = reader.ReadToEnd(); - } - } - - return new DefaultRazorSourceDocument(content, contentEncoding, fileName); + return new StringSourceDocument(content, encoding, fileName); } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/StreamSourceDocument.cs b/src/Microsoft.AspNetCore.Razor.Language/StreamSourceDocument.cs new file mode 100644 index 0000000000..99efef4933 --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Language/StreamSourceDocument.cs @@ -0,0 +1,111 @@ +// 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.IO; +using System.Security.Cryptography; +using System.Text; + +namespace Microsoft.AspNetCore.Razor.Language +{ + internal class StreamSourceDocument : RazorSourceDocument + { + // Internal for testing + internal readonly RazorSourceDocument _innerSourceDocument; + + private readonly byte[] _checksum; + + public StreamSourceDocument(Stream stream, Encoding encoding, string fileName) + { + if (stream == null) + { + throw new ArgumentNullException(nameof(stream)); + } + + _checksum = ComputeChecksum(stream); + _innerSourceDocument = CreateInnerSourceDocument(stream, encoding, fileName); + } + + public override char this[int position] => _innerSourceDocument[position]; + + public override Encoding Encoding => _innerSourceDocument.Encoding; + + public override string FileName => _innerSourceDocument.FileName; + + public override int Length => _innerSourceDocument.Length; + + public override RazorSourceLineCollection Lines => _innerSourceDocument.Lines; + + public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) + => _innerSourceDocument.CopyTo(sourceIndex, destination, destinationIndex, count); + + public override byte[] GetChecksum() + { + var copiedChecksum = new byte[_checksum.Length]; + _checksum.CopyTo(copiedChecksum, 0); + + return copiedChecksum; + } + + private static byte[] ComputeChecksum(Stream stream) + { + using (var hashAlgorithm = SHA1.Create()) + { + var checksum = hashAlgorithm.ComputeHash(stream); + stream.Position = 0; + + return checksum; + } + } + + private static RazorSourceDocument CreateInnerSourceDocument(Stream stream, Encoding encoding, string fileName) + { + var streamLength = (int)stream.Length; + var content = string.Empty; + var contentEncoding = encoding ?? Encoding.UTF8; + + if (streamLength > 0) + { + var bufferSize = Math.Min(streamLength, LargeObjectHeapLimitInChars); + + var reader = new StreamReader( + stream, + contentEncoding, + detectEncodingFromByteOrderMarks: true, + bufferSize: bufferSize, + leaveOpen: true); + + using (reader) + { + reader.Peek(); // Just to populate the encoding + + if (encoding == null) + { + contentEncoding = reader.CurrentEncoding; + } + else if (encoding != reader.CurrentEncoding) + { + throw new InvalidOperationException( + Resources.FormatMismatchedContentEncoding( + encoding.EncodingName, + reader.CurrentEncoding.EncodingName)); + } + + if (streamLength > LargeObjectHeapLimitInChars) + { + // If the resulting string would end up on the large object heap, then use LargeTextSourceDocument. + return new LargeTextSourceDocument( + reader, + LargeObjectHeapLimitInChars, + contentEncoding, + fileName); + } + + content = reader.ReadToEnd(); + } + } + + return new StringSourceDocument(content, contentEncoding, fileName); + } + } +} diff --git a/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorSourceDocument.cs b/src/Microsoft.AspNetCore.Razor.Language/StringSourceDocument.cs similarity index 66% rename from src/Microsoft.AspNetCore.Razor.Language/DefaultRazorSourceDocument.cs rename to src/Microsoft.AspNetCore.Razor.Language/StringSourceDocument.cs index 1e8d35a826..e2c062eef5 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorSourceDocument.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/StringSourceDocument.cs @@ -2,16 +2,18 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Security.Cryptography; using System.Text; namespace Microsoft.AspNetCore.Razor.Language { - internal class DefaultRazorSourceDocument : RazorSourceDocument + internal class StringSourceDocument : RazorSourceDocument { private readonly string _content; private readonly RazorSourceLineCollection _lines; + private byte[] _checksum; - public DefaultRazorSourceDocument(string content, Encoding encoding, string fileName) + public StringSourceDocument(string content, Encoding encoding, string fileName) { if (content == null) { @@ -69,5 +71,27 @@ namespace Microsoft.AspNetCore.Razor.Language _content.CopyTo(sourceIndex, destination, destinationIndex, count); } + + public override byte[] GetChecksum() + { + if (_checksum == null) + { + var charBuffer = _content.ToCharArray(); + var encoder = Encoding.GetEncoder(); + var byteCount = encoder.GetByteCount(charBuffer, 0, charBuffer.Length, flush: true); + var bytes = new byte[byteCount]; + encoder.GetBytes(charBuffer, 0, charBuffer.Length, bytes, 0, flush: true); + + using (var hashAlgorithm = SHA1.Create()) + { + _checksum = hashAlgorithm.ComputeHash(bytes); + } + } + + var copiedChecksum = new byte[_checksum.Length]; + _checksum.CopyTo(copiedChecksum, 0); + + return copiedChecksum; + } } } diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorTagHelperBinderPhaseTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorTagHelperBinderPhaseTest.cs index 6bbb4b77a7..1a03af009b 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorTagHelperBinderPhaseTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorTagHelperBinderPhaseTest.cs @@ -838,7 +838,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var errorSink = new ErrorSink(); var phase = new DefaultRazorTagHelperBinderPhase(); - var document = RazorCodeDocument.Create(new DefaultRazorSourceDocument("Test content", encoding: Encoding.UTF8, fileName: "TestFile")); + var document = RazorCodeDocument.Create(new StringSourceDocument("Test content", encoding: Encoding.UTF8, fileName: "TestFile")); // Act var prefix = phase.ProcessTagHelperPrefix(((IEnumerable)directiveDescriptors).ToList(), document, errorSink); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/LargeTextRazorSourceDocumentTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/LargeTextSourceDocumentTest.cs similarity index 56% rename from test/Microsoft.AspNetCore.Razor.Language.Test/LargeTextRazorSourceDocumentTest.cs rename to test/Microsoft.AspNetCore.Razor.Language.Test/LargeTextSourceDocumentTest.cs index ac35fccbf8..3f4a7b89bd 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/LargeTextRazorSourceDocumentTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/LargeTextSourceDocumentTest.cs @@ -1,15 +1,65 @@ -using System; -using System.Collections.Generic; -using System.IO; +using System.IO; using System.Text; using Xunit; namespace Microsoft.AspNetCore.Razor.Language.Test { - public class LargeTextRazorSourceDocumentTest + public class LargeTextSourceDocumentTest { private const int ChunkTestLength = 10; + [Fact] + public void GetChecksum_ReturnsCopiedChecksum() + { + // Arrange + var contentString = "Hello World"; + var stream = TestRazorSourceDocument.CreateStreamContent(contentString); + var reader = new StreamReader(stream, detectEncodingFromByteOrderMarks: true); + var document = new LargeTextSourceDocument(reader, 5, Encoding.UTF8, "file.cshtml"); + + // Act + var firstChecksum = document.GetChecksum(); + var secondChecksum = document.GetChecksum(); + + // Assert + Assert.Equal(firstChecksum, secondChecksum); + Assert.NotSame(firstChecksum, secondChecksum); + } + + [Fact] + public void GetChecksum_ComputesCorrectChecksum_UTF8() + { + // Arrange + var contentString = "Hello World"; + var stream = TestRazorSourceDocument.CreateStreamContent(contentString); + var reader = new StreamReader(stream, detectEncodingFromByteOrderMarks: true); + var document = new LargeTextSourceDocument(reader, 5, Encoding.UTF8, "file.cshtml"); + var expectedChecksum = new byte[] { 10, 77, 85, 168, 215, 120, 229, 2, 47, 171, 112, 25, 119, 197, 216, 64, 187, 196, 134, 208 }; + + // Act + var checksum = document.GetChecksum(); + + // Assert + Assert.Equal(expectedChecksum, checksum); + } + + [Fact] + public void GetChecksum_ComputesCorrectChecksum_UTF32() + { + // Arrange + var contentString = "Hello World"; + var stream = TestRazorSourceDocument.CreateStreamContent(contentString, Encoding.UTF32); + var reader = new StreamReader(stream, detectEncodingFromByteOrderMarks: true); + var document = new LargeTextSourceDocument(reader, 5, Encoding.UTF32, "file.cshtml"); + var expectedChecksum = new byte[] { 108, 172, 130, 171, 42, 19, 155, 176, 211, 80, 224, 121, 169, 133, 25, 134, 48, 228, 199, 141 }; + + // Act + var checksum = document.GetChecksum(); + + // Assert + Assert.Equal(expectedChecksum, checksum); + } + [Theory] [InlineData(ChunkTestLength - 1)] [InlineData(ChunkTestLength)] @@ -31,7 +81,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Test var stream = TestRazorSourceDocument.CreateStreamContent(new string(content)); var reader = new StreamReader(stream, true); - var document = new LargeTextRazorSourceDocument(reader, ChunkTestLength, Encoding.UTF8, "file.cshtml"); + var document = new LargeTextSourceDocument(reader, ChunkTestLength, Encoding.UTF8, "file.cshtml"); // Act var output = new char[contentLength]; @@ -56,7 +106,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Test var reader = new StreamReader(stream, true); // Act - var document = new LargeTextRazorSourceDocument(reader, ChunkTestLength, Encoding.UTF8, fileName); + var document = new LargeTextSourceDocument(reader, ChunkTestLength, Encoding.UTF8, fileName); // Assert Assert.Equal(fileName, document.FileName); @@ -70,7 +120,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Test var reader = new StreamReader(stream, true); // Act - var document = new LargeTextRazorSourceDocument(reader, ChunkTestLength, Encoding.UTF8, "file.cshtml"); + var document = new LargeTextSourceDocument(reader, ChunkTestLength, Encoding.UTF8, "file.cshtml"); // Assert Assert.Equal(3, document.Lines.Count); @@ -92,7 +142,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Test var stream = TestRazorSourceDocument.CreateStreamContent("abcdefghijklmnopqrstuvwxyz"); var reader = new StreamReader(stream, true); - var document = new LargeTextRazorSourceDocument(reader, ChunkTestLength, Encoding.UTF8, "file.cshtml"); + var document = new LargeTextSourceDocument(reader, ChunkTestLength, Encoding.UTF8, "file.cshtml"); // Act var destination = new char[1000]; diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/RazorSourceDocumentTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/RazorSourceDocumentTest.cs index bc4065214d..bc2d714423 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/RazorSourceDocumentTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/RazorSourceDocumentTest.cs @@ -1,7 +1,6 @@ // 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.Text; using Xunit; @@ -19,7 +18,7 @@ namespace Microsoft.AspNetCore.Razor.Language var document = RazorSourceDocument.ReadFrom(content, "file.cshtml"); // Assert - Assert.IsType(document); + Assert.IsType(document); Assert.Equal("file.cshtml", document.FileName); Assert.Same(Encoding.UTF8, document.Encoding); } @@ -35,7 +34,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Assert Assert.Equal("file.cshtml", document.FileName); - Assert.Same(Encoding.UTF32, Assert.IsType(document).Encoding); + Assert.Same(Encoding.UTF32, Assert.IsType(document).Encoding); } [Fact] @@ -49,86 +48,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Assert Assert.Equal("file.cshtml", document.FileName); - Assert.Same(Encoding.UTF32, Assert.IsType(document).Encoding); - } - - [Fact] - public void ReadFrom_DetectsEncoding() - { - // Arrange - var content = TestRazorSourceDocument.CreateStreamContent(encoding: Encoding.UTF32); - - // Act - var document = RazorSourceDocument.ReadFrom(content, "file.cshtml"); - - // Assert - Assert.IsType(document); - Assert.Equal("file.cshtml", document.FileName); - Assert.Equal(Encoding.UTF32, document.Encoding); - } - - [Fact] - public void ReadFrom_EmptyStream_DetectsEncoding() - { - // Arrange - var content = TestRazorSourceDocument.CreateStreamContent(content: string.Empty, encoding: Encoding.UTF32); - - // Act - var document = RazorSourceDocument.ReadFrom(content, "file.cshtml"); - - // Assert - Assert.IsType(document); - Assert.Equal("file.cshtml", document.FileName); - Assert.Equal(Encoding.UTF32, document.Encoding); - } - - [Fact] - public void ReadFrom_FailsOnMismatchedEncoding() - { - // Arrange - var content = TestRazorSourceDocument.CreateStreamContent(encoding: Encoding.UTF32); - var expectedMessage = Resources.FormatMismatchedContentEncoding(Encoding.UTF8.EncodingName, Encoding.UTF32.EncodingName); - - // Act & Assert - var exception = Assert.Throws( - () => RazorSourceDocument.ReadFrom(content, "file.cshtml", Encoding.UTF8)); - Assert.Equal(expectedMessage, exception.Message); - } - - [Theory] - [InlineData(100000)] - [InlineData(RazorSourceDocument.LargeObjectHeapLimitInChars)] - [InlineData(RazorSourceDocument.LargeObjectHeapLimitInChars + 2)] - [InlineData(RazorSourceDocument.LargeObjectHeapLimitInChars * 2 - 1)] - [InlineData(RazorSourceDocument.LargeObjectHeapLimitInChars * 2)] - public void ReadFrom_LargeContent(int contentLength) - { - // Arrange - var content = new string('a', contentLength); - var stream = TestRazorSourceDocument.CreateStreamContent(content); - - // Act - var document = RazorSourceDocument.ReadFrom(stream, "file.cshtml"); - - // Assert - Assert.IsType(document); - Assert.Equal("file.cshtml", document.FileName); - Assert.Same(Encoding.UTF8, document.Encoding); - Assert.Equal(content, ReadContent(document)); - } - - [Fact] - public void ReadFrom_ProjectItem() - { - // Arrange - var projectItem = new TestRazorProjectItem("/test-path"); - - // Act - var document = RazorSourceDocument.ReadFrom(projectItem); - - // Assert - Assert.Equal(projectItem.Path, document.FileName); - Assert.Equal(projectItem.Content, ReadContent(document)); + Assert.Same(Encoding.UTF32, Assert.IsType(document).Encoding); } [Fact] @@ -145,6 +65,20 @@ namespace Microsoft.AspNetCore.Razor.Language Assert.Equal(projectItem.Content, ReadContent(document)); } + [Fact] + public void ReadFrom_ProjectItem() + { + // Arrange + var projectItem = new TestRazorProjectItem("/test-path"); + + // Act + var document = RazorSourceDocument.ReadFrom(projectItem); + + // Assert + Assert.Equal(projectItem.Path, document.FileName); + Assert.Equal(projectItem.Content, ReadContent(document)); + } + [Fact] public void Create_WithoutEncoding() { diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/StreamSourceDocumentTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/StreamSourceDocumentTest.cs new file mode 100644 index 0000000000..6ab12c5924 --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/StreamSourceDocumentTest.cs @@ -0,0 +1,147 @@ +// 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.IO; +using System.Text; +using Xunit; + +namespace Microsoft.AspNetCore.Razor.Language +{ + public class StreamSourceDocumentTest + { + [Fact] + public void GetChecksum_ReturnsCopiedChecksum() + { + // Arrange + var content = "Hello World!"; + var stream = CreateBOMStream(content, Encoding.UTF8); + var document = new StreamSourceDocument(stream, Encoding.UTF8, "file.cshtml"); + + // Act + var firstChecksum = document.GetChecksum(); + var secondChecksum = document.GetChecksum(); + + // Assert + Assert.Equal(firstChecksum, secondChecksum); + Assert.NotSame(firstChecksum, secondChecksum); + } + + [Fact] + public void GetChecksum_ComputesCorrectChecksum_UTF8() + { + // Arrange + var content = "Hello World!"; + var stream = CreateBOMStream(content, Encoding.UTF8); + var document = new StreamSourceDocument(stream, Encoding.UTF8, "file.cshtml"); + var expectedChecksum = new byte[] { 70, 180, 84, 105, 70, 79, 152, 31, 71, 157, 46, 159, 50, 83, 1, 243, 222, 48, 90, 18 }; + + // Act + var checksum = document.GetChecksum(); + + // Assert + Assert.Equal(expectedChecksum, checksum); + } + + [Fact] + public void GetChecksum_ComputesCorrectChecksum_UTF32AutoDetect() + { + // Arrange + var content = "Hello World!"; + var stream = CreateBOMStream(content, Encoding.UTF32); + var document = new StreamSourceDocument(stream, encoding: null, fileName: "file.cshtml"); + var expectedChecksum = new byte[] { 159, 154, 109, 89, 250, 163, 165, 108, 2, 112, 34, 4, 247, 161, 82, 168, 77, 213, 107, 71 }; + + // Act + var checksum = document.GetChecksum(); + + // Assert + Assert.Equal(expectedChecksum, checksum); + } + + [Fact] + public void ConstructedWithoutEncoding_DetectsEncoding() + { + // Arrange + var content = TestRazorSourceDocument.CreateStreamContent(encoding: Encoding.UTF32); + + // Act + var document = new StreamSourceDocument(content, encoding: null, fileName: "file.cshtml"); + + // Assert + Assert.IsType(document); + Assert.Equal("file.cshtml", document.FileName); + Assert.Equal(Encoding.UTF32, document.Encoding); + } + + [Fact] + public void ConstructedWithoutEncoding_EmptyStream_DetectsEncoding() + { + // Arrange + var content = TestRazorSourceDocument.CreateStreamContent(content: string.Empty, encoding: Encoding.UTF32); + + // Act + var document = new StreamSourceDocument(content, encoding: null, fileName: "file.cshtml"); + + // Assert + Assert.IsType(document); + Assert.Equal("file.cshtml", document.FileName); + Assert.Equal(Encoding.UTF32, document.Encoding); + } + + [Fact] + public void FailsOnMismatchedEncoding() + { + // Arrange + var content = TestRazorSourceDocument.CreateStreamContent(encoding: Encoding.UTF32); + var expectedMessage = Resources.FormatMismatchedContentEncoding(Encoding.UTF8.EncodingName, Encoding.UTF32.EncodingName); + + // Act & Assert + var exception = Assert.Throws( + () => new StreamSourceDocument(content, Encoding.UTF8, "file.cshtml")); + Assert.Equal(expectedMessage, exception.Message); + } + + [Theory] + [InlineData(100000)] + [InlineData(RazorSourceDocument.LargeObjectHeapLimitInChars)] + [InlineData(RazorSourceDocument.LargeObjectHeapLimitInChars + 2)] + [InlineData(RazorSourceDocument.LargeObjectHeapLimitInChars * 2 - 1)] + [InlineData(RazorSourceDocument.LargeObjectHeapLimitInChars * 2)] + public void DetectsSizeOfStreamForLargeContent(int contentLength) + { + // Arrange + var content = new string('a', contentLength); + var stream = TestRazorSourceDocument.CreateStreamContent(content); + + // Act + var document = new StreamSourceDocument(stream, encoding: null, fileName: "file.cshtml"); + + // Assert + var streamDocument = Assert.IsType(document); + Assert.IsType(streamDocument._innerSourceDocument); + Assert.Equal("file.cshtml", document.FileName); + Assert.Same(Encoding.UTF8, document.Encoding); + Assert.Equal(content, ReadContent(document)); + } + + private static MemoryStream CreateBOMStream(string content, Encoding encoding) + { + var preamble = encoding.GetPreamble(); + var contentBytes = encoding.GetBytes(content); + var buffer = new byte[preamble.Length + contentBytes.Length]; + preamble.CopyTo(buffer, 0); + contentBytes.CopyTo(buffer, preamble.Length); + var stream = new MemoryStream(buffer); + return stream; + } + + private static string ReadContent(RazorSourceDocument razorSourceDocument) + { + var buffer = new char[razorSourceDocument.Length]; + razorSourceDocument.CopyTo(0, buffer, 0, buffer.Length); + + return new string(buffer); + } + } +} diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorSourceDocumentTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/StringSourceDocumentTest.cs similarity index 70% rename from test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorSourceDocumentTest.cs rename to test/Microsoft.AspNetCore.Razor.Language.Test/StringSourceDocumentTest.cs index 9b90f27e88..980e9b2c9c 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorSourceDocumentTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/StringSourceDocumentTest.cs @@ -1,21 +1,66 @@ // 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 System.Text; using Xunit; namespace Microsoft.AspNetCore.Razor.Language { - public class DefaultRazorSourceDocumentTest + public class StringSourceDocumentTest { + [Fact] + public void GetChecksum_ReturnsCopiedChecksum() + { + // Arrange + var content = "Hello World!"; + var document = new StringSourceDocument(content, Encoding.UTF8, "file.cshtml"); + + // Act + var firstChecksum = document.GetChecksum(); + var secondChecksum = document.GetChecksum(); + + // Assert + Assert.Equal(firstChecksum, secondChecksum); + Assert.NotSame(firstChecksum, secondChecksum); + } + + [Fact] + public void GetChecksum_ComputesCorrectChecksum_UTF8() + { + // Arrange + var content = "Hello World!"; + var document = new StringSourceDocument(content, Encoding.UTF8, "file.cshtml"); + var expectedChecksum = new byte[] { 46, 247, 189, 230, 8, 206, 84, 4, 233, 125, 95, 4, 47, 149, 248, 159, 28, 35, 40, 113 }; + + // Act + var checksum = document.GetChecksum(); + + // Assert + Assert.Equal(expectedChecksum, checksum); + } + + [Fact] + public void GetChecksum_ComputesCorrectChecksum_UTF32() + { + // Arrange + var content = "Hello World!"; + var document = new StringSourceDocument(content, Encoding.UTF32, "file.cshtml"); + var expectedChecksum = new byte[] { 8, 149, 159, 15, 242, 255, 115, 227, 219, 78, 61, 53, 127, 239, 77, 239, 215, 140, 248, 44 }; + + // Act + var checksum = document.GetChecksum(); + + // Assert + Assert.Equal(expectedChecksum, checksum); + } + [Fact] public void Indexer_ProvidesCharacterAccessToContent() { // Arrange var expectedContent = "Hello, World!"; var indexerBuffer = new char[expectedContent.Length]; - var document = new DefaultRazorSourceDocument(expectedContent, Encoding.UTF8, fileName: "file.cshtml"); + var document = new StringSourceDocument(expectedContent, Encoding.UTF8, fileName: "file.cshtml"); // Act for (var i = 0; i < document.Length; i++) @@ -33,7 +78,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var expectedContent = "Hello, World!"; - var document = new DefaultRazorSourceDocument(expectedContent, Encoding.UTF8, fileName: "file.cshtml"); + var document = new StringSourceDocument(expectedContent, Encoding.UTF8, fileName: "file.cshtml"); // Act & Assert Assert.Equal(expectedContent.Length, document.Length); @@ -46,7 +91,7 @@ namespace Microsoft.AspNetCore.Razor.Language var content = "Hello, World!"; // Act - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: "file.cshtml"); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: "file.cshtml"); // Assert Assert.Equal("file.cshtml", document.FileName); @@ -59,7 +104,7 @@ namespace Microsoft.AspNetCore.Razor.Language var content = "Hello, World!"; // Act - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Assert Assert.Null(document.FileName); @@ -70,7 +115,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "Hello, World!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); var expectedContent = "Hello"; var charBuffer = new char[expectedContent.Length]; @@ -87,7 +132,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "Hello, World!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); var expectedContent = "$Hello"; var charBuffer = new char[expectedContent.Length]; charBuffer[0] = '$'; @@ -105,7 +150,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "Hello, World!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); var expectedContent = "World"; var charBuffer = new char[expectedContent.Length]; @@ -122,7 +167,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "Hi"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); var charBuffer = new char[2]; // Act @@ -138,7 +183,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "Hi"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act & Assert // @@ -157,7 +202,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = string.Empty; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = document.Lines.Count; @@ -171,7 +216,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = string.Empty; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = document.Lines.GetLineLength(0); @@ -185,7 +230,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "hello\n"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = document.Lines.GetLineLength(0); @@ -199,7 +244,7 @@ namespace Microsoft.AspNetCore.Razor.Language { // Arrange var content = "hello\r\n"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = document.Lines.GetLineLength(0); @@ -218,13 +263,13 @@ namespace Microsoft.AspNetCore.Razor.Language .Append("jumps over the lazy dog.") .ToString(); - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = GetAllLineMappings(document); // Assert - Assert.Equal(new int[]{ 16, 5, 24 }, actual); + Assert.Equal(new int[] { 16, 5, 24 }, actual); } [Fact] @@ -233,7 +278,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\r\nWorld!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = GetAllLineMappings(document); @@ -248,7 +293,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\rWorld!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = GetAllLineMappings(document); @@ -264,7 +309,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\rBig\r\nWorld!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = GetAllLineMappings(document); @@ -279,7 +324,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\nWorld!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = GetAllLineMappings(document); @@ -294,7 +339,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\u0085World!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = GetAllLineMappings(document); @@ -309,7 +354,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\u2028World!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = GetAllLineMappings(document); @@ -324,7 +369,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\u2029World!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = GetAllLineMappings(document); @@ -339,7 +384,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello, World!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: "Hi.cshtml"); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: "Hi.cshtml"); // Act var actual = document.Lines.GetLocation(1); @@ -357,7 +402,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\nBig\r\nWorld!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = document.Lines.GetLocation(0); @@ -373,7 +418,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\nBig\r\nWorld!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = document.Lines.GetLocation(5); @@ -389,7 +434,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\nBig\r\nWorld!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = document.Lines.GetLocation(7); @@ -405,7 +450,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\nBig\r\nWorld!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = document.Lines.GetLocation(11); @@ -421,7 +466,7 @@ namespace Microsoft.AspNetCore.Razor.Language // Arrange var content = "Hello\nBig\r\nWorld!"; - var document = new DefaultRazorSourceDocument(content, Encoding.UTF8, fileName: null); + var document = new StringSourceDocument(content, Encoding.UTF8, fileName: null); // Act var actual = document.Lines.GetLocation(16); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithBaseType.codegen.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithBaseType.codegen.cs index 6c4449207d..50b0dc2ca5 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithBaseType.codegen.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithBaseType.codegen.cs @@ -1,4 +1,4 @@ -#pragma checksum "TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithBaseType.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "247d02621904d87ab805e437f33c5d03b9a0de91" +#pragma checksum "TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithBaseType.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "38aa8e26c5d2a85c61d8e93fe69dd326fe82671b" namespace Razor { #line hidden diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.codegen.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.codegen.cs index d2d0e10bf0..78167c41e6 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.codegen.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.codegen.cs @@ -1,4 +1,4 @@ -#pragma checksum "TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "247d02621904d87ab805e437f33c5d03b9a0de91" +#pragma checksum "TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithConfigureClass.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "38aa8e26c5d2a85c61d8e93fe69dd326fe82671b" namespace Razor { #line hidden diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithDefaults.codegen.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithDefaults.codegen.cs index 89da6ca0cc..d070fabb65 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithDefaults.codegen.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithDefaults.codegen.cs @@ -1,4 +1,4 @@ -#pragma checksum "TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithDefaults.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "247d02621904d87ab805e437f33c5d03b9a0de91" +#pragma checksum "TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithDefaults.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "38aa8e26c5d2a85c61d8e93fe69dd326fe82671b" namespace Razor { #line hidden diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithSetNamespace.codegen.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithSetNamespace.codegen.cs index 1f20dfb4c9..cb94ed09d7 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithSetNamespace.codegen.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithSetNamespace.codegen.cs @@ -1,4 +1,4 @@ -#pragma checksum "TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithSetNamespace.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "247d02621904d87ab805e437f33c5d03b9a0de91" +#pragma checksum "TestFiles/IntegrationTests/RazorTemplateEngineIntegrationTest/GenerateCodeWithSetNamespace.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "38aa8e26c5d2a85c61d8e93fe69dd326fe82671b" namespace MyApp.Razor.Views { #line hidden diff --git a/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/TestRazorProjectItem.cs b/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/TestRazorProjectItem.cs index 4c102c1b4d..623a04c711 100644 --- a/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/TestRazorProjectItem.cs +++ b/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/TestRazorProjectItem.cs @@ -28,6 +28,18 @@ namespace Microsoft.AspNetCore.Razor.Language public string Content { get; set; } = "Default content"; - public override Stream Read() => new MemoryStream(Encoding.UTF8.GetBytes(Content)); + public override Stream Read() + { + // Act like a file and have a UTF8 BOM. + var preamble = Encoding.UTF8.GetPreamble(); + var contentBytes = Encoding.UTF8.GetBytes(Content); + var buffer = new byte[preamble.Length + contentBytes.Length]; + preamble.CopyTo(buffer, 0); + contentBytes.CopyTo(buffer, preamble.Length); + + var stream = new MemoryStream(buffer); + + return stream; + } } } diff --git a/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/TestRazorSourceDocument.cs b/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/TestRazorSourceDocument.cs index 9b356adcc4..57a5fb196e 100644 --- a/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/TestRazorSourceDocument.cs +++ b/test/Microsoft.AspNetCore.Razor.Test.Common/Langauge/TestRazorSourceDocument.cs @@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Razor.Language content = NormalizeNewLines(content); } - return new DefaultRazorSourceDocument(content, encoding ?? Encoding.UTF8, path); + return new StringSourceDocument(content, encoding ?? Encoding.UTF8, path); } } @@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Razor.Language content = NormalizeNewLines(content); } - return new DefaultRazorSourceDocument(content, encoding ?? Encoding.UTF8, fileName); + return new StringSourceDocument(content, encoding ?? Encoding.UTF8, fileName); } private static string NormalizeNewLines(string content)