123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the MIT license.
- using Moq;
- namespace Microsoft.NET.Sdk.Razor.Tests
- {
- public class BuildIncrementalismTest : AspNetSdkTest
- {
- public BuildIncrementalismTest(ITestOutputHelper log) : base(log) { }
- [Fact(Skip = "https://github.com/dotnet/aspnetcore/issues/28780")]
- public void Build_ErrorInGeneratedCode_ReportsMSBuildError_OnIncrementalBuild()
- {
- var testAsset = "RazorSimpleMvc";
- var projectDirectory = CreateAspNetSdkTestAsset(testAsset);
- // Introducing a Razor semantic error
- var indexPage = Path.Combine(projectDirectory.Path, "Views", "Home", "Index.cshtml");
- File.WriteAllText(indexPage, "@{ // Unterminated code block");
- // Regular build
- VerifyError(projectDirectory);
- // Incremental build
- VerifyError(projectDirectory);
- void VerifyError(TestAsset privateDirectory)
- {
- var build = new BuildCommand(projectDirectory);
- var result = build.Execute();
- result.Should().Fail().And.HaveStdOutContaining("RZ1006");
- var intermediateOutputPath = build.GetIntermediateDirectory(DefaultTfm, "Debug").ToString();
- // Compilation failed without creating the views assembly
- new FileInfo(Path.Combine(intermediateOutputPath, "SimpleMvc.dll")).Should().Exist();
- new FileInfo(Path.Combine(intermediateOutputPath, "SimpleMvc.Views.dll")).Should().NotExist();
- // File with error does not get written to disk.
- new FileInfo(Path.Combine(intermediateOutputPath, "Razor", "Views", "Home", "Index.cshtml.g.cs")).Should().NotExist();
- }
- }
- [Fact(Skip = "https://github.com/dotnet/aspnetcore/issues/28780")]
- public void BuildComponents_DoesNotRegenerateComponentDefinition_WhenDefinitionIsUnchanged()
- {
- var testAsset = "RazorMvcWithComponents";
- var projectDirectory = CreateAspNetSdkTestAsset(testAsset);
- // Act - 1
- var build = new BuildCommand(projectDirectory);
- var intermediateOutputPath = build.GetIntermediateDirectory(DefaultTfm, "Debug").ToString();
- var outputPath = build.GetOutputDirectory(DefaultTfm, "Debug").ToString();
- var updatedContent = "Some content";
- var tagHelperOutputCache = Path.Combine(intermediateOutputPath, "MvcWithComponents.TagHelpers.output.cache");
- var generatedFile = Path.Combine(intermediateOutputPath, "Razor", "Views", "Shared", "NavMenu.razor.g.cs");
- var generatedDefinitionFile = Path.Combine(intermediateOutputPath, "RazorDeclaration", "Views", "Shared", "NavMenu.razor.g.cs");
- // Assert - 1
- var result = build.Execute();
- result.Should().Pass();
- var outputFile = Path.Combine(outputPath, "MvcWithComponents.dll");
- new FileInfo(outputFile).Should().Exist();
- var outputAssemblyThumbprint = FileThumbPrint.Create(outputFile);
- new FileInfo(generatedDefinitionFile).Should().Exist();
- var generatedDefinitionThumbprint = FileThumbPrint.Create(generatedDefinitionFile);
- new FileInfo(generatedFile).Should().Exist();
- var generatedFileThumbprint = FileThumbPrint.Create(generatedFile);
- new FileInfo(tagHelperOutputCache).Should().Exist();
- new FileInfo(tagHelperOutputCache).Should().Contain(@"""Name"":""MvcWithComponents.Views.Shared.NavMenu""");
- var definitionThumbprint = FileThumbPrint.Create(tagHelperOutputCache);
- // Act - 2
- var page = Path.Combine(projectDirectory.Path, "Views", "Shared", "NavMenu.razor");
- File.WriteAllText(page, updatedContent, Encoding.UTF8);
- File.SetLastWriteTimeUtc(page, File.GetLastWriteTimeUtc(page).AddSeconds(1));
- build = new BuildCommand(projectDirectory);
- result = build.Execute();
- // Assert - 2
- new FileInfo(generatedDefinitionFile).Should().Exist();
- // Definition file remains unchanged.
- Assert.Equal(generatedDefinitionThumbprint, FileThumbPrint.Create(generatedDefinitionFile));
- new FileInfo(generatedFile).Should().Exist();
- // Generated file should change and include the new content.
- Assert.NotEqual(generatedFileThumbprint, FileThumbPrint.Create(generatedFile));
- new FileInfo(generatedFile).Should().Contain(updatedContent);
- // TagHelper cache should remain unchanged.
- Assert.Equal(definitionThumbprint, FileThumbPrint.Create(tagHelperOutputCache));
- }
- [Fact(Skip = "https://github.com/dotnet/aspnetcore/issues/28780")]
- public void Build_TouchesUpToDateMarkerFile()
- {
- var testAsset = "RazorClassLibrary";
- var projectDirectory = CreateAspNetSdkTestAsset(testAsset);
- // Remove the components so that they don't interfere with these tests
- Directory.Delete(Path.Combine(projectDirectory.Path, "Components"), recursive: true);
- var build = new BuildCommand(projectDirectory);
- build.Execute()
- .Should()
- .Pass();
- string intermediateOutputPath = Path.Combine(build.GetBaseIntermediateDirectory().FullName, "Debug", DefaultTfm);
- var classLibraryDll = Path.Combine(intermediateOutputPath, "ClassLibrary.dll");
- var classLibraryViewsDll = Path.Combine(intermediateOutputPath, "ClassLibrary.Views.dll");
- var markerFile = Path.Combine(intermediateOutputPath, "ClassLibrary.csproj.CopyComplete"); ;
- new FileInfo(classLibraryDll).Should().Exist();
- new FileInfo(classLibraryViewsDll).Should().Exist();
- new FileInfo(markerFile).Should().Exist();
- // Gather thumbprints before incremental build.
- var classLibraryThumbPrint = FileThumbPrint.Create(classLibraryDll);
- var classLibraryViewsThumbPrint = FileThumbPrint.Create(classLibraryViewsDll);
- var markerFileThumbPrint = FileThumbPrint.Create(markerFile);
- build = new BuildCommand(projectDirectory);
- build.Execute()
- .Should()
- .Pass();
- // Verify thumbprint file is unchanged between true incremental builds
- Assert.Equal(classLibraryThumbPrint, FileThumbPrint.Create(classLibraryDll));
- Assert.Equal(classLibraryViewsThumbPrint, FileThumbPrint.Create(classLibraryViewsDll));
- // In practice, this should remain unchanged. However, since our tests reference
- // binaries from other projects, this file gets updated by Microsoft.Common.targets
- Assert.NotEqual(markerFileThumbPrint, FileThumbPrint.Create(markerFile));
- // Change a cshtml file and verify ClassLibrary.Views.dll and marker file are updated
- File.AppendAllText(Path.Combine(projectDirectory.Path, "Views", "_ViewImports.cshtml"), Environment.NewLine);
- build = new BuildCommand(projectDirectory);
- build.Execute()
- .Should()
- .Pass();
- Assert.Equal(classLibraryThumbPrint, FileThumbPrint.Create(classLibraryDll));
- Assert.NotEqual(classLibraryViewsThumbPrint, FileThumbPrint.Create(classLibraryViewsDll));
- Assert.NotEqual(markerFileThumbPrint, FileThumbPrint.Create(markerFile));
- }
- private IDisposable LockDirectory(string directory)
- {
- var disposables = new List<IDisposable>();
- foreach (var file in Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories))
- {
- disposables.Add(File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None));
- }
- var disposable = new Mock<IDisposable>();
- disposable.Setup(d => d.Dispose())
- .Callback(() => disposables.ForEach(d => d.Dispose()));
- return disposable.Object;
- }
- }
- }
|