diff --git a/test/FunctionalTests/CoreCLRTests/ApplicationWithParseErrorsTest_CoreCLR.cs b/test/FunctionalTests/CoreCLRTests/ApplicationWithParseErrorsTest_CoreCLR.cs index 77159e5e13..076d71f6ba 100644 --- a/test/FunctionalTests/CoreCLRTests/ApplicationWithParseErrorsTest_CoreCLR.cs +++ b/test/FunctionalTests/CoreCLRTests/ApplicationWithParseErrorsTest_CoreCLR.cs @@ -24,9 +24,8 @@ namespace FunctionalTests public async Task PublishingPrintsParseErrors() { // Arrange - var applicationPath = ApplicationPaths.GetTestAppDirectory("ApplicationWithParseErrors"); - var indexPath = Path.Combine(applicationPath, "Views", "Home", "Index.cshtml"); - var viewImportsPath = Path.Combine(applicationPath, "Views", "Home", "About.cshtml"); + var indexPath = Path.Combine(Fixture.TestProjectDirectory, "Views", "Home", "Index.cshtml"); + var viewImportsPath = Path.Combine(Fixture.TestProjectDirectory, "Views", "Home", "About.cshtml"); var expectedErrors = new[] { indexPath + " (0): The code block is missing a closing \"}\" character. Make sure you have a matching \"}\" character for all the \"{\" characters within this block, and that none of the \"}\" characters are being interpreted as markup.", diff --git a/test/FunctionalTests/CoreCLRTests/ApplicationWithTagHelpersTest_CoreCLR.cs b/test/FunctionalTests/CoreCLRTests/ApplicationWithTagHelpersTest_CoreCLR.cs index b1d3664da6..3f42c7c1c7 100644 --- a/test/FunctionalTests/CoreCLRTests/ApplicationWithTagHelpersTest_CoreCLR.cs +++ b/test/FunctionalTests/CoreCLRTests/ApplicationWithTagHelpersTest_CoreCLR.cs @@ -1,7 +1,10 @@ // 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.Threading.Tasks; +using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Testing; using Xunit; using Xunit.Abstractions; @@ -9,10 +12,10 @@ using Xunit.Abstractions; namespace FunctionalTests { public class ApplicationWithTagHelpersTest_CoreCLR : - LoggedTest, IClassFixture> + LoggedTest, IClassFixture { public ApplicationWithTagHelpersTest_CoreCLR( - CoreCLRApplicationTestFixture fixture, + ApplicationWithTagHelpersTestFixture fixture, ITestOutputHelper output) : base(output) { @@ -56,5 +59,17 @@ namespace FunctionalTests TestEmbeddedResource.AssertContent($"ApplicationWithTagHelpers.Home.LocalTagHelper.txt", response); } } + + public class ApplicationWithTagHelpersTestFixture : CoreCLRApplicationTestFixture + { + protected override Task CreateDeploymentAsyncCore(ILoggerFactory loggerFactory) + { + CopyDirectory( + new DirectoryInfo(Path.Combine(ApplicationPath, "..", "ClassLibraryTagHelper")), + new DirectoryInfo(Path.Combine(WorkingDirectory, "ClassLibraryTagHelper"))); + + return base.CreateDeploymentAsyncCore(loggerFactory); + } + } } } diff --git a/test/FunctionalTests/CoreCLRTests/PublishWithDebugTest_CoreCLR.cs b/test/FunctionalTests/CoreCLRTests/PublishWithDebugTest_CoreCLR.cs deleted file mode 100644 index c66e4b68a5..0000000000 --- a/test/FunctionalTests/CoreCLRTests/PublishWithDebugTest_CoreCLR.cs +++ /dev/null @@ -1,56 +0,0 @@ -// 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.Threading.Tasks; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.Extensions.Logging.Testing; -using Xunit; -using Xunit.Abstractions; - -namespace FunctionalTests -{ - public class PublishWithDebugTest_CoreCLR : - LoggedTest, IClassFixture - { - public PublishWithDebugTest_CoreCLR( - TestFixture fixture, - ITestOutputHelper output) - : base(output) - { - Fixture = fixture; - } - - public ApplicationTestFixture Fixture { get; } - - [Fact] - public async Task PublishingInDebugWorks() - { - using (StartLog(out var loggerFactory)) - { - // Arrange - var deployment = await Fixture.CreateDeploymentAsync(loggerFactory); - - // Assert - var expected = Path.Combine(deployment.ContentRoot, $"{Fixture.ApplicationName}.PrecompiledViews.dll"); - Assert.True(File.Exists(expected), $"File {expected} does not exist."); - } - } - - public class TestFixture : CoreCLRApplicationTestFixture - { - public TestFixture() - { - PublishOnly = true; - } - - protected override DeploymentParameters GetDeploymentParameters() - { - var deploymentParameters = base.GetDeploymentParameters(); - deploymentParameters.Configuration = "Debug"; - - return deploymentParameters; - } - } - } -} diff --git a/test/FunctionalTests/CoreCLRTests/SimpleAppTest_CoreCLR.cs b/test/FunctionalTests/CoreCLRTests/SimpleAppTest_CoreCLR.cs index 9b90c31a17..18e17b588e 100644 --- a/test/FunctionalTests/CoreCLRTests/SimpleAppTest_CoreCLR.cs +++ b/test/FunctionalTests/CoreCLRTests/SimpleAppTest_CoreCLR.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.IO; using System.Threading.Tasks; using Microsoft.Extensions.Logging.Testing; using Xunit; @@ -22,7 +21,7 @@ namespace FunctionalTests public ApplicationTestFixture Fixture { get; } - [Fact(Skip = "Unblocking the build - https://github.com/aspnet/MvcPrecompilation/issues/224")] + [Fact] public async Task Precompilation_WorksForSimpleApps() { using (StartLog(out var loggerFactory)) diff --git a/test/FunctionalTests/DesktopTests/ApplicationWithParseErrorsTest_Desktop.cs b/test/FunctionalTests/DesktopTests/ApplicationWithParseErrorsTest_Desktop.cs index 587cbd9b32..b0fcb22c79 100644 --- a/test/FunctionalTests/DesktopTests/ApplicationWithParseErrorsTest_Desktop.cs +++ b/test/FunctionalTests/DesktopTests/ApplicationWithParseErrorsTest_Desktop.cs @@ -27,9 +27,8 @@ namespace FunctionalTests public async Task PublishingPrintsParseErrors() { // Arrange - var applicationPath = ApplicationPaths.GetTestAppDirectory("ApplicationWithParseErrors"); - var indexPath = Path.Combine(applicationPath, "Views", "Home", "Index.cshtml"); - var viewImportsPath = Path.Combine(applicationPath, "Views", "Home", "About.cshtml"); + var indexPath = Path.Combine(Fixture.TestProjectDirectory, "Views", "Home", "Index.cshtml"); + var viewImportsPath = Path.Combine(Fixture.TestProjectDirectory, "Views", "Home", "About.cshtml"); var expectedErrors = new[] { indexPath + " (0): The code block is missing a closing \"}\" character. Make sure you have a matching \"}\" character for all the \"{\" characters within this block, and that none of the \"}\" characters are being interpreted as markup.", diff --git a/test/FunctionalTests/DesktopTests/ApplicationWithTagHelpersTest_Desktop.cs b/test/FunctionalTests/DesktopTests/ApplicationWithTagHelpersTest_Desktop.cs index 8b3508be2b..68d661e2d8 100644 --- a/test/FunctionalTests/DesktopTests/ApplicationWithTagHelpersTest_Desktop.cs +++ b/test/FunctionalTests/DesktopTests/ApplicationWithTagHelpersTest_Desktop.cs @@ -1,8 +1,11 @@ // 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.Threading.Tasks; +using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Testing; using Xunit; using Xunit.Abstractions; @@ -12,10 +15,10 @@ namespace FunctionalTests [OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.MacOSX)] public class ApplicationWithTagHelpersTest_Desktop : - LoggedTest, IClassFixture> + LoggedTest, IClassFixture { public ApplicationWithTagHelpersTest_Desktop( - DesktopApplicationTestFixture fixture, + ApplicationWithTagHelpersTestFixture fixture, ITestOutputHelper output) : base(output) { @@ -59,5 +62,17 @@ namespace FunctionalTests TestEmbeddedResource.AssertContent($"ApplicationWithTagHelpers.Home.LocalTagHelper.txt", response); } } + + public class ApplicationWithTagHelpersTestFixture : DesktopApplicationTestFixture + { + protected override Task CreateDeploymentAsyncCore(ILoggerFactory loggerFactory) + { + CopyDirectory( + new DirectoryInfo(Path.Combine(ApplicationPath, "..", "ClassLibraryTagHelper")), + new DirectoryInfo(Path.Combine(WorkingDirectory, "ClassLibraryTagHelper"))); + + return base.CreateDeploymentAsyncCore(loggerFactory); + } + } } } diff --git a/test/FunctionalTests/DesktopTests/PublishWithDebugTest_Desktop.cs b/test/FunctionalTests/DesktopTests/SimpleAppTestWithPlatformx86_Desktop.cs similarity index 53% rename from test/FunctionalTests/DesktopTests/PublishWithDebugTest_Desktop.cs rename to test/FunctionalTests/DesktopTests/SimpleAppTestWithPlatformx86_Desktop.cs index 8dd660f420..ca47095612 100644 --- a/test/FunctionalTests/DesktopTests/PublishWithDebugTest_Desktop.cs +++ b/test/FunctionalTests/DesktopTests/SimpleAppTestWithPlatformx86_Desktop.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.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Testing.xunit; @@ -13,11 +12,11 @@ namespace FunctionalTests { [OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.MacOSX)] - public class PublishWithDebugTest_Desktop : - LoggedTest, IClassFixture + public class SimpleAppTestWithPlatformx86_Desktop : + LoggedTest, IClassFixture> { - public PublishWithDebugTest_Desktop( - TestFixture fixture, + public SimpleAppTestWithPlatformx86_Desktop( + DesktopApplicationTestFixture fixture, ITestOutputHelper output) : base(output) { @@ -27,32 +26,31 @@ namespace FunctionalTests public ApplicationTestFixture Fixture { get; } [ConditionalFact] - public async Task PublishingInDebugWorks() + public async Task Precompilation_PublishingForPlatform() { using (StartLog(out var loggerFactory)) { // Arrange var deployment = await Fixture.CreateDeploymentAsync(loggerFactory); + // Act + var response = await deployment.HttpClient.GetStringWithRetryAsync( + deployment.ApplicationBaseUri, + loggerFactory.CreateLogger(Fixture.ApplicationName)); + // Assert - var expected = Path.Combine(deployment.ContentRoot, $"{Fixture.ApplicationName}.PrecompiledViews.dll"); - Assert.True(File.Exists(expected), $"File {expected} does not exist."); + TestEmbeddedResource.AssertContent("SimpleAppTest.Home.Index.txt", response); } } - public class TestFixture : DesktopApplicationTestFixture + public class SimpleAppTestWithPlatformx86_DesktopFixture : DesktopApplicationTestFixture { - public TestFixture() - { - PublishOnly = true; - } - protected override DeploymentParameters GetDeploymentParameters() { - var deploymentParameters = base.GetDeploymentParameters(); - deploymentParameters.Configuration = "Debug"; + var parameters = base.GetDeploymentParameters(); + parameters.AdditionalPublishParameters = "/p:Platform=x86"; - return deploymentParameters; + return parameters; } } } diff --git a/test/FunctionalTests/DesktopTests/SimpleAppTest_Desktop.cs b/test/FunctionalTests/DesktopTests/SimpleAppTest_Desktop.cs index fb70a5a53e..e3fa91caa5 100644 --- a/test/FunctionalTests/DesktopTests/SimpleAppTest_Desktop.cs +++ b/test/FunctionalTests/DesktopTests/SimpleAppTest_Desktop.cs @@ -25,7 +25,7 @@ namespace FunctionalTests public ApplicationTestFixture Fixture { get; } - [ConditionalFact(Skip = "Unblocking the build - https://github.com/aspnet/MvcPrecompilation/issues/224")] + [ConditionalFact] public async Task Precompilation_WorksForSimpleApps() { using (StartLog(out var loggerFactory)) diff --git a/test/FunctionalTests/Infrastructure/ApplicationTestFixture.cs b/test/FunctionalTests/Infrastructure/ApplicationTestFixture.cs index 4df83aeec5..931e14422d 100644 --- a/test/FunctionalTests/Infrastructure/ApplicationTestFixture.cs +++ b/test/FunctionalTests/Infrastructure/ApplicationTestFixture.cs @@ -3,9 +3,11 @@ using System; using System.Collections.Generic; +using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.Logging; namespace FunctionalTests @@ -13,28 +15,44 @@ namespace FunctionalTests public abstract class ApplicationTestFixture : IDisposable { private const string DotnetCLITelemetryOptOut = "DOTNET_CLI_TELEMETRY_OPTOUT"; - private static readonly SemaphoreSlim _deploymentLock = new SemaphoreSlim(initialCount: 1); + private static readonly string SolutionDirectory; + private Task _deploymentTask; private ApplicationDeployer _deployer; + static ApplicationTestFixture() + { + SolutionDirectory = TestPathUtilities.GetSolutionRootDirectory("RazorViewCompilation"); + if (!SolutionDirectory.EndsWith(Path.DirectorySeparatorChar.ToString())) + { + SolutionDirectory += Path.DirectorySeparatorChar; + } + } + protected ApplicationTestFixture(string applicationName, string applicationPath) { ApplicationName = applicationName; ApplicationPath = applicationPath ?? ApplicationPaths.GetTestAppDirectory(applicationName); + WorkingDirectory = Path.Combine(Path.GetTempPath(), "PrecompilationTool", Path.GetRandomFileName()); + TestProjectDirectory = Path.Combine(WorkingDirectory, ApplicationName); } public string ApplicationName { get; } public string ApplicationPath { get; } + public string WorkingDirectory { get; } + + public string TestProjectDirectory { get; } + public bool PublishOnly { get; set; } protected abstract DeploymentParameters GetDeploymentParameters(); protected DeploymentParameters GetDeploymentParameters(RuntimeFlavor flavor, string targetFramework) - => GetDeploymentParameters(ApplicationPath, ApplicationName, flavor, targetFramework); + => GetDeploymentParameters(TestProjectDirectory, ApplicationName, flavor, targetFramework); - public static DeploymentParameters GetDeploymentParameters(string applicationPath, string applicationName, RuntimeFlavor flavor, string targetFramework) + private static DeploymentParameters GetDeploymentParameters(string applicationPath, string applicationName, RuntimeFlavor flavor, string targetFramework) { // This determines the configuration of the the test project and consequently the configuration the src projects are most likely built in. var projectConfiguration = @@ -54,15 +72,17 @@ namespace FunctionalTests { ApplicationName = applicationName, PublishApplicationBeforeDeployment = true, - Configuration = "Release", + Configuration = projectConfiguration, EnvironmentVariables = { new KeyValuePair(DotnetCLITelemetryOptOut, "1"), + new KeyValuePair("SolutionDirectory", SolutionDirectory), new KeyValuePair("SolutionConfiguration", projectConfiguration), }, PublishEnvironmentVariables = { new KeyValuePair(DotnetCLITelemetryOptOut, "1"), + new KeyValuePair("SolutionDirectory", SolutionDirectory), new KeyValuePair("SolutionConfiguration", projectConfiguration), }, TargetFramework = targetFramework, @@ -78,35 +98,89 @@ namespace FunctionalTests _deploymentTask.Result.HttpClient?.Dispose(); } + CleanupWorkingDirectory(); + _deployer?.Dispose(); } - public async Task CreateDeploymentAsync(ILoggerFactory loggerFactory) + public Task CreateDeploymentAsync(ILoggerFactory loggerFactory) { - try + if (_deploymentTask == null) { - await _deploymentLock.WaitAsync(TimeSpan.FromSeconds(10)); - if (_deploymentTask == null) - { - var deploymentParameters = GetDeploymentParameters(); - if (PublishOnly) - { - _deployer = new PublishOnlyDeployer(deploymentParameters, loggerFactory); - } - else - { - _deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory); - } + _deploymentTask = CreateDeploymentAsyncCore(loggerFactory); + } - _deploymentTask = _deployer.DeployAsync(); + return _deploymentTask; + } + + protected virtual Task CreateDeploymentAsyncCore(ILoggerFactory loggerFactory) + { + CopyDirectory(new DirectoryInfo(ApplicationPath), new DirectoryInfo(TestProjectDirectory)); + + File.Copy(Path.Combine(SolutionDirectory, "global.json"), Path.Combine(TestProjectDirectory, "global.json")); + File.Copy(Path.Combine(ApplicationPath, "..", "Directory.Build.props"), Path.Combine(TestProjectDirectory, "Directory.Build.props")); + File.Copy(Path.Combine(ApplicationPath, "..", "Directory.Build.targets"), Path.Combine(TestProjectDirectory, "Directory.Build.targets")); + + var deploymentParameters = GetDeploymentParameters(); + if (PublishOnly) + { + _deployer = new PublishOnlyDeployer(deploymentParameters, loggerFactory); + } + else + { + _deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory); + } + + return _deployer.DeployAsync(); + } + + public void CopyDirectory(DirectoryInfo source, DirectoryInfo destination, bool recursive = true) + { + // Recurse into subdirectories + foreach (var directory in source.EnumerateDirectories()) + { + if (directory.Name == "bin") + { + continue; + } + + var created = destination.CreateSubdirectory(directory.Name); + + // We only want to copy the restore artifacts from obj directory while ignoring in any configuration specific directories + CopyDirectory(directory, created, recursive: directory.Name != "obj"); + } + + foreach (var file in source.EnumerateFiles()) + { + file.CopyTo(Path.Combine(destination.FullName, file.Name)); + } + } + + private void CleanupWorkingDirectory() + { + var tries = 5; + var sleep = TimeSpan.FromSeconds(3); + + for (var i = 0; i < tries; i++) + { + try + { + if (Directory.Exists(WorkingDirectory)) + { + Directory.Delete(WorkingDirectory, recursive: true); + } + return; + } + catch when (i < tries - 1) + { + Console.WriteLine($"Failed to delete directory {TestProjectDirectory}, trying again."); + Thread.Sleep(sleep); + } + catch + { + // Do nothing } } - finally - { - _deploymentLock.Release(); - } - - return await _deploymentTask; } } } diff --git a/testapps/Directory.Build.props b/testapps/Directory.Build.props index 4c4c409bf9..2c0a965d5b 100644 --- a/testapps/Directory.Build.props +++ b/testapps/Directory.Build.props @@ -1,5 +1,9 @@ - + + $(MSBuildThisFileDirectory)..\ + + + netcoreapp2.2 diff --git a/testapps/Directory.Build.targets b/testapps/Directory.Build.targets index 350846ecee..03b1ec5b64 100644 --- a/testapps/Directory.Build.targets +++ b/testapps/Directory.Build.targets @@ -1,13 +1,13 @@ - + $(MvcRazorCompileOnPublish) $(Configuration) - <_MvcViewCompilationTasksPath>$(MSBuildThisFileDirectory)..\src\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.Tasks\bin\$(SolutionConfiguration)\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.Tasks.dll - <_MvcViewCompilationBinariesDir>$(MSBuildThisFileDirectory)..\src\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation\bin\$(SolutionConfiguration)\ + <_MvcViewCompilationTasksPath>$(SolutionDirectory)src\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.Tasks\bin\$(SolutionConfiguration)\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.Tasks.dll + <_MvcViewCompilationBinariesDir>$(SolutionDirectory)src\Microsoft.AspNetCore.Mvc.Razor.ViewCompilation\bin\$(SolutionConfiguration)\ -