From 4498058343d736750dfb5fb142ccbb8116380636 Mon Sep 17 00:00:00 2001 From: Hao Kung <HaoK@users.noreply.github.com> Date: Wed, 26 Feb 2020 12:55:41 -0800 Subject: [PATCH] [Helix] Shared framework support + Templates tests (#19177) --- .azure/pipelines/ci.yml | 17 ++++-- .azure/pipelines/quarantined-tests.yml | 5 +- eng/helix/content/InstallAppRuntime.ps1 | 54 +++++++++++++++++++ eng/helix/content/InstallNode.ps1 | 4 +- eng/helix/content/installappruntime.sh | 20 +++++++ eng/helix/content/runtests.cmd | 15 ++++++ eng/helix/content/runtests.sh | 15 ++++++ eng/targets/Helix.props | 2 + eng/targets/Helix.targets | 14 +++++ .../test/BlazorServerTemplateTest.cs | 6 ++- .../test/ByteOrderMarkTest.cs | 7 ++- .../test/EmptyWebTemplateTest.cs | 4 +- src/ProjectTemplates/test/GrpcTemplateTest.cs | 4 +- .../test/Helpers/ProcessEx.cs | 13 +++-- src/ProjectTemplates/test/Helpers/Project.cs | 27 +++++----- .../test/Helpers/ProjectFactoryFixture.cs | 6 ++- .../test/Helpers/TemplatePackageInstaller.cs | 26 ++++++--- .../test/IdentityUIPackageTest.cs | 4 +- src/ProjectTemplates/test/MvcTemplateTest.cs | 9 ++-- .../test/ProjectTemplates.Tests.csproj | 9 ++-- .../test/RazorClassLibraryTemplateTest.cs | 4 +- .../test/RazorPagesTemplateTest.cs | 9 ++-- .../SpaTemplateTest/AngularTemplateTest.cs | 9 ++-- .../SpaTemplateTest/ReactReduxTemplateTest.cs | 4 +- .../test/SpaTemplateTest/ReactTemplateTest.cs | 9 ++-- .../test/WebApiTemplateTest.cs | 4 +- .../test/WorkerTemplateTest.cs | 4 +- .../E2ETesting/SeleniumStandaloneServer.cs | 7 +++ 28 files changed, 248 insertions(+), 63 deletions(-) create mode 100644 eng/helix/content/InstallAppRuntime.ps1 create mode 100644 eng/helix/content/installappruntime.sh diff --git a/.azure/pipelines/ci.yml b/.azure/pipelines/ci.yml index 6f20958002f..82cb6cb5bce 100644 --- a/.azure/pipelines/ci.yml +++ b/.azure/pipelines/ci.yml @@ -154,8 +154,7 @@ stages: displayName: Build x64 # Build the x86 shared framework - # TODO: make it possible to build for one Windows architecture at a time - # This is going to actually build x86 native assets. See https://github.com/dotnet/aspnetcore/issues/7196 + # This is going to actually build x86 native assets. - script: ./build.cmd -ci -arch x86 @@ -631,7 +630,7 @@ stages: publishOnError: true includeForks: true -# Helix x64 + # Helix x64 - template: jobs/default-build.yml parameters: condition: eq(variables['Build.Reason'], 'PullRequest') @@ -640,9 +639,12 @@ stages: agentOs: Windows timeoutInMinutes: 180 steps: + # Build the shared framework + - script: ./build.cmd -ci -all -pack -arch x64 -buildNative /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log /bl:artifacts/log/helix.build.x64.binlog + displayName: Build shared fx - script: .\restore.cmd -ci displayName: Restore - - script: .\build.cmd -ci -NoRestore -test -projects eng\helix\helix.proj /p:IsRequiredCheck=true /p:IsHelixJob=true /p:BuildAllProjects=true /p:BuildNative=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log -bl + - script: .\build.cmd -ci -NoRestore -test -projects eng\helix\helix.proj /p:IsRequiredCheck=true /p:IsHelixJob=true /p:BuildAllProjects=true /p:BuildNative=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log -bl displayName: Run build.cmd helix target env: HelixApiAccessToken: $(HelixApiAccessToken) # Needed for internal queues @@ -661,9 +663,13 @@ stages: agentOs: Windows timeoutInMinutes: 180 steps: + # Build the shared framework + - script: ./build.cmd -ci -all -pack -arch x64 -buildNative /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log /bl:artifacts/log/helix.daily.build.x64.binlog + displayName: Build shared fx + # Build the x86 shared framework - script: .\restore.cmd -ci displayName: Restore - - script: .\build.cmd -ci -NoRestore -test -projects eng\helix\helix.proj /p:IsHelixJob=true /p:IsHelixDaily=true /p:BuildAllProjects=true /p:BuildNative=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log -bl + - script: .\build.cmd -ci -NoRestore -test -projects eng\helix\helix.proj /p:IsHelixJob=true /p:IsHelixDaily=true /p:BuildAllProjects=true /p:BuildNative=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log -bl displayName: Run build.cmd helix target env: HelixApiAccessToken: $(HelixApiAccessToken) # Needed for internal queues @@ -683,6 +689,7 @@ stages: agentOs: Linux timeoutInMinutes: 180 steps: + # Build the shared framework - script: ./restore.sh -ci displayName: Restore - script: ./build.sh -ci --arch arm64 -test --no-build-nodejs -projects $(Build.SourcesDirectory)/eng/helix/helix.proj /p:IsHelixJob=true /p:IsHelixDaily=true /p:BuildAllProjects=true /p:BuildNative=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log -bl diff --git a/.azure/pipelines/quarantined-tests.yml b/.azure/pipelines/quarantined-tests.yml index 6ac0143ed1e..bb9224b38b9 100644 --- a/.azure/pipelines/quarantined-tests.yml +++ b/.azure/pipelines/quarantined-tests.yml @@ -30,9 +30,12 @@ jobs: agentOs: Windows timeoutInMinutes: 240 steps: + # Build the shared framework + - script: ./build.cmd -ci -all -pack -arch x64 -buildNative /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log /bl:artifacts/log/helix.build.x64.binlog + displayName: Build shared fx - script: .\restore.cmd -ci displayName: Restore - - script: .\build.cmd -ci -NoRestore -test -projects eng\helix\helix.proj /p:RunQuarantinedTests=true /p:IsRequiredCheck=true /p:IsHelixJob=true /p:BuildAllProjects=true /p:BuildNative=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log -bl + - script: .\build.cmd -ci -NoRestore -test -projects eng\helix\helix.proj /p:RunQuarantinedTests=true /p:IsRequiredCheck=true /p:IsHelixJob=true /p:BuildAllProjects=true /p:BuildNative=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log -bl displayName: Run build.cmd helix target env: HelixApiAccessToken: $(HelixApiAccessToken) # Needed for internal queues diff --git a/eng/helix/content/InstallAppRuntime.ps1 b/eng/helix/content/InstallAppRuntime.ps1 new file mode 100644 index 00000000000..9d9aaffb5c8 --- /dev/null +++ b/eng/helix/content/InstallAppRuntime.ps1 @@ -0,0 +1,54 @@ + <# + .SYNOPSIS + Installs an AspNetCore shared framework on a machine + .DESCRIPTION + This script installs an AspNetCore shared framework on a machine + .PARAMETER AppRuntimePath + The path to the app runtime package to install. + .PARAMETER InstallDir + The directory to install the shared framework to. + .PARAMETER Framework + The framework directory to copy the shared framework from. + .PARAMETER RuntimeIdentifier + The runtime identifier for the shared framework. + #> +param( + [Parameter(Mandatory = $true)] + $AppRuntimePath, + + [Parameter(Mandatory = $true)] + $InstallDir, + + [Parameter(Mandatory = $true)] + $Framework, + + [Parameter(Mandatory = $true)] + $RuntimeIdentifier) + +$ErrorActionPreference = 'Stop' +$ProgressPreference = 'SilentlyContinue' # Workaround PowerShell/PowerShell#2138 + +Set-StrictMode -Version 1 + +Write-Host "Extracting to $InstallDir" + +$zipPackage = [io.path]::ChangeExtension($AppRuntimePath, ".zip") +Write-Host "Renaming to $zipPackage" +Rename-Item -Path $AppRuntimePath -NewName $zipPackage +if (Get-Command -Name 'Microsoft.PowerShell.Archive\Expand-Archive' -ErrorAction Ignore) { + # Use built-in commands where possible as they are cross-plat compatible + Microsoft.PowerShell.Archive\Expand-Archive -Path $zipPackage -DestinationPath ".\tmpRuntime" -Force +} +else { + Remove-Item ".\tmpRuntime" -Recurse -ErrorAction Ignore + # Fallback to old approach for old installations of PowerShell + Add-Type -AssemblyName System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::ExtractToDirectory($zipPackage, ".\tmpRuntime") +} + +Get-ChildItem -Path ".\tmpRuntime" -Recurse + +Write-Host "Copying managed files to $InstallDir" +Copy-Item -Path ".\tmpRuntime\runtimes\$RuntimeIdentifier\lib\$Framework\*" $InstallDir +Write-Host "Copying native files to $InstallDir" +Copy-Item -Path ".\tmpRuntime\runtimes\$RuntimeIdentifier\native\*" $InstallDir diff --git a/eng/helix/content/InstallNode.ps1 b/eng/helix/content/InstallNode.ps1 index 84425f271b6..3754eee5f55 100644 --- a/eng/helix/content/InstallNode.ps1 +++ b/eng/helix/content/InstallNode.ps1 @@ -29,9 +29,9 @@ if (Get-Command "node.exe" -ErrorAction SilentlyContinue) exit } -if (Test-Path "$output_dir\node.exe") +if (Test-Path "$InstallDir\node.exe") { - Write-Host "Node.exe found at $output_dir" + Write-Host "Node.exe found at $InstallDir" exit } diff --git a/eng/helix/content/installappruntime.sh b/eng/helix/content/installappruntime.sh new file mode 100644 index 00000000000..45cb1554fab --- /dev/null +++ b/eng/helix/content/installappruntime.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# Cause the script to fail if any subcommand fails +set -e + +appRuntimePath=$1 +output_dir=$2 +framework=$3 +rid=$4 +tmpDir=./tmpRuntime + +echo "Installing shared framework from $appRuntimePath" +cp $appRuntimePath sharedFx.zip + +mkdir -p $tmpDir +unzip sharedFx.zip -d $tmpDir +mkdir -p $output_dir +echo "Copying to $output_dir" +cp $tmpDir/runtimes/$rid/lib/$framework/* $output_dir +cp $tmpDir/runtimes/$rid/native/* $output_dir diff --git a/eng/helix/content/runtests.cmd b/eng/helix/content/runtests.cmd index 80f5a66bb3b..73cf658c18c 100644 --- a/eng/helix/content/runtests.cmd +++ b/eng/helix/content/runtests.cmd @@ -21,7 +21,22 @@ set PATH=%DOTNET_ROOT%;%PATH%;%HELIX_CORRELATION_PAYLOAD%\node\bin powershell.exe -NoProfile -ExecutionPolicy unrestricted -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -useb 'https://dot.net/v1/dotnet-install.ps1'))) -Architecture %$arch% -Version %$sdkVersion% -InstallDir %DOTNET_ROOT%" powershell.exe -NoProfile -ExecutionPolicy unrestricted -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -useb 'https://dot.net/v1/dotnet-install.ps1'))) -Architecture %$arch% -Runtime dotnet -Version %$runtimeVersion% -InstallDir %DOTNET_ROOT%" +if EXIST ".\Microsoft.AspNetCore.App" ( + echo "Found Microsoft.AspNetCore.App, copying to %DOTNET_ROOT%\shared\Microsoft.AspNetCore.App\%runtimeVersion%" + xcopy /i /y ".\Microsoft.AspNetCore.App" %DOTNET_ROOT%\shared\Microsoft.AspNetCore.App\%runtimeVersion%\ +) + +echo "Current Directory: %HELIX_WORKITEM_ROOT%" set HELIX=%$helixQueue% +set HELIX_DIR=%HELIX_WORKITEM_ROOT% +set NUGET_FALLBACK_PACKAGES=%HELIX_DIR% +set NUGET_RESTORE=%HELIX_DIR%\nugetRestore +echo "Setting HELIX_DIR: %HELIX_DIR%" +echo Creating nuget restore directory: %NUGET_RESTORE% +mkdir %NUGET_RESTORE% +mkdir logs + +dir %DOTNET_ROOT%\dotnet vstest %$target% -lt >discovered.txt find /c "Exception thrown" discovered.txt diff --git a/eng/helix/content/runtests.sh b/eng/helix/content/runtests.sh index 51b596afa07..c31297d587a 100644 --- a/eng/helix/content/runtests.sh +++ b/eng/helix/content/runtests.sh @@ -31,6 +31,14 @@ export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 # Used by SkipOnHelix attribute export helix="$helix_queue_name" +export HELIX_DIR="$DIR" +export NUGET_FALLBACK_PACKAGES="$DIR" +export NUGET_RESTORE="$DIR/nugetRestore" +echo "Creating nugetRestore directory: $NUGET_RESTORE" +mkdir $NUGET_RESTORE +mkdir logs + +ls -la RESET="\033[0m" RED="\033[0;31m" @@ -82,6 +90,13 @@ if [ $? -ne 0 ]; then done fi +# Copy over any local shared fx if found +if [ -d "Microsoft.AspNetCore.App" ] +then + echo "Found Microsoft.AspNetCore.App directory, copying to $DOTNET_ROOT/shared/Microsoft.AspNetCore.App/$dotnet_runtime_version." + cp -r Microsoft.AspNetCore.App $DOTNET_ROOT/shared/Microsoft.AspNetCore.App/$dotnet_runtime_version +fi + if [ -e /proc/self/coredump_filter ]; then # Include memory in private and shared file-backed mappings in the dump. # This ensures that we can see disassembly from our shared libraries when diff --git a/eng/targets/Helix.props b/eng/targets/Helix.props index d36c4a1a7aa..d4c7a99d524 100644 --- a/eng/targets/Helix.props +++ b/eng/targets/Helix.props @@ -21,6 +21,8 @@ <HelixUseArchive>false</HelixUseArchive> <LoggingTestingDisableFileLogging Condition="'$(IsHelixJob)' == 'true'">false</LoggingTestingDisableFileLogging> <NodeVersion>10.15.3</NodeVersion> + <AppRuntimeVersion>5.0.0-ci</AppRuntimeVersion> + <TestDependsOnAspNetRuntime>false</TestDependsOnAspNetRuntime> </PropertyGroup> <ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'"> diff --git a/eng/targets/Helix.targets b/eng/targets/Helix.targets index 722158b18f4..00849843534 100644 --- a/eng/targets/Helix.targets +++ b/eng/targets/Helix.targets @@ -16,6 +16,20 @@ <HelixPreCommand Include="call RunPowershell.cmd InstallNode.ps1 $(NodeVersion) %25HELIX_CORRELATION_PAYLOAD%25\node\bin || exit /b 1" /> </ItemGroup> + <ItemGroup Condition="'$(IsHelixJob)' == 'true' AND '$(IsWindowsHelixQueue)' == 'true' AND '$(TestDependsOnAspNetRuntime)' == 'true'"> + <HelixContent Include="$(RepoRoot)artifacts\packages\Release\Shipping\Microsoft.AspNetCore.App.Runtime.win-x64.$(AppRuntimeVersion).nupkg" /> + <HelixPreCommand Include="call RunPowershell.cmd InstallAppRuntime.ps1 Microsoft.AspNetCore.App.Runtime.win-x64.$(AppRuntimeVersion).nupkg Microsoft.AspNetCore.App netcoreapp5.0 win-x64 || exit /b 1" /> + </ItemGroup> + + <ItemGroup Condition="'$(IsHelixJob)' == 'true' AND '$(IsWindowsHelixQueue)' == 'false' AND '$(TestDependsOnAspNetRuntime)' == 'true'"> + <HelixContent Include="$(RepoRoot)artifacts\packages\Release\Shipping\Microsoft.AspNetCore.App.Runtime.win-x64.$(AppRuntimeVersion).nupkg" /> + <HelixPreCommand Include="./installappruntime.sh Microsoft.AspNetCore.App.Runtime.win-x64.$(AppRuntimeVersion).nupkg Microsoft.AspNetCore.App netcoreapp5.0 win-x64" /> + </ItemGroup> + + <ItemGroup Condition="'$(IsHelixJob)' == 'true' AND '$(TestDependsOnAspNetRuntime)' == 'true'"> + <HelixContent Include="$(RepoRoot)artifacts\packages\Release\Shipping\*-ci.nupkg" /> + </ItemGroup> + <!-- Item group has to be defined here becasue Helix.props is evaluated before xunit.runner.console.props --> <ItemGroup Condition="$(BuildHelixPayload)"> <Content Include="@(HelixContent)" /> diff --git a/src/ProjectTemplates/test/BlazorServerTemplateTest.cs b/src/ProjectTemplates/test/BlazorServerTemplateTest.cs index 1c6239d10ed..80201023862 100644 --- a/src/ProjectTemplates/test/BlazorServerTemplateTest.cs +++ b/src/ProjectTemplates/test/BlazorServerTemplateTest.cs @@ -24,7 +24,8 @@ namespace Templates.Test public Project Project { get; private set; } - [Fact] + [ConditionalFact] + [SkipOnHelix("selenium")] public async Task BlazorServerTemplateWorks_NoAuth() { Project = await ProjectFactory.GetOrCreateProject("blazorservernoauth", Output); @@ -79,9 +80,10 @@ namespace Templates.Test } } - [Theory] + [ConditionalTheory] [InlineData(true)] [InlineData(false)] + [SkipOnHelix("ef restore no worky")] public async Task BlazorServerTemplateWorks_IndividualAuth(bool useLocalDB) { Project = await ProjectFactory.GetOrCreateProject("blazorserverindividual" + (useLocalDB ? "uld" : ""), Output); diff --git a/src/ProjectTemplates/test/ByteOrderMarkTest.cs b/src/ProjectTemplates/test/ByteOrderMarkTest.cs index df7acd2f4dd..76600bf9e28 100644 --- a/src/ProjectTemplates/test/ByteOrderMarkTest.cs +++ b/src/ProjectTemplates/test/ByteOrderMarkTest.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; +using Microsoft.AspNetCore.Testing; using Xunit; using Xunit.Abstractions; @@ -19,7 +20,8 @@ namespace Templates.Test _output = output; } - [Theory] + [ConditionalTheory] + [SkipOnHelix("missing files")] [InlineData("Web.ProjectTemplates")] [InlineData("Web.Spa.ProjectTemplates")] public void JSAndJSONInAllTemplates_ShouldNotContainBOM(string projectName) @@ -60,7 +62,8 @@ namespace Templates.Test Assert.False(filesWithBOMCharactersPresent); } - [Fact] + [ConditionalFact] + [SkipOnHelix("missing files")] public void RazorFilesInWebProjects_ShouldContainBOM() { var projectName = "Web.ProjectTemplates"; diff --git a/src/ProjectTemplates/test/EmptyWebTemplateTest.cs b/src/ProjectTemplates/test/EmptyWebTemplateTest.cs index bcd52da1d59..a448f039a4d 100644 --- a/src/ProjectTemplates/test/EmptyWebTemplateTest.cs +++ b/src/ProjectTemplates/test/EmptyWebTemplateTest.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Templates.Test.Helpers; +using Microsoft.AspNetCore.Testing; using Xunit; using Xunit.Abstractions; @@ -22,7 +23,8 @@ namespace Templates.Test public ITestOutputHelper Output { get; } - [Fact] + [ConditionalFact] + [SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] public async Task EmptyWebTemplateCSharp() { await EmtpyTemplateCore(languageOverride: null); diff --git a/src/ProjectTemplates/test/GrpcTemplateTest.cs b/src/ProjectTemplates/test/GrpcTemplateTest.cs index 8d0eef03957..eda3fb44ef0 100644 --- a/src/ProjectTemplates/test/GrpcTemplateTest.cs +++ b/src/ProjectTemplates/test/GrpcTemplateTest.cs @@ -4,6 +4,7 @@ using System; using System.Runtime.InteropServices; using System.Threading.Tasks; +using Microsoft.AspNetCore.Testing; using Templates.Test.Helpers; using Xunit; using Xunit.Abstractions; @@ -23,7 +24,8 @@ namespace Templates.Test public ProjectFactoryFixture ProjectFactory { get; } public ITestOutputHelper Output { get; } - [Fact] + [ConditionalFact] + [SkipOnHelix("Not supported queues", Queues = "Windows.7.Amd64;Windows.7.Amd64.Open;OSX.1014.Amd64;OSX.1014.Amd64.Open")] public async Task GrpcTemplate() { Project = await ProjectFactory.GetOrCreateProject("grpc", Output); diff --git a/src/ProjectTemplates/test/Helpers/ProcessEx.cs b/src/ProjectTemplates/test/Helpers/ProcessEx.cs index f5bf857996d..db132bdafe0 100644 --- a/src/ProjectTemplates/test/Helpers/ProcessEx.cs +++ b/src/ProjectTemplates/test/Helpers/ProcessEx.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; @@ -99,6 +100,11 @@ namespace Templates.Test.Helpers } startInfo.EnvironmentVariables["NUGET_PACKAGES"] = NUGET_PACKAGES; + + if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("helix"))) + { + startInfo.EnvironmentVariables["NUGET_FALLBACK_PACKAGES"] = Environment.GetEnvironmentVariable("NUGET_FALLBACK_PACKAGES"); + } output.WriteLine($"==> {startInfo.FileName} {startInfo.Arguments} [{startInfo.WorkingDirectory}]"); var proc = Process.Start(startInfo); @@ -189,11 +195,12 @@ namespace Templates.Test.Helpers } } - private static string GetNugetPackagesRestorePath() => - typeof(ProcessEx).Assembly + private static string GetNugetPackagesRestorePath() => (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("NUGET_RESTORE"))) + ? typeof(ProcessEx).Assembly .GetCustomAttributes<AssemblyMetadataAttribute>() .First(attribute => attribute.Key == "TestPackageRestorePath") - .Value; + .Value + : Environment.GetEnvironmentVariable("NUGET_RESTORE"); public void Dispose() { diff --git a/src/ProjectTemplates/test/Helpers/Project.cs b/src/ProjectTemplates/test/Helpers/Project.cs index 33e50d20915..28a9bdd9170 100644 --- a/src/ProjectTemplates/test/Helpers/Project.cs +++ b/src/ProjectTemplates/test/Helpers/Project.cs @@ -24,7 +24,16 @@ namespace Templates.Test.Helpers public static bool IsCIEnvironment => typeof(Project).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>() .Any(a => a.Key == "ContinuousIntegrationBuild"); - public static string ArtifactsLogDir => GetAssemblyMetadata("ArtifactsLogDir"); + public static string ArtifactsLogDir => (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HELIX_DIR"))) + ? GetAssemblyMetadata("ArtifactsLogDir") + : Path.Combine(Environment.GetEnvironmentVariable("HELIX_DIR"), "logs"); + + // FIGURE OUT EF PATH + public static string DotNetEfFullPath => (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("helix"))) + ? typeof(ProjectFactoryFixture).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>() + .First(attribute => attribute.Key == "DotNetEfFullPath") + .Value + : Path.Combine("NuGetPackageRoot", "dotnet-ef/$(DotnetEfPackageVersion)/tools/netcoreapp3.1/any/dotnet-ef.dll"); public SemaphoreSlim DotNetNewLock { get; set; } public SemaphoreSlim NodeLock { get; set; } @@ -297,13 +306,7 @@ namespace Templates.Test.Helpers internal async Task<ProcessEx> RunDotNetEfCreateMigrationAsync(string migrationName) { - var assembly = typeof(ProjectFactoryFixture).Assembly; - - var dotNetEfFullPath = assembly.GetCustomAttributes<AssemblyMetadataAttribute>() - .First(attribute => attribute.Key == "DotNetEfFullPath") - .Value; - - var args = $"\"{dotNetEfFullPath}\" --verbose --no-build migrations add {migrationName}"; + var args = $"\"{DotNetEfFullPath}\" --verbose --no-build migrations add {migrationName}"; // Only run one instance of 'dotnet new' at once, as a workaround for // https://github.com/aspnet/templating/issues/63 @@ -322,13 +325,7 @@ namespace Templates.Test.Helpers internal async Task<ProcessEx> RunDotNetEfUpdateDatabaseAsync() { - var assembly = typeof(ProjectFactoryFixture).Assembly; - - var dotNetEfFullPath = assembly.GetCustomAttributes<AssemblyMetadataAttribute>() - .First(attribute => attribute.Key == "DotNetEfFullPath") - .Value; - - var args = $"\"{dotNetEfFullPath}\" --verbose --no-build database update"; + var args = $"\"{DotNetEfFullPath}\" --verbose --no-build database update"; // Only run one instance of 'dotnet new' at once, as a workaround for // https://github.com/aspnet/templating/issues/63 diff --git a/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs b/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs index ffd1b0ae4ff..9399433be96 100644 --- a/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs +++ b/src/ProjectTemplates/test/Helpers/ProjectFactoryFixture.cs @@ -61,9 +61,11 @@ namespace Templates.Test.Helpers } private static string GetTemplateFolderBasePath(Assembly assembly) => - assembly.GetCustomAttributes<AssemblyMetadataAttribute>() + (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HELIX_DIR"))) + ? assembly.GetCustomAttributes<AssemblyMetadataAttribute>() .Single(a => a.Key == "TestTemplateCreationFolder") - .Value; + .Value + : Path.Combine(Environment.GetEnvironmentVariable("HELIX_DIR"), "Templates", "BaseFolder"); public void Dispose() { diff --git a/src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs b/src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs index 07db888279a..3eed004ef60 100644 --- a/src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs +++ b/src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs @@ -42,10 +42,12 @@ namespace Templates.Test.Helpers "Microsoft.AspNetCore.Blazor.Templates", }; - public static string CustomHivePath { get; } = typeof(TemplatePackageInstaller) - .Assembly.GetCustomAttributes<AssemblyMetadataAttribute>() - .Single(s => s.Key == "CustomTemplateHivePath").Value; - + public static string CustomHivePath { get; } = (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("helix"))) + ? typeof(TemplatePackageInstaller) + .Assembly.GetCustomAttributes<AssemblyMetadataAttribute>() + .Single(s => s.Key == "CustomTemplateHivePath").Value + : Path.Combine("Hives", ".templateEngine"); + public static async Task EnsureTemplatingEngineInitializedAsync(ITestOutputHelper output) { await InstallerLock.WaitAsync(); @@ -81,11 +83,19 @@ namespace Templates.Test.Helpers private static async Task InstallTemplatePackages(ITestOutputHelper output) { - var builtPackages = Directory.EnumerateFiles( - typeof(TemplatePackageInstaller).Assembly + string packagesDir; + if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("helix"))) + { + packagesDir = "."; + } + else + { + packagesDir = typeof(TemplatePackageInstaller).Assembly .GetCustomAttributes<AssemblyMetadataAttribute>() - .Single(a => a.Key == "ArtifactsShippingPackagesDir").Value, - "*.nupkg") + .Single(a => a.Key == "ArtifactsShippingPackagesDir").Value; + } + + var builtPackages = Directory.EnumerateFiles(packagesDir, "*Templates*.nupkg") .Where(p => _templatePackages.Any(t => Path.GetFileName(p).StartsWith(t, StringComparison.OrdinalIgnoreCase))) .ToArray(); diff --git a/src/ProjectTemplates/test/IdentityUIPackageTest.cs b/src/ProjectTemplates/test/IdentityUIPackageTest.cs index deede64521a..fe794a3629b 100644 --- a/src/ProjectTemplates/test/IdentityUIPackageTest.cs +++ b/src/ProjectTemplates/test/IdentityUIPackageTest.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Net; using System.Threading.Tasks; +using Microsoft.AspNetCore.Testing; using Templates.Test.Helpers; using Xunit; using Xunit.Abstractions; @@ -117,8 +118,9 @@ namespace Templates.Test "Identity/lib/jquery-validation-unobtrusive/LICENSE.txt", }; - [Theory] + [ConditionalTheory] [MemberData(nameof(MSBuildIdentityUIPackageOptions))] + [SkipOnHelix("ef restore no worky")] public async Task IdentityUIPackage_WorksWithDifferentOptions(IDictionary<string, string> packageOptions, string versionValidator, string[] expectedFiles) { Project = await ProjectFactory.GetOrCreateProject("identityuipackage" + string.Concat(packageOptions.Values), Output); diff --git a/src/ProjectTemplates/test/MvcTemplateTest.cs b/src/ProjectTemplates/test/MvcTemplateTest.cs index 976eef53463..271aed575b2 100644 --- a/src/ProjectTemplates/test/MvcTemplateTest.cs +++ b/src/ProjectTemplates/test/MvcTemplateTest.cs @@ -28,7 +28,8 @@ namespace Templates.Test [Fact] public async Task MvcTemplate_NoAuthFSharp() => await MvcTemplateCore(languageOverride: "F#"); - [Fact] + [ConditionalFact] + [SkipOnHelix("cert failure", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] public async Task MvcTemplate_NoAuthCSharp() => await MvcTemplateCore(languageOverride: null); private async Task MvcTemplateCore(string languageOverride) @@ -103,9 +104,10 @@ namespace Templates.Test } } - [Theory] + [ConditionalTheory] [InlineData(true)] [InlineData(false)] + [SkipOnHelix("ef restore no worky")] public async Task MvcTemplate_IndividualAuth(bool useLocalDB) { Project = await ProjectFactory.GetOrCreateProject("mvcindividual" + (useLocalDB ? "uld" : ""), Output); @@ -220,7 +222,8 @@ namespace Templates.Test } } - [Fact] + [ConditionalFact] + [SkipOnHelix("razor compilation restore no worky")] public async Task MvcTemplate_RazorRuntimeCompilation_BuildsAndPublishes() { Project = await ProjectFactory.GetOrCreateProject("mvc_rc", Output); diff --git a/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj b/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj index c2774689163..8f1984b78a8 100644 --- a/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj +++ b/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj @@ -10,10 +10,9 @@ <RunTemplateTests Condition="'$(RunTemplateTests)' == ''" >true</RunTemplateTests> <SkipTests Condition="'$(RunTemplateTests)' != 'true'">true</SkipTests> - - <!-- Tests do not work on Helix or when bin/ directory is not in project directory due to undeclared dependency on test content. --> - <!-- https://github.com/dotnet/aspnetcore/issues/6857 --> - <BuildHelixPayload>false</BuildHelixPayload> + <SkipHelixArm>true</SkipHelixArm> + + <!-- Some tests still do not work on Helix, so continue running these on azdo for now--> <SkipTests Condition="'$(RunTemplateTests)' == 'true'">false</SkipTests> <BaseOutputPath /> <OutputPath /> @@ -24,12 +23,14 @@ <TestPackageRestorePath>$([MSBuild]::EnsureTrailingSlash('$(RepoRoot)'))obj\template-restore\</TestPackageRestorePath> <TestTemplateTestsProps>TemplateTests.props</TestTemplateTestsProps> <GenerateLoggingTestingAssemblyAttributes>false</GenerateLoggingTestingAssemblyAttributes> + <TestDependsOnAspNetRuntime>true</TestDependsOnAspNetRuntime> </PropertyGroup> <ItemGroup> <EmbeddedResource Include="template-baselines.json" /> <Compile Include="$(SharedSourceRoot)Process\*.cs" LinkBase="shared\Process" /> <Compile Include="$(SharedSourceRoot)CertificateGeneration\**\*.cs" LinkBase="shared\CertificateGeneration" /> + <Compile Include="$(SharedSourceRoot)test\SkipOnHelixAttribute.cs" /> </ItemGroup> <ItemGroup> diff --git a/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs b/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs index 0d02a56f8f8..f8d6bd65b59 100644 --- a/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs +++ b/src/ProjectTemplates/test/RazorClassLibraryTemplateTest.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Templates.Test.Helpers; using Xunit; using Xunit.Abstractions; +using Microsoft.AspNetCore.Testing; namespace Templates.Test { @@ -40,7 +41,8 @@ namespace Templates.Test Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult)); } - [Fact] + [ConditionalFact] + [SkipOnHelix("restore no worky")] public async Task RazorClassLibraryTemplateAsync() { Project = await ProjectFactory.GetOrCreateProject("razorclasslib", Output); diff --git a/src/ProjectTemplates/test/RazorPagesTemplateTest.cs b/src/ProjectTemplates/test/RazorPagesTemplateTest.cs index 818a5745364..73e4a5da527 100644 --- a/src/ProjectTemplates/test/RazorPagesTemplateTest.cs +++ b/src/ProjectTemplates/test/RazorPagesTemplateTest.cs @@ -25,7 +25,8 @@ namespace Templates.Test public ITestOutputHelper Output { get; } - [Fact] + [ConditionalFact] + [SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] public async Task RazorPagesTemplate_NoAuth() { Project = await ProjectFactory.GetOrCreateProject("razorpagesnoauth", Output); @@ -93,9 +94,10 @@ namespace Templates.Test } } - [Theory] + [ConditionalTheory] [InlineData(false)] [InlineData(true)] + [SkipOnHelix("ef restore no worky")] public async Task RazorPagesTemplate_IndividualAuth(bool useLocalDB) { Project = await ProjectFactory.GetOrCreateProject("razorpagesindividual" + (useLocalDB ? "uld" : ""), Output); @@ -210,7 +212,8 @@ namespace Templates.Test } } - [Fact] + [ConditionalFact] + [SkipOnHelix("runtime compliation restore no worky")] public async Task RazorPagesTemplate_RazorRuntimeCompilation_BuildsAndPublishes() { Project = await ProjectFactory.GetOrCreateProject("razorpages_rc", Output); diff --git a/src/ProjectTemplates/test/SpaTemplateTest/AngularTemplateTest.cs b/src/ProjectTemplates/test/SpaTemplateTest/AngularTemplateTest.cs index e1d5db13388..fc787751892 100644 --- a/src/ProjectTemplates/test/SpaTemplateTest/AngularTemplateTest.cs +++ b/src/ProjectTemplates/test/SpaTemplateTest/AngularTemplateTest.cs @@ -15,15 +15,18 @@ namespace Templates.Test.SpaTemplateTest public AngularTemplateTest(ProjectFactoryFixture projectFactory, BrowserFixture browserFixture, ITestOutputHelper output) : base(projectFactory, browserFixture, output) { } - [Fact] + [ConditionalFact] + [SkipOnHelix("selenium")] public Task AngularTemplate_Works() => SpaTemplateImplAsync("angularnoauth", "angular", useLocalDb: false, usesAuth: false); - [Fact] + [ConditionalFact] + [SkipOnHelix("selenium")] public Task AngularTemplate_IndividualAuth_Works() => SpaTemplateImplAsync("angularindividual", "angular", useLocalDb: false, usesAuth: true); - [Fact] + [ConditionalFact] + [SkipOnHelix("selenium")] public Task AngularTemplate_IndividualAuth_Works_LocalDb() => SpaTemplateImplAsync("angularindividualuld", "angular", useLocalDb: true, usesAuth: true); } diff --git a/src/ProjectTemplates/test/SpaTemplateTest/ReactReduxTemplateTest.cs b/src/ProjectTemplates/test/SpaTemplateTest/ReactReduxTemplateTest.cs index 44d6b67f325..3e32514cc1e 100644 --- a/src/ProjectTemplates/test/SpaTemplateTest/ReactReduxTemplateTest.cs +++ b/src/ProjectTemplates/test/SpaTemplateTest/ReactReduxTemplateTest.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.E2ETesting; +using Microsoft.AspNetCore.Testing; using Templates.Test.Helpers; using Xunit; using Xunit.Abstractions; @@ -16,7 +17,8 @@ namespace Templates.Test.SpaTemplateTest { } - [Fact] + [ConditionalFact] + [SkipOnHelix("selenium")] public Task ReactReduxTemplate_Works_NetCore() => SpaTemplateImplAsync("reactredux", "reactredux", useLocalDb: false, usesAuth: false); } diff --git a/src/ProjectTemplates/test/SpaTemplateTest/ReactTemplateTest.cs b/src/ProjectTemplates/test/SpaTemplateTest/ReactTemplateTest.cs index 469e87acd56..a2e1c1c3685 100644 --- a/src/ProjectTemplates/test/SpaTemplateTest/ReactTemplateTest.cs +++ b/src/ProjectTemplates/test/SpaTemplateTest/ReactTemplateTest.cs @@ -17,15 +17,18 @@ namespace Templates.Test.SpaTemplateTest { } - [Fact] + [ConditionalFact] + [SkipOnHelix("selenium")] public Task ReactTemplate_Works_NetCore() => SpaTemplateImplAsync("reactnoauth", "react", useLocalDb: false, usesAuth: false); - [Fact] + [ConditionalFact] + [SkipOnHelix("selenium")] public Task ReactTemplate_IndividualAuth_NetCore() => SpaTemplateImplAsync("reactindividual", "react", useLocalDb: false, usesAuth: true); - [Fact] + [ConditionalFact] + [SkipOnHelix("selenium")] public Task ReactTemplate_IndividualAuth_NetCore_LocalDb() => SpaTemplateImplAsync("reactindividualuld", "react", useLocalDb: true, usesAuth: true); } diff --git a/src/ProjectTemplates/test/WebApiTemplateTest.cs b/src/ProjectTemplates/test/WebApiTemplateTest.cs index 375f2924726..2f9a5ce1624 100644 --- a/src/ProjectTemplates/test/WebApiTemplateTest.cs +++ b/src/ProjectTemplates/test/WebApiTemplateTest.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Templates.Test.Helpers; +using Microsoft.AspNetCore.Testing; using Xunit; using Xunit.Abstractions; @@ -25,7 +26,8 @@ namespace Templates.Test [Fact] public async Task WebApiTemplateFSharp() => await WebApiTemplateCore(languageOverride: "F#"); - [Fact] + [ConditionalFact] + [SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] public async Task WebApiTemplateCSharp() => await WebApiTemplateCore(languageOverride: null); private async Task WebApiTemplateCore(string languageOverride) diff --git a/src/ProjectTemplates/test/WorkerTemplateTest.cs b/src/ProjectTemplates/test/WorkerTemplateTest.cs index 738eafc61d6..0299f17a118 100644 --- a/src/ProjectTemplates/test/WorkerTemplateTest.cs +++ b/src/ProjectTemplates/test/WorkerTemplateTest.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Templates.Test.Helpers; using Xunit; using Xunit.Abstractions; +using Microsoft.AspNetCore.Testing; namespace Templates.Test { @@ -20,7 +21,8 @@ namespace Templates.Test public ProjectFactoryFixture ProjectFactory { get; } public ITestOutputHelper Output { get; } - [Fact] + [ConditionalFact] + [SkipOnHelix("restore no worky")] public async Task WorkerTemplateAsync() { Project = await ProjectFactory.GetOrCreateProject("worker", Output); diff --git a/src/Shared/E2ETesting/SeleniumStandaloneServer.cs b/src/Shared/E2ETesting/SeleniumStandaloneServer.cs index 8ca56542437..fd0878aec2f 100644 --- a/src/Shared/E2ETesting/SeleniumStandaloneServer.cs +++ b/src/Shared/E2ETesting/SeleniumStandaloneServer.cs @@ -113,6 +113,13 @@ namespace Microsoft.AspNetCore.E2ETesting // It's important that we get the folder value before we start the process to prevent // untracked processes when the tracking folder is not correctly configure. var trackingFolder = GetProcessTrackingFolder(); + if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("helix"))) + { + // Just create a random tracking folder on helix + trackingFolder = Path.Combine(Directory.GetCurrentDirectory(), Path.GetRandomFileName()); + Directory.CreateDirectory(trackingFolder); + } + if (!Directory.Exists(trackingFolder)) { throw new InvalidOperationException($"Invalid tracking folder. Set the 'SeleniumProcessTrackingFolder' MSBuild property to a valid folder."); -- GitLab