From ddcda63cdfb5ef0def3969b116ce44dfec2e407f Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 21 Mar 2017 18:45:49 -0700 Subject: [PATCH 1/4] Migrate CSharpBuild and BasicBuild over to inheriting from AbstractIntegrationTest --- .../IntegrationTests/CSharp/CSharpBuild.cs | 18 +++++------------- .../IntegrationTests/VisualBasic/BasicBuild.cs | 13 +++++-------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpBuild.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpBuild.cs index 1ebddd8a3f5e7..92cb82b8e3385 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpBuild.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpBuild.cs @@ -8,21 +8,13 @@ namespace Roslyn.VisualStudio.IntegrationTests.CSharp { [Collection(nameof(SharedIntegrationHostFixture))] - public class CSharpBuild : IDisposable + public class CSharpBuild : AbstractIntegrationTest { - private readonly VisualStudioInstanceContext _visualStudio; - public CSharpBuild(VisualStudioInstanceFactory instanceFactory) + : base(instanceFactory) { - _visualStudio = instanceFactory.GetNewOrUsedInstance(SharedIntegrationHostFixture.RequiredPackageIds); - - _visualStudio.Instance.SolutionExplorer.CreateSolution(nameof(CSharpBuild)); - _visualStudio.Instance.SolutionExplorer.AddProject("TestProj", WellKnownProjectTemplates.ConsoleApplication, LanguageNames.CSharp); - } - - public void Dispose() - { - _visualStudio.Dispose(); + VisualStudio.Instance.SolutionExplorer.CreateSolution(nameof(CSharpBuild)); + VisualStudio.Instance.SolutionExplorer.AddProject("TestProj", WellKnownProjectTemplates.ConsoleApplication, LanguageNames.CSharp); } [Fact] @@ -38,7 +30,7 @@ static void Main(string[] args) } }"; - _visualStudio.Instance.Editor.SetText(editorText); + VisualStudio.Instance.Editor.SetText(editorText); // TODO: Validate build works as expected } diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicBuild.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicBuild.cs index 1fb6965fd0b26..f38e40534b200 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicBuild.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicBuild.cs @@ -7,16 +7,13 @@ namespace Roslyn.VisualStudio.IntegrationTests.VisualBasic { [Collection(nameof(SharedIntegrationHostFixture))] - public class BasicBuild + public class BasicBuild : AbstractIntegrationTest { - private readonly VisualStudioInstanceContext _visualStudio; - public BasicBuild(VisualStudioInstanceFactory instanceFactory) + : base(instanceFactory) { - _visualStudio = instanceFactory.GetNewOrUsedInstance(SharedIntegrationHostFixture.RequiredPackageIds); - - _visualStudio.Instance.SolutionExplorer.CreateSolution(nameof(BasicBuild)); - _visualStudio.Instance.SolutionExplorer.AddProject("TestProj", WellKnownProjectTemplates.ConsoleApplication, LanguageNames.VisualBasic); + VisualStudio.Instance.SolutionExplorer.CreateSolution(nameof(BasicBuild)); + VisualStudio.Instance.SolutionExplorer.AddProject("TestProj", WellKnownProjectTemplates.ConsoleApplication, LanguageNames.VisualBasic); } [Fact] @@ -30,7 +27,7 @@ End Sub End Module"; - _visualStudio.Instance.Editor.SetText(editorText); + VisualStudio.Instance.Editor.SetText(editorText); // TODO: Validate build works as expected } From addd31a3a02087c6c207f1b151c16e5d5ffe51b4 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 21 Mar 2017 19:46:38 -0700 Subject: [PATCH 2/4] Have a VisualStudioInstance hold onto more information An instance should hold onto it's supported packages and path without expecting the factory to do it for it. --- .../TestUtilities/VisualStudioInstance.cs | 17 ++++++++++++++++- .../VisualStudioInstanceFactory.cs | 17 ++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstance.cs b/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstance.cs index 6f22182025be0..5a773ab2019b6 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstance.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstance.cs @@ -1,6 +1,8 @@ // 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.Immutable; +using System.Diagnostics; using System.Runtime.InteropServices; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Ipc; @@ -43,10 +45,23 @@ public class VisualStudioInstance internal Process HostProcess { get; } - public VisualStudioInstance(Process hostProcess, DTE dte) + /// + /// The set of Visual Studio packages that are installed into this instance. + /// + public ImmutableHashSet SupportedPackageIds { get; } + + /// + /// The path to the root of this installed version of Visual Studio. This is the folder that contains + /// Common7\IDE. + /// + public string InstallationPath { get; } + + public VisualStudioInstance(Process hostProcess, DTE dte, ImmutableHashSet supportedPackageIds, string installationPath) { HostProcess = hostProcess; Dte = dte; + SupportedPackageIds = supportedPackageIds; + InstallationPath = installationPath; StartRemoteIntegrationService(dte); diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstanceFactory.cs b/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstanceFactory.cs index 37e47a6077d95..b259089a722e9 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstanceFactory.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstanceFactory.cs @@ -28,8 +28,7 @@ public sealed class VisualStudioInstanceFactory : IDisposable /// The instance that has already been launched by this factory and can be reused. /// private VisualStudioInstance _currentlyRunningInstance; - private ImmutableHashSet _supportedPackageIds; - private string _installationPath; + private bool _hasCurrentlyActiveContext; static VisualStudioInstanceFactory() @@ -123,7 +122,7 @@ private bool ShouldStartNewInstance(ImmutableHashSet requiredPackageIds) // * The current instance is no longer running return _currentlyRunningInstance == null - || (_supportedPackageIds != null && !requiredPackageIds.All((requiredPackageId) => _supportedPackageIds.Contains(requiredPackageId))) // _supportedPackagesIds will be null if ISetupInstance2.GetPackages() is NYI + || (!requiredPackageIds.All(id => _currentlyRunningInstance.SupportedPackageIds.Contains(id))) || !_currentlyRunningInstance.IsRunning; } @@ -142,6 +141,8 @@ private void UpdateCurrentlyRunningInstance(ImmutableHashSet requiredPac { Process hostProcess; DTE dte; + ImmutableHashSet supportedPackageIds; + string installationPath; if (shouldStartNewInstance) { @@ -149,10 +150,10 @@ private void UpdateCurrentlyRunningInstance(ImmutableHashSet requiredPac _currentlyRunningInstance?.Close(); var instance = LocateVisualStudioInstance(requiredPackageIds) as ISetupInstance2; - _supportedPackageIds = ImmutableHashSet.CreateRange(instance.GetPackages().Select((supportedPackage) => supportedPackage.GetId())); - _installationPath = instance.GetInstallationPath(); + supportedPackageIds = ImmutableHashSet.CreateRange(instance.GetPackages().Select((supportedPackage) => supportedPackage.GetId())); + installationPath = instance.GetInstallationPath(); - hostProcess = StartNewVisualStudioProcess(_installationPath); + hostProcess = StartNewVisualStudioProcess(installationPath); // We wait until the DTE instance is up before we're good dte = IntegrationHelper.WaitForNotNullAsync(() => IntegrationHelper.TryLocateDteForProcess(hostProcess)).Result; } @@ -166,11 +167,13 @@ private void UpdateCurrentlyRunningInstance(ImmutableHashSet requiredPac hostProcess = _currentlyRunningInstance.HostProcess; dte = _currentlyRunningInstance.Dte; + supportedPackageIds = _currentlyRunningInstance.SupportedPackageIds; + installationPath = _currentlyRunningInstance.InstallationPath; _currentlyRunningInstance.Close(exitHostProcess: false); } - _currentlyRunningInstance = new VisualStudioInstance(hostProcess, dte); + _currentlyRunningInstance = new VisualStudioInstance(hostProcess, dte, supportedPackageIds, installationPath); } private static ISetupConfiguration GetSetupConfiguration() From a50015acd051032145c13114f498a2c4de3b6e1f Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 21 Mar 2017 19:46:52 -0700 Subject: [PATCH 3/4] Add a trivial API to get the path to a solution file --- .../TestUtilities/InProcess/SolutionExplorer_InProc.cs | 4 ++-- .../TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs index a43f6bf8ee01c..fff39a37609a9 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/SolutionExplorer_InProc.cs @@ -59,9 +59,9 @@ private static IDictionary InitializeVisualBasicProjectTemplates }; } - public string DirectoryName => Path.GetDirectoryName(FileName); + public string DirectoryName => Path.GetDirectoryName(SolutionFileFullPath); - public string FileName + public string SolutionFileFullPath { get { diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs index bbd748d9c3cc8..78aea56d5e410 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/SolutionExplorer_OutOfProc.cs @@ -19,6 +19,11 @@ public SolutionExplorer_OutOfProc(VisualStudioInstance visualStudioInstance) public void CloseSolution(bool saveFirst = false) => _inProc.CloseSolution(saveFirst); + /// + /// The full file path to the solution file. + /// + public string SolutionFileFullPath => _inProc.SolutionFileFullPath; + /// /// Creates and loads a new solution in the host process, optionally saving the existing solution if one exists. /// From 1b336c0a2d014009e479b35f534a5e0d371eced0 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 21 Mar 2017 19:47:30 -0700 Subject: [PATCH 4/4] Add a test to test building with devenv /build Fixes https://github.com/dotnet/roslyn/issues/16865 --- src/EditorFeatures/TestUtilities/Traits.cs | 1 + .../IntegrationTests/CSharp/CSharpBuild.cs | 25 ++++++++++++++++++- .../VisualBasic/BasicBuild.cs | 3 ++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/EditorFeatures/TestUtilities/Traits.cs b/src/EditorFeatures/TestUtilities/Traits.cs index 9392224cca979..d22226b51ef72 100644 --- a/src/EditorFeatures/TestUtilities/Traits.cs +++ b/src/EditorFeatures/TestUtilities/Traits.cs @@ -22,6 +22,7 @@ public static class Features public const string BlockCommentEditing = nameof(BlockCommentEditing); public const string BraceHighlighting = nameof(BraceHighlighting); public const string BraceMatching = nameof(BraceMatching); + public const string Build = nameof(Build); public const string CallHierarchy = nameof(CallHierarchy); public const string CaseCorrection = nameof(CaseCorrection); public const string ChangeSignature = nameof(ChangeSignature); diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpBuild.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpBuild.cs index 92cb82b8e3385..4b6ff655795ae 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpBuild.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpBuild.cs @@ -1,8 +1,11 @@ // 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.Diagnostics; +using System.IO; using Microsoft.CodeAnalysis; using Microsoft.VisualStudio.IntegrationTest.Utilities; +using Roslyn.Test.Utilities; using Xunit; namespace Roslyn.VisualStudio.IntegrationTests.CSharp @@ -17,7 +20,7 @@ public CSharpBuild(VisualStudioInstanceFactory instanceFactory) VisualStudio.Instance.SolutionExplorer.AddProject("TestProj", WellKnownProjectTemplates.ConsoleApplication, LanguageNames.CSharp); } - [Fact] + [Fact, Trait(Traits.Feature, Traits.Features.Build)] public void BuildProject() { var editorText = @"using System; @@ -35,5 +38,25 @@ static void Main(string[] args) // TODO: Validate build works as expected } + [Fact, Trait(Traits.Feature, Traits.Features.Build)] + public void BuildWithCommandLine() + { + VisualStudio.Instance.SolutionExplorer.SaveAll(); + + var pathToDevenv = Path.Combine(VisualStudio.Instance.InstallationPath, @"Common7\IDE\devenv.exe"); + var pathToSolution = VisualStudio.Instance.SolutionExplorer.SolutionFileFullPath; + var logFileName = pathToSolution + ".log"; + + File.Delete(logFileName); + + var commandLine = $"\"{pathToSolution}\" /Rebuild Debug /Out \"{logFileName}\" {VisualStudioInstanceFactory.VsLaunchArgs}"; + + var process = Process.Start(pathToDevenv, commandLine); + process.WaitForExit(); + + Assert.Equal(0, process.ExitCode); + + Assert.Contains("Rebuild All: 1 succeeded, 0 failed, 0 skipped", File.ReadAllText(logFileName)); + } } } diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicBuild.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicBuild.cs index f38e40534b200..fb55b14927fdc 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicBuild.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicBuild.cs @@ -2,6 +2,7 @@ using Microsoft.CodeAnalysis; using Microsoft.VisualStudio.IntegrationTest.Utilities; +using Roslyn.Test.Utilities; using Xunit; namespace Roslyn.VisualStudio.IntegrationTests.VisualBasic @@ -16,7 +17,7 @@ public BasicBuild(VisualStudioInstanceFactory instanceFactory) VisualStudio.Instance.SolutionExplorer.AddProject("TestProj", WellKnownProjectTemplates.ConsoleApplication, LanguageNames.VisualBasic); } - [Fact] + [Fact, Trait(Traits.Feature, Traits.Features.Build)] public void BuildProject() { var editorText = @"Module Program