diff --git a/src/Microsoft.AspNetCore.Razor.Tools/DiscoverCommand.cs b/src/Microsoft.AspNetCore.Razor.Tools/DiscoverCommand.cs index 9ca5b3d8bb..2fedb87022 100644 --- a/src/Microsoft.AspNetCore.Razor.Tools/DiscoverCommand.cs +++ b/src/Microsoft.AspNetCore.Razor.Tools/DiscoverCommand.cs @@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.Razor.Tools { Serialize(stream, tagHelpers); - stream.Position = 0L; + stream.Position = 0; var newHash = Hash(stream); var existingHash = Hash(outputFilePath); @@ -158,7 +158,7 @@ namespace Microsoft.AspNetCore.Razor.Tools if (!HashesEqual(newHash, existingHash)) { stream.Position = 0; - using (var output = File.OpenWrite(outputFilePath)) + using (var output = File.Open(outputFilePath, FileMode.Create)) { stream.CopyTo(output); } diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/Assert.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/Assert.cs index 12445df451..b41e7e4bcc 100644 --- a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/Assert.cs +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/Assert.cs @@ -136,6 +136,23 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests } } + public static void FileContentEquals(MSBuildResult result, string filePath, string expected) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + filePath = Path.Combine(result.Project.DirectoryPath, filePath); + FileExists(result, filePath); + + var actual = File.ReadAllText(filePath); + if (!actual.Equals(expected, StringComparison.Ordinal)) + { + throw new FileContentNotEqualException(result, filePath, expected, actual); + } + } + public static void FileContainsLine(MSBuildResult result, string filePath, string match) { if (result == null) @@ -470,6 +487,36 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests } } + private class FileContentNotEqualException : MSBuildXunitException + { + public FileContentNotEqualException(MSBuildResult result, string filePath, string expected, string actual) + : base(result) + { + FilePath = filePath; + Expected = expected; + Actual = actual; + } + + public string Actual { get; } + + public string FilePath { get; } + + public string Expected { get; } + + protected override string Heading + { + get + { + var builder = new StringBuilder(); + builder.AppendFormat("File content of '{0}' did not match the expected content: '{1}'.", FilePath, Expected); + builder.AppendLine(); + builder.AppendLine(); + builder.AppendLine(Actual); + return builder.ToString(); + } + } + } + private class FileMissingException : MSBuildXunitException { public FileMissingException(MSBuildResult result, string filePath) diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildIncrementalismTest.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildIncrementalismTest.cs index 6e2a123cdb..75cc832f72 100644 --- a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildIncrementalismTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildIncrementalismTest.cs @@ -56,5 +56,34 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests } } } + + [Fact] + [InitializeTestProject("SimpleMvc")] + public async Task RazorGenerate_RegeneratesTagHelperInputs_IfFileChanges() + { + // Act - 1 + var expectedTagHelperCacheContent = @"""Name"":""SimpleMvc.SimpleTagHelper"""; + var result = await DotnetMSBuild("Build", "/p:RazorCompileOnBuild=true"); + var file = Path.Combine(Project.DirectoryPath, "SimpleTagHelper.cs"); + var tagHelperOutputCache = Path.Combine(IntermediateOutputPath, "SimpleMvc.TagHelpers.output.cache"); + var generatedFile = Path.Combine(RazorIntermediateOutputPath, "Views", "Home", "Index.cs"); + + // Assert - 1 + Assert.BuildPassed(result); + Assert.FileContains(result, tagHelperOutputCache, expectedTagHelperCacheContent); + var fileThumbPrint = GetThumbPrint(generatedFile); + + // Act - 2 + // Update the source content and build. We should expect the outputs to be regenerated. + ReplaceContent(string.Empty, file); + result = await DotnetMSBuild("Build", "/p:RazorCompileOnBuild=true"); + + // Assert - 2 + Assert.BuildPassed(result); + Assert.FileContentEquals(result, tagHelperOutputCache, "[]"); + var newThumbPrint = GetThumbPrint(generatedFile); + Assert.NotEqual(fileThumbPrint, newThumbPrint); + } + } } diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildIntegrationTestBase.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildIntegrationTestBase.cs index b69109869b..020887b57c 100644 --- a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildIntegrationTestBase.cs +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildIntegrationTestBase.cs @@ -92,6 +92,9 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests } File.WriteAllText(filePath, content, Encoding.UTF8); + // Timestamps on xplat are precise only to a second. Update it's last write time by at least 1 second + // so we can ensure that MSBuild recognizes the file change. See https://github.com/dotnet/corefx/issues/26024 + File.SetLastWriteTimeUtc(filePath, File.GetLastWriteTimeUtc(filePath).AddSeconds(1)); } /// diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/RazorGenerateIntegrationTest.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/RazorGenerateIntegrationTest.cs index bab76935dd..c5254cfe37 100644 --- a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/RazorGenerateIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/RazorGenerateIntegrationTest.cs @@ -109,9 +109,6 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests // Act - 2 // Update the source content and build. We should expect the outputs to be regenerated. - // Timestamps on xplat are precise only to a second. Add a delay so we can ensure that MSBuild recognizes the - // file change. See https://github.com/dotnet/corefx/issues/26024 - await Task.Delay(TimeSpan.FromSeconds(1)); ReplaceContent("Uodated content", file); result = await DotnetMSBuild(RazorGenerateTarget); @@ -189,37 +186,6 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests Assert.FileDoesNotExist(result, generatedFile); } - [Fact(Skip = "https://github.com/aspnet/Razor/issues/2104")] - [InitializeTestProject("SimpleMvc")] - public async Task RazorGenerate_Rebuilds_IfTagHelpersChanged() - { - // Act - 1 - var expectedTagHelperCacheContent = @"""Name"":""SimpleMvc.SimpleTagHelper"""; - var result = await DotnetMSBuild(RazorGenerateTarget); - var file = Path.Combine(Project.DirectoryPath, "SimpleTagHelper.cs"); - var tagHelperOutputCache = Path.Combine(IntermediateOutputPath, "SimpleMvc.TagHelpers.output.cache"); - var generatedFile = Path.Combine(RazorIntermediateOutputPath, "Views", "Home", "Index.cs"); - - // Assert - 1 - Assert.BuildPassed(result); - Assert.FileContains(result, tagHelperOutputCache, expectedTagHelperCacheContent); - var fileThumbPrint = GetThumbPrint(generatedFile); - - // Act - 2 - // Update the source content and build. We should expect the outputs to be regenerated. - // Timestamps on xplat are precise only to a second. Add a delay so we can ensure that MSBuild recognizes the - // file change. See https://github.com/dotnet/corefx/issues/26024 - await Task.Delay(TimeSpan.FromSeconds(1)); - ReplaceContent(string.Empty, file); - result = await DotnetMSBuild(RazorGenerateTarget); - - // Assert - 2 - Assert.BuildPassed(result); - Assert.FileDoesNotContain(result, tagHelperOutputCache, expectedTagHelperCacheContent); - var newThumbPrint = GetThumbPrint(generatedFile); - Assert.NotEqual(fileThumbPrint, newThumbPrint); - } - [Fact] [InitializeTestProject("SimpleMvc")] public async Task RazorGenerate_Noops_WithNoFiles() diff --git a/test/testapps/SimpleMvc/SimpleTagHelper.cs b/test/testapps/SimpleMvc/SimpleTagHelper.cs index a2abedef92..7cc52922d9 100644 --- a/test/testapps/SimpleMvc/SimpleTagHelper.cs +++ b/test/testapps/SimpleMvc/SimpleTagHelper.cs @@ -5,4 +5,4 @@ namespace SimpleMvc public class SimpleTagHelper : TagHelper { } -} \ No newline at end of file +}