diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml index 0f3dbd1844fc7f5f5f719bed2e76b03f74d9c731..c7c3350346053e9dabdc9ce41ea85ac4152554e5 100644 --- a/azure-pipelines-integration.yml +++ b/azure-pipelines-integration.yml @@ -24,7 +24,9 @@ pr: jobs: - job: VS_Integration - pool: dotnet-external-vs2019-preview + pool: + name: NetCorePublic-Pool + queue: buildpool.windows.10.amd64.vs2019.pre.open strategy: maxParallel: 4 matrix: @@ -68,6 +70,15 @@ jobs: continueOnError: true condition: not(succeeded()) + - task: PublishBuildArtifacts@1 + displayName: Publish Secondary Logs + inputs: + PathtoPublish: '$(Build.SourcesDirectory)\artifacts\log2\$(_configuration)' + ArtifactName: '$(System.JobAttempt)-Secondary Logs $(_configuration) $(_completionName) $(Build.BuildNumber)' + publishLocation: Container + continueOnError: true + condition: not(succeeded()) + - task: PublishBuildArtifacts@1 displayName: Publish Screenshots inputs: diff --git a/eng/build.ps1 b/eng/build.ps1 index dd47f54d9524935b55921d15b33bcf53d00bc4b2..641f3486f6025de8b617cfbad1a3cbac14c9a919 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -345,6 +345,8 @@ function TestUsingOptimizedRunner() { $env:ROSLYN_TEST_LEGACY_COMPLETION = "true" } + $secondaryLogDir = Join-Path (Join-Path $ArtifactsDir "log2") $configuration + Create-Directory $secondaryLogDir $testResultsDir = Join-Path $ArtifactsDir "TestResults\$configuration" $binDir = Join-Path $ArtifactsDir "bin" $runTests = GetProjectOutputBinary "RunTests.exe" @@ -358,6 +360,7 @@ function TestUsingOptimizedRunner() { $args = "`"$xunitDir`"" $args += " `"-out:$testResultsDir`"" $args += " `"-logs:$LogDir`"" + $args += " `"-secondaryLogs:$secondaryLogDir`"" $args += " -nocache" $args += " -tfm:net472" diff --git a/src/Compilers/Core/MSBuildTask/Csc.cs b/src/Compilers/Core/MSBuildTask/Csc.cs index 35f71df1dca506ae3e9e0ad4384a636f942a795d..09601be8757fe8b9c8ff5d19e4f32f3bcd7c1108 100644 --- a/src/Compilers/Core/MSBuildTask/Csc.cs +++ b/src/Compilers/Core/MSBuildTask/Csc.cs @@ -149,6 +149,8 @@ public string WarningsNotAsErrors get { return (string)_store[nameof(WarningsNotAsErrors)]; } } + public string NullableContextOptions { get { return null; } set { } } + public string Nullable { set { _store[nameof(Nullable)] = value; } diff --git a/src/Compilers/Extension/CompilerPackage.cs b/src/Compilers/Extension/CompilerPackage.cs index b57b04eca3cd2c4cfc8a017874841be2900284c5..47e41de72de68cb886237688ccef69d679263a02 100644 --- a/src/Compilers/Extension/CompilerPackage.cs +++ b/src/Compilers/Extension/CompilerPackage.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.IO; using System.Reflection; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using EnvDTE; @@ -16,6 +17,7 @@ namespace Roslyn.Compilers.Extension { [ProvideAutoLoad(UIContextGuids.SolutionExists, PackageAutoLoadFlags.BackgroundLoad)] [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] + [Guid("31C0675E-87A4-4061-A0DD-A4E510FCCF97")] public sealed class CompilerPackage : AsyncPackage { public static string RoslynHive = null; diff --git a/src/EditorFeatures/Core/Implementation/EncapsulateField/AbstractEncapsulateFieldCommandHandler.cs b/src/EditorFeatures/Core/Implementation/EncapsulateField/AbstractEncapsulateFieldCommandHandler.cs index 44cca64c29542df0389b63695de093e7f1e63f7f..ae6f86aa732096c84be802bd3d3dc0a31898c7cf 100644 --- a/src/EditorFeatures/Core/Implementation/EncapsulateField/AbstractEncapsulateFieldCommandHandler.cs +++ b/src/EditorFeatures/Core/Implementation/EncapsulateField/AbstractEncapsulateFieldCommandHandler.cs @@ -80,6 +80,7 @@ private bool Execute(EncapsulateFieldCommandArgs args, IUIThreadOperationScope w } waitScope.AllowCancellation = false; + cancellationToken = waitScope.Context.UserCancellationToken; var finalSolution = result.GetSolutionAsync(cancellationToken).WaitAndGetResult(cancellationToken); diff --git a/src/Tools/Source/RunTests/Options.cs b/src/Tools/Source/RunTests/Options.cs index ebbb80eac519ac62a00a020f5572d36a28eb2adb..87e45c91c5a8517adaeea22766d596701631bbc3 100644 --- a/src/Tools/Source/RunTests/Options.cs +++ b/src/Tools/Source/RunTests/Options.cs @@ -91,6 +91,11 @@ internal class Options /// public string LogFilesOutputDirectory { get; set; } + /// + /// Directory to hold secondary dump files created while running tests. + /// + public string LogFilesSecondaryOutputDirectory { get; set; } + internal static Options Parse(string[] args) { if (args == null || args.Any(a => a == null) || args.Length < 2) @@ -154,6 +159,11 @@ bool isOption(string argument, string optionName, out string value) opt.LogFilesOutputDirectory = logsPath; index++; } + else if (isOption(current, "-secondaryLogs", out string secondaryLogsPath)) + { + opt.LogFilesSecondaryOutputDirectory = secondaryLogsPath; + index++; + } else if (isOption(current, "-display", out value)) { if (Enum.TryParse(value, ignoreCase: true, result: out Display display)) @@ -238,6 +248,9 @@ bool isOption(string argument, string optionName, out string value) opt.LogFilesOutputDirectory = opt.TestResultXmlOutputDirectory; } + // If we weren't passed both -secondaryLogs and -logs but just -logs (or -out), use the same value for -secondaryLogs too. + opt.LogFilesSecondaryOutputDirectory ??= opt.LogFilesOutputDirectory; + opt.Assemblies = args.Skip(index).ToList(); return allGood ? opt : null; } diff --git a/src/Tools/Source/RunTests/ProcDumpUtil.cs b/src/Tools/Source/RunTests/ProcDumpUtil.cs index 6c8ea4eae10351167d4fc63677beee9efbacc8a2..9142088fd27839d0d4020ba0564c377d10c10ed8 100644 --- a/src/Tools/Source/RunTests/ProcDumpUtil.cs +++ b/src/Tools/Source/RunTests/ProcDumpUtil.cs @@ -11,22 +11,27 @@ namespace RunTests { private const string KeyProcDumpFilePath = "ProcDumpFilePath"; private const string KeyProcDumpDirectory = "ProcDumpOutputPath"; + private const string KeyProcDumpSecondaryDirectory = "ProcDumpSecondaryOutputPath"; internal string ProcDumpFilePath { get; } internal string DumpDirectory { get; } + internal string SecondaryDumpDirectory { get; } - internal ProcDumpInfo(string procDumpFilePath, string dumpDirectory) + internal ProcDumpInfo(string procDumpFilePath, string dumpDirectory, string secondaryDumpDirectory) { Debug.Assert(Path.IsPathRooted(procDumpFilePath)); Debug.Assert(Path.IsPathRooted(dumpDirectory)); + Debug.Assert(Path.IsPathRooted(secondaryDumpDirectory)); ProcDumpFilePath = procDumpFilePath; DumpDirectory = dumpDirectory; + SecondaryDumpDirectory = secondaryDumpDirectory; } internal void WriteEnvironmentVariables(Dictionary environment) { environment[KeyProcDumpFilePath] = ProcDumpFilePath; environment[KeyProcDumpDirectory] = DumpDirectory; + environment[KeyProcDumpSecondaryDirectory] = SecondaryDumpDirectory; } internal static ProcDumpInfo? ReadFromEnvironment() @@ -35,13 +40,14 @@ internal void WriteEnvironmentVariables(Dictionary environment) var procDumpFilePath = Environment.GetEnvironmentVariable(KeyProcDumpFilePath); var dumpDirectory = Environment.GetEnvironmentVariable(KeyProcDumpDirectory); + var secondaryDumpDirectory = Environment.GetEnvironmentVariable(KeyProcDumpSecondaryDirectory); - if (!validate(procDumpFilePath) || !validate(dumpDirectory)) + if (!validate(procDumpFilePath) || !validate(dumpDirectory) || !validate(secondaryDumpDirectory)) { return null; } - return new ProcDumpInfo(procDumpFilePath, dumpDirectory); + return new ProcDumpInfo(procDumpFilePath, dumpDirectory, secondaryDumpDirectory); } } diff --git a/src/Tools/Source/RunTests/Program.cs b/src/Tools/Source/RunTests/Program.cs index 6a5967378bd72f1d7e0299c238d8230bb755a1e8..c73830d3d1e94801769933326128e423090c2d19 100644 --- a/src/Tools/Source/RunTests/Program.cs +++ b/src/Tools/Source/RunTests/Program.cs @@ -20,6 +20,11 @@ namespace RunTests { internal sealed partial class Program { + private static readonly ImmutableHashSet PrimaryProcessNames = ImmutableHashSet.Create( + StringComparer.OrdinalIgnoreCase, + "devenv", + "xunit.console.x86"); + internal const int ExitSuccess = 0; internal const int ExitFailure = 1; @@ -223,10 +228,12 @@ async Task DumpProcess(Process targetProcess, string procDumpExeFilePath, string var procDumpInfo = GetProcDumpInfo(options); if (procDumpInfo != null) { - var dumpDir = procDumpInfo.Value.DumpDirectory; var counter = 0; foreach (var proc in ProcessUtil.GetProcessTree(Process.GetCurrentProcess()).OrderBy(x => x.ProcessName)) { + var dumpDir = PrimaryProcessNames.Contains(proc.ProcessName) + ? procDumpInfo.Value.DumpDirectory + : procDumpInfo.Value.SecondaryDumpDirectory; var dumpFilePath = Path.Combine(dumpDir, $"{proc.ProcessName}-{counter}.dmp"); await DumpProcess(proc, procDumpInfo.Value.ProcDumpFilePath, dumpFilePath); counter++; @@ -244,7 +251,7 @@ async Task DumpProcess(Process targetProcess, string procDumpExeFilePath, string { if (!string.IsNullOrEmpty(options.ProcDumpDirectory)) { - return new ProcDumpInfo(Path.Combine(options.ProcDumpDirectory, "procdump.exe"), options.LogFilesOutputDirectory); + return new ProcDumpInfo(Path.Combine(options.ProcDumpDirectory, "procdump.exe"), options.LogFilesOutputDirectory, options.LogFilesSecondaryOutputDirectory); } return null; diff --git a/src/VisualStudio/Core/Def/Implementation/Preview/PreviewEngine.cs b/src/VisualStudio/Core/Def/Implementation/Preview/PreviewEngine.cs index f0218ab22a6d864581564aa105aadaa754819376..522ed9236a69e008a4c77a37971d7ff1ddbadf60 100644 --- a/src/VisualStudio/Core/Def/Implementation/Preview/PreviewEngine.cs +++ b/src/VisualStudio/Core/Def/Implementation/Preview/PreviewEngine.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; @@ -61,9 +62,9 @@ internal class PreviewEngine : ForegroundThreadAffinitizedObject, IVsPreviewChan { _topLevelName = topLevelItemName; _topLevelGlyph = topLevelGlyph; - _title = title; - _helpString = helpString; - _description = description; + _title = title ?? throw new ArgumentNullException(nameof(title)); + _helpString = helpString ?? throw new ArgumentNullException(nameof(helpString)); + _description = description ?? throw new ArgumentNullException(nameof(description)); _newSolution = newSolution.WithMergedLinkedFileChangesAsync(oldSolution, cancellationToken: CancellationToken.None).Result; _oldSolution = oldSolution; _diffSelector = componentModel.GetService(); diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpEncapsulateField.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpEncapsulateField.cs index fecd883c20c31b666b5b8a632884e8180094ad63..3f1e3034cf71bdc645e7a5bd5d410f7f663b0ab3 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpEncapsulateField.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpEncapsulateField.cs @@ -33,7 +33,7 @@ static void Main(string[] args) } }"; - [WpfFact] + [WpfFact(Skip = "https://github.com/dotnet/roslyn/issues/35701")] [Trait(Traits.Feature, Traits.Features.EncapsulateField)] public void EncapsulateThroughCommand() { diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicEncapsulateField.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicEncapsulateField.cs index 03ab8930668f9964854651b097f67fb60c7d11ac..efa308d3c0bef0466afa1a1f518131294bbd25bc 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicEncapsulateField.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicEncapsulateField.cs @@ -28,7 +28,7 @@ Sub Main() End Sub End Module"; - [WpfFact] + [WpfFact(Skip = "https://github.com/dotnet/roslyn/issues/35701")] [Trait(Traits.Feature, Traits.Features.EncapsulateField)] public void EncapsulateThroughCommand() { diff --git a/src/VisualStudio/IntegrationTest/TestSetup/IntegrationTestServicePackage.cs b/src/VisualStudio/IntegrationTest/TestSetup/IntegrationTestServicePackage.cs index e986b1308222fb5ae195e21adc2a1e632f2cd2b4..8dbe6cf0af2e102393a40aa8661e8abeb9d1cf15 100644 --- a/src/VisualStudio/IntegrationTest/TestSetup/IntegrationTestServicePackage.cs +++ b/src/VisualStudio/IntegrationTest/TestSetup/IntegrationTestServicePackage.cs @@ -16,12 +16,21 @@ namespace Microsoft.VisualStudio.IntegrationTest.Setup [ProvideAutoLoad(UIContextGuids80.SolutionExists, PackageAutoLoadFlags.BackgroundLoad)] public sealed class IntegrationTestServicePackage : AsyncPackage { + private static readonly Guid s_compilerPackage = new Guid("31C0675E-87A4-4061-A0DD-A4E510FCCF97"); + protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress) { await base.InitializeAsync(cancellationToken, progress).ConfigureAwait(true); await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); + var shell = (IVsShell)await GetServiceAsync(typeof(SVsShell)); + ErrorHandler.ThrowOnFailure(shell.IsPackageInstalled(s_compilerPackage, out var installed)); + if (installed != 0) + { + await ((IVsShell7)shell).LoadPackageAsync(s_compilerPackage); + } + IntegrationTestServiceCommands.Initialize(this); } } diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/Dialog_OutOfProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/Dialog_OutOfProc.cs index 46ad922fdcc9cf29c0dc1854db2e301de65c39c0..f9878ca685d8e8043793b9ceb6b0d371d5f84f28 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/Dialog_OutOfProc.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/Dialog_OutOfProc.cs @@ -14,17 +14,21 @@ public Dialog_OutOfProc(VisualStudioInstance visualStudioInstance) public void VerifyOpen(string dialogName) { + using var cancellationTokenSource = new CancellationTokenSource(Helper.HangMitigatingTimeout); + // FindDialog will wait until the dialog is open, so the return value is unused. - DialogHelpers.FindDialogByName(GetMainWindowHWnd(), dialogName, isOpen: true, CancellationToken.None); + DialogHelpers.FindDialogByName(GetMainWindowHWnd(), dialogName, isOpen: true, cancellationTokenSource.Token); // Wait for application idle to ensure the dialog is fully initialized - VisualStudioInstance.WaitForApplicationIdle(CancellationToken.None); + VisualStudioInstance.WaitForApplicationIdle(cancellationTokenSource.Token); } public void VerifyClosed(string dialogName) { + using var cancellationTokenSource = new CancellationTokenSource(Helper.HangMitigatingTimeout); + // FindDialog will wait until the dialog is closed, so the return value is unused. - DialogHelpers.FindDialogByName(GetMainWindowHWnd(), dialogName, isOpen: false, CancellationToken.None); + DialogHelpers.FindDialogByName(GetMainWindowHWnd(), dialogName, isOpen: false, cancellationTokenSource.Token); } public void Click(string dialogName, string buttonName) diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstanceFactory.cs b/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstanceFactory.cs index 9f697a81ba004a40bf7b3ddca91b60c8a7c502c5..ab7b551c1ad789a792020ce40bd5504e5d08f599 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstanceFactory.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstanceFactory.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using EnvDTE; using Microsoft.VisualStudio.Setup.Configuration; +using Microsoft.Win32; using RunTests; using Process = System.Diagnostics.Process; @@ -332,6 +333,18 @@ private static Process StartNewVisualStudioProcess(string installationPath, int var useAsyncCompletionSetting = usingAsyncCompletion ? 1 : -1; Process.Start(vsRegEditExeFile, $"set \"{installationPath}\" {Settings.Default.VsRootSuffix} HKCU \"ApplicationPrivateSettings\\WindowManagement\\Options\" UseAsyncCompletion string \"1*System.Int32*{useAsyncCompletionSetting}\"").WaitForExit(); + var disabledFlights = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\ABExp\LocalTest", "DisabledFlights", Array.Empty()) as string[] ?? Array.Empty(); + if (usingAsyncCompletion) + { + disabledFlights = disabledFlights.Where(flight => !string.Equals(flight, "completionapi", StringComparison.OrdinalIgnoreCase)).ToArray(); + } + else if (!disabledFlights.Contains("completionapi", StringComparer.OrdinalIgnoreCase)) + { + disabledFlights = disabledFlights.Concat(new[] { "completionapi" }).ToArray(); + } + + Registry.SetValue(@"HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\ABExp\LocalTest", "DisabledFlights", disabledFlights, RegistryValueKind.MultiString); + // Disable text editor error reporting because it pops up a dialog. We want to either fail fast in our // custom handler or fail silently and continue testing. Process.Start(vsRegEditExeFile, $"set \"{installationPath}\" {Settings.Default.VsRootSuffix} HKCU \"Text Editor\" \"Report Exceptions\" dword 0").WaitForExit();