diff --git a/azure-pipelines-integration-corehost.yml b/azure-pipelines-integration-corehost.yml index cc58a29576b70..62648c365e7b9 100644 --- a/azure-pipelines-integration-corehost.yml +++ b/azure-pipelines-integration-corehost.yml @@ -70,34 +70,28 @@ parameters: type: number default: 150 -jobs: -- job: VS_Integration_CoreHost_Debug - pool: - name: ${{ parameters.poolName }} - demands: ImageOverride -equals ${{ parameters.queueName }} - timeoutInMinutes: ${{ parameters.timeout }} - variables: - - name: XUNIT_LOGS - value: $(Build.SourcesDirectory)\artifacts\log\Debug - steps: - - template: eng/pipelines/test-integration-job.yml - parameters: - configuration: Debug - oop64bit: true +stages: +- template: eng/pipelines/test-integration-helix.yml + parameters: + poolName: ${{ parameters.poolName }} + queueName: ${{ parameters.queueName }} + timeout: ${{ parameters.timeout }} + configuration: Debug + testRuns: + - oop64bit: true oopCoreClr: true + lspEditor: false + runName: VS_Integration_CoreHost_Debug - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: - - job: VS_Integration_CoreHost_Release - pool: - name: ${{ parameters.poolName }} - demands: ImageOverride -equals ${{ parameters.queueName }} - timeoutInMinutes: ${{ parameters.timeout }} - variables: - - name: XUNIT_LOGS - value: $(Build.SourcesDirectory)\artifacts\log\Debug - steps: - - template: eng/pipelines/test-integration-job.yml - parameters: - configuration: Release - oop64bit: true + - template: eng/pipelines/test-integration-helix.yml + parameters: + poolName: ${{ parameters.poolName }} + queueName: ${{ parameters.queueName }} + timeout: ${{ parameters.timeout }} + configuration: Release + testRuns: + - oop64bit: true oopCoreClr: true + lspEditor: false + runName: VS_Integration_CoreHost_Release diff --git a/azure-pipelines-integration-lsp.yml b/azure-pipelines-integration-lsp.yml index 6ecb40c388caa..25063253d0e0a 100644 --- a/azure-pipelines-integration-lsp.yml +++ b/azure-pipelines-integration-lsp.yml @@ -56,20 +56,15 @@ parameters: type: number default: 150 -variables: -- name: XUNIT_LOGS - value: $(Build.SourcesDirectory)\artifacts\log\$(_configuration) - -jobs: -- job: VS_Integration_LSP - pool: - name: ${{ parameters.poolName }} - demands: ImageOverride -equals ${{ parameters.queueName }} - timeoutInMinutes: ${{ parameters.timeout }} - - steps: - - template: eng/pipelines/test-integration-job.yml - parameters: - configuration: Debug - oop64bit: true +stages: +- template: eng/pipelines/test-integration-helix.yml + parameters: + poolName: ${{ parameters.poolName }} + queueName: ${{ parameters.queueName }} + timeout: ${{ parameters.timeout }} + configuration: Debug + testRuns: + - oop64bit: true + oopCoreClr: false lspEditor: true + runName: VS_Integration_LSP_Debug_64 diff --git a/azure-pipelines-integration-scouting.yml b/azure-pipelines-integration-scouting.yml index f66374105aea5..72b4d1cf71bb8 100644 --- a/azure-pipelines-integration-scouting.yml +++ b/azure-pipelines-integration-scouting.yml @@ -34,62 +34,34 @@ parameters: default: 150 stages: -- stage: Debug_Integration - dependsOn: [] - variables: - - name: XUNIT_LOGS - value: $(Build.SourcesDirectory)\artifacts\log\Debug - jobs: - - job: VS_Integration_Debug_32 - pool: - name: ${{ parameters.poolName }} - demands: ImageOverride -equals ${{ parameters.queueName }} - timeoutInMinutes: ${{ parameters.timeout }} - steps: - - template: eng/pipelines/test-integration-job.yml - parameters: - configuration: Debug - oop64bit: false - lspEditor: false +- template: eng/pipelines/test-integration-helix.yml + parameters: + poolName: ${{ parameters.poolName }} + queueName: ${{ parameters.queueName }} + timeout: ${{ parameters.timeout }} + configuration: Debug + testRuns: + - oop64bit: false + oopCoreClr: false + lspEditor: false + runName: VS_Integration_Debug_32 + - oop64bit: true + oopCoreClr: false + lspEditor: false + runName: VS_Integration_Debug_64 - - job: VS_Integration_Debug_64 - pool: - name: ${{ parameters.poolName }} - demands: ImageOverride -equals ${{ parameters.queueName }} - timeoutInMinutes: ${{ parameters.timeout }} - steps: - - template: eng/pipelines/test-integration-job.yml - parameters: - configuration: Debug - oop64bit: true - lspEditor: false - -- stage: Release_Integration - dependsOn: [] - variables: - - name: XUNIT_LOGS - value: $(Build.SourcesDirectory)\artifacts\log\Release - jobs: - - job: VS_Integration_Release_32 - pool: - name: ${{ parameters.poolName }} - demands: ImageOverride -equals ${{ parameters.queueName }} - timeoutInMinutes: ${{ parameters.timeout }} - steps: - - template: eng/pipelines/test-integration-job.yml - parameters: - configuration: Release - oop64bit: false - lspEditor: false - - - job: VS_Integration_Release_64 - pool: - name: ${{ parameters.poolName }} - demands: ImageOverride -equals ${{ parameters.queueName }} - timeoutInMinutes: ${{ parameters.timeout }} - steps: - - template: eng/pipelines/test-integration-job.yml - parameters: - configuration: Release - oop64bit: true - lspEditor: false +- template: eng/pipelines/test-integration-helix.yml + parameters: + poolName: ${{ parameters.poolName }} + queueName: ${{ parameters.queueName }} + timeout: ${{ parameters.timeout }} + configuration: Release + testRuns: + - oop64bit: false + oopCoreClr: false + lspEditor: false + runName: VS_Integration_Release_32 + - oop64bit: true + oopCoreClr: false + lspEditor: false + runName: VS_Integration_Release_64 diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml index cb1824f0e22d5..a7d5aaefe8eea 100644 --- a/azure-pipelines-integration.yml +++ b/azure-pipelines-integration.yml @@ -68,64 +68,36 @@ parameters: default: 150 stages: -- stage: Debug_Integration - dependsOn: [] - variables: - - name: XUNIT_LOGS - value: $(Build.SourcesDirectory)\artifacts\log\Debug - jobs: - - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: - - job: VS_Integration_Debug_32 - pool: - name: ${{ parameters.poolName }} - demands: ImageOverride -equals ${{ parameters.queueName }} - timeoutInMinutes: ${{ parameters.timeout }} - steps: - - template: eng/pipelines/test-integration-job.yml - parameters: - configuration: Debug - oop64bit: false - lspEditor: false - - - job: VS_Integration_Debug_64 - pool: - name: ${{ parameters.poolName }} - demands: ImageOverride -equals ${{ parameters.queueName }} - timeoutInMinutes: ${{ parameters.timeout }} - steps: - - template: eng/pipelines/test-integration-job.yml - parameters: - configuration: Debug - oop64bit: true +- template: eng/pipelines/test-integration-helix.yml + parameters: + poolName: ${{ parameters.poolName }} + queueName: ${{ parameters.queueName }} + timeout: ${{ parameters.timeout }} + configuration: Debug + testRuns: + - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: + - oop64bit: false + oopCoreClr: false lspEditor: false + runName: VS_Integration_Debug_32 + - oop64bit: true + oopCoreClr: false + lspEditor: false + runName: VS_Integration_Debug_64 -- stage: Release_Integration - dependsOn: [] - variables: - - name: XUNIT_LOGS - value: $(Build.SourcesDirectory)\artifacts\log\Release - jobs: - - job: VS_Integration_Release_32 - pool: - name: ${{ parameters.poolName }} - demands: ImageOverride -equals ${{ parameters.queueName }} - timeoutInMinutes: ${{ parameters.timeout }} - steps: - - template: eng/pipelines/test-integration-job.yml - parameters: - configuration: Release - oop64bit: false +- template: eng/pipelines/test-integration-helix.yml + parameters: + poolName: ${{ parameters.poolName }} + queueName: ${{ parameters.queueName }} + timeout: ${{ parameters.timeout }} + configuration: Release + testRuns: + - oop64bit: false + oopCoreClr: false + lspEditor: false + runName: VS_Integration_Release_32 + - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: + - oop64bit: true + oopCoreClr: false lspEditor: false - - - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: - - job: VS_Integration_Release_64 - pool: - name: ${{ parameters.poolName }} - demands: ImageOverride -equals ${{ parameters.queueName }} - timeoutInMinutes: ${{ parameters.timeout }} - steps: - - template: eng/pipelines/test-integration-job.yml - parameters: - configuration: Release - oop64bit: true - lspEditor: false + runName: VS_Integration_Release_64 diff --git a/eng/build.ps1 b/eng/build.ps1 index 5c4014a4096e4..f6ac496ee7ceb 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -539,8 +539,13 @@ function EnablePreviewSdks() { # Deploy our core VSIX libraries to Visual Studio via the Roslyn VSIX tool. This is an alternative to # deploying at build time. function Deploy-VsixViaTool() { - $vsixDir = Get-PackageDir "RoslynTools.VSIXExpInstaller" - $vsixExe = Join-Path $vsixDir "tools\VsixExpInstaller.exe" + + $vsixExe = Join-Path $ArtifactsDir "bin\RunTests\$configuration\net7.0\VSIXExpInstaller\VSIXExpInstaller.exe" + Write-Host "VSIX EXE path: " $vsixExe + if (-not (Test-Path $vsixExe)) { + Write-Host "VSIX EXE not found: '$vsixExe'." -ForegroundColor Red + ExitWithExitCode 1 + } $vsInfo = LocateVisualStudio if ($vsInfo -eq $null) { diff --git a/eng/pipelines/test-integration-helix.yml b/eng/pipelines/test-integration-helix.yml new file mode 100644 index 0000000000000..c7b8a27aed816 --- /dev/null +++ b/eng/pipelines/test-integration-helix.yml @@ -0,0 +1,118 @@ +parameters: + - name: poolName + type: string + - name: queueName + type: string + - name: configuration + type: string + default: 'Debug' + values: [ 'Debug', 'Release' ] + - name: timeout + type: number + - name: testRuns + type: object + default: + - oop64bit: true + oopCoreClr: false + lspEditor: false + runName: 64 + + +stages: +- stage: Windows_${{ parameters.configuration }}_Build + dependsOn: [] + jobs: + - template: build-windows-job.yml + parameters: + jobName: Build_Windows_${{ parameters.configuration }} + testArtifactName: Transport_Artifacts_Windows_${{ parameters.configuration }} + configuration: ${{ parameters.configuration }} + poolName: ${{ parameters.poolName }} + queueName: ${{ parameters.queueName }} + restoreArguments: -msbuildEngine vs + buildArguments: -msbuildEngine vs + +- stage: ${{ parameters.configuration }}_Integration + dependsOn: Windows_${{ parameters.configuration }}_Build + variables: + - name: XUNIT_LOGS + value: $(Build.SourcesDirectory)\artifacts\log\${{ parameters.configuration }} + jobs: + - ${{ each testParameters in parameters.testRuns }}: + - job: ${{ testParameters.runName }} + timeoutInMinutes: ${{ parameters.timeout }} + pool: + name: ${{ parameters.poolName }} + demands: ImageOverride -equals ${{ parameters.queueName }} + steps: + - task: DownloadPipelineArtifact@2 + displayName: Download Test Payload + inputs: + artifact: Transport_Artifacts_Windows_${{ parameters.configuration }} + path: '$(Build.SourcesDirectory)' + + - task: BatchScript@1 + displayName: Rehydrate RunTests + inputs: + filename: ./artifacts/bin/RunTests/${{ parameters.configuration }}/net7.0/rehydrate.cmd + env: + HELIX_CORRELATION_PAYLOAD: '$(Build.SourcesDirectory)\.duplicate' + + # This is a temporary step until the actual test run moves to helix (then we would need to rehydrate the tests there instead) + - task: BatchScript@1 + displayName: Rehydrate Microsoft.VisualStudio.LanguageServices.New.IntegrationTests + inputs: + filename: ./artifacts/bin/Microsoft.VisualStudio.LanguageServices.New.IntegrationTests/${{ parameters.configuration }}/net472/rehydrate.cmd + env: + HELIX_CORRELATION_PAYLOAD: '$(Build.SourcesDirectory)\.duplicate' + + # This is a temporary step until the actual test run moves to helix (then we would need to rehydrate the tests there instead) + - task: BatchScript@1 + displayName: Rehydrate Microsoft.CodeAnalysis.Workspaces.MSBuild.UnitTests (net6.0-windows) + inputs: + filename: ./artifacts\bin\Microsoft.CodeAnalysis.Workspaces.MSBuild.UnitTests/${{ parameters.configuration }}/net6.0-windows/rehydrate.cmd + env: + HELIX_CORRELATION_PAYLOAD: '$(Build.SourcesDirectory)\.duplicate' + + # This is a temporary step until the actual test run moves to helix (then we would need to rehydrate the tests there instead) + - task: BatchScript@1 + displayName: Rehydrate Microsoft.CodeAnalysis.Workspaces.MSBuild.UnitTests (net472) + inputs: + filename: ./artifacts\bin\Microsoft.CodeAnalysis.Workspaces.MSBuild.UnitTests/${{ parameters.configuration }}/net472/rehydrate.cmd + env: + HELIX_CORRELATION_PAYLOAD: '$(Build.SourcesDirectory)\.duplicate' + + - task: PowerShell@2 + displayName: Run Integration Tests + inputs: + filePath: eng/build.ps1 + arguments: -ci -prepareMachine -testVsi -configuration ${{ parameters.configuration }} -oop64bit:$${{ testParameters.oop64bit }} -oopCoreClr:$${{ testParameters.oopCoreClr }} -collectDumps -lspEditor:$${{ testParameters.lspEditor }} + + # These are temporary publishing steps - once the tests run on helix, the artifacts will be attached to the helix payload. + - task: PublishTestResults@2 + displayName: Publish xUnit Test Results + inputs: + testRunner: XUnit + testResultsFiles: $(Build.SourcesDirectory)\artifacts\TestResults\${{ parameters.configuration }}\*.xml + mergeTestResults: true + testRunTitle: '$(System.JobAttempt)-Integration ${{ parameters.configuration }} OOP64_${{ testParameters.oop64bit }} OOPCoreClr_${{ testParameters.oopCoreClr }}' + condition: always() + + # Dumps from test timeouts or crashes get published to the test results directory by dotnet test, so make sure to publish any here. + - task: PublishBuildArtifacts@1 + displayName: Publish Test Results Directory + inputs: + PathtoPublish: '$(Build.SourcesDirectory)\artifacts\TestResults\${{ parameters.configuration }}' + ArtifactName: '$(System.JobAttempt)-Logs ${{ parameters.configuration }} OOP64_${{ testParameters.oop64bit }} OOPCoreClr_${{ testParameters.oopCoreClr }} LspEditor_${{ testParameters.lspEditor }} $(Build.BuildNumber)' + publishLocation: Container + continueOnError: true + condition: not(succeeded()) + + - task: PublishBuildArtifacts@1 + displayName: Publish Logs + inputs: + PathtoPublish: '$(Build.SourcesDirectory)\artifacts\log\${{ parameters.configuration }}' + ArtifactName: '$(System.JobAttempt)-Logs ${{ parameters.configuration }} OOP64_${{ testParameters.oop64bit }} OOPCoreClr_${{ testParameters.oopCoreClr }} LspEditor_${{ testParameters.lspEditor }} $(Build.BuildNumber)' + publishLocation: Container + continueOnError: true + condition: not(succeeded()) diff --git a/src/Tools/PrepareTests/MinimizeUtil.cs b/src/Tools/PrepareTests/MinimizeUtil.cs index 19295e8f2d485..1f1d866af7586 100644 --- a/src/Tools/PrepareTests/MinimizeUtil.cs +++ b/src/Tools/PrepareTests/MinimizeUtil.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.Contracts; using System.IO; using System.Linq; using System.Reflection.Metadata; @@ -53,10 +54,17 @@ internal static void Run(string sourceDirectory, string destinationDirectory, bo Dictionary> initialWalk() { IEnumerable directories = new[] { - Path.Combine(sourceDirectory, "eng") + Path.Combine(sourceDirectory, "eng"), }; + + if (!isUnix) + { + directories = directories.Concat([Path.Combine(sourceDirectory, "artifacts", "VSSetup")]); + } + var artifactsDir = Path.Combine(sourceDirectory, "artifacts/bin"); directories = directories.Concat(Directory.EnumerateDirectories(artifactsDir, "*.UnitTests")); + directories = directories.Concat(Directory.EnumerateDirectories(artifactsDir, "*.IntegrationTests")); directories = directories.Concat(Directory.EnumerateDirectories(artifactsDir, "RunTests")); var idToFilePathMap = directories.AsParallel() @@ -71,6 +79,7 @@ Dictionary> initialWalk() static IEnumerable<(Guid mvid, FilePathInfo pathInfo)> walkDirectory(string unitDirPath, string sourceDirectory, string destinationDirectory) { + Console.WriteLine($"[{DateTime.UtcNow}] Walking {unitDirPath}"); string? lastOutputDirectory = null; foreach (var sourceFilePath in Directory.EnumerateFiles(unitDirPath, "*", SearchOption.AllDirectories)) { @@ -144,24 +153,38 @@ void writeHydrateFile() } var builder = new StringBuilder(); + var fileName = isUnix ? "rehydrate.sh" : "rehydrate.cmd"; + var rehydratedDirectories = new List(); foreach (var group in grouping) { - string filename; builder.Clear(); if (isUnix) { - filename = "rehydrate.sh"; writeUnixRehydrateContent(builder, group); rehydrateAllBuilder.AppendLine(@"bash """ + Path.Combine("$scriptroot", group.Key, "rehydrate.sh") + @""""); } else { - filename = "rehydrate.cmd"; writeWindowsRehydrateContent(builder, group); rehydrateAllBuilder.AppendLine("call " + Path.Combine("%~dp0", group.Key, "rehydrate.cmd")); } - File.WriteAllText(Path.Combine(destinationDirectory, group.Key, filename), builder.ToString()); + File.WriteAllText(Path.Combine(destinationDirectory, group.Key, fileName), builder.ToString()); + rehydratedDirectories.Add(group.Key); + } + + // Even if we didn't have any duplicates, write out a file since later scripts rely on its existence. + var noDuplicatesGrouping = idToFilePathMap.Values + .SelectMany(v => v) + .GroupBy(v => getGroupDirectory(v.RelativeDirectory)); + foreach (var noDuplicate in noDuplicatesGrouping) + { + if (!rehydratedDirectories.Contains(noDuplicate.Key)) + { + var file = Path.Combine(destinationDirectory, noDuplicate.Key, fileName); + Contract.Assert(!File.Exists(file)); + File.WriteAllText(file, "echo \"Nothing to rehydrate\""); + } } string rehydrateAllFilename = isUnix ? "rehydrate-all.sh" : "rehydrate-all.cmd"; diff --git a/src/Tools/PrepareTests/TestDiscovery.cs b/src/Tools/PrepareTests/TestDiscovery.cs index 4a0c868b400d7..33a9e261722c1 100644 --- a/src/Tools/PrepareTests/TestDiscovery.cs +++ b/src/Tools/PrepareTests/TestDiscovery.cs @@ -120,8 +120,10 @@ static bool RunWorker(string dotnetPath, string pathToWorker, string pathToAssem private static List GetAssemblies(string binDirectory, bool isUnix) { - var unitTestAssemblies = Directory.GetFiles(binDirectory, "*.UnitTests.dll", SearchOption.AllDirectories).Where(ShouldInclude); - return unitTestAssemblies.ToList(); + var unitTestAssemblies = Directory.GetFiles(binDirectory, "*UnitTests.dll", SearchOption.AllDirectories); + var integrationTestAssemblies = Directory.GetFiles(binDirectory, "*IntegrationTests.dll", SearchOption.AllDirectories); + var assemblies = unitTestAssemblies.Concat(integrationTestAssemblies).Where(ShouldInclude); + return assemblies.ToList(); bool ShouldInclude(string path) { diff --git a/src/Tools/Source/RunTests/RunTests.csproj b/src/Tools/Source/RunTests/RunTests.csproj index 07e5d75d73d88..6bc1f0272ca71 100644 --- a/src/Tools/Source/RunTests/RunTests.csproj +++ b/src/Tools/Source/RunTests/RunTests.csproj @@ -18,4 +18,16 @@ + + + + + + + + <_CopyItems Include="$(NuGetPackageRoot)roslyntools.vsixexpinstaller\$(RoslynToolsVSIXExpInstallerVersion)\tools\*.*" /> + + + + \ No newline at end of file