Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;

using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;

namespace Microsoft.VisualStudio.TestPlatform.Client;

internal class InProcessTestRunAttachmentsProcessingEventsHandler : ITestRunAttachmentsProcessingEventsHandler
{
private readonly ITestRunAttachmentsProcessingEventsHandler _oldEventsHandler;

public InProcessTestRunAttachmentsProcessingEventsHandler(
ITestRunAttachmentsProcessingEventsHandler oldEventsHandler)
{
_oldEventsHandler = oldEventsHandler;
Comment thread
cvpoienaru marked this conversation as resolved.
Outdated
}

public void HandleLogMessage(TestMessageLevel level, string? message)
{
_oldEventsHandler.HandleLogMessage(level, message);
}

public void HandleProcessedAttachmentsChunk(IEnumerable<AttachmentSet> attachments)
{
// Not implemented by design, keep in sync with the same named method from
// TestRunAttachmentsProcessingEventsHandler.cs.
throw new NotImplementedException();
}

public void HandleRawMessage(string rawMessage)
{
// No-op by design.
//
// For out-of-process vstest.console, raw messages are passed to the translation layer but
// they are never read and don't get passed to the actual events handler in TW. If they
// were (as it happens for in-process vstest.console since there is no more translation
// layer) a NotImplemented exception would be raised as per the time this of writing this
// note.
//
// Consider changing this logic in the future if TW changes the handling logic for raw
// messages.
}

public void HandleTestRunAttachmentsProcessingComplete(
TestRunAttachmentsProcessingCompleteEventArgs attachmentsProcessingCompleteEventArgs,
IEnumerable<AttachmentSet>? lastChunk)
{
_oldEventsHandler.HandleTestRunAttachmentsProcessingComplete(
attachmentsProcessingCompleteEventArgs,
lastChunk);
}

public void HandleTestRunAttachmentsProcessingProgress(
TestRunAttachmentsProcessingProgressEventArgs attachmentsProcessingProgressEventArgs)
{
_oldEventsHandler.HandleTestRunAttachmentsProcessingProgress(
attachmentsProcessingProgressEventArgs);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,16 @@ public void HandleLogMessage(TestMessageLevel level, string? message)

public void HandleRawMessage(string rawMessage)
{
_testSessionEventsHandler.HandleRawMessage(rawMessage);
// No-op by design.
//
// For out-of-process vstest.console, raw messages are passed to the translation layer but
// they are never read and don't get passed to the actual events handler in TW. If they
// were (as it happens for in-process vstest.console since there is no more translation
// layer) a NotImplemented exception would be raised as per the time this of writing this
// note.
//
// Consider changing this logic in the future if TW changes the handling logic for raw
// messages.
}

public void HandleStartTestSessionComplete(StartTestSessionCompleteEventArgs? eventArgs)
Expand Down
28 changes: 26 additions & 2 deletions src/vstest.console/HandlerToEventsRegistrarAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,19 @@ public DiscoveryHandlerToEventsRegistrarAdapter(ITestDiscoveryEventsHandler2 han
_handleDiscoveredTests += (_, e) => _handler.HandleDiscoveredTests(e.DiscoveredTestCases);
_handleLogMessage += (_, e) => _handler.HandleLogMessage(e.Level, e.Message);
_handleDiscoveryComplete += (_, e) => _handler.HandleDiscoveryComplete(e, null);
_handleRawMessage += (_, e) => _handler.HandleRawMessage(e);
_handleRawMessage += (_, e) =>
{
// No-op by design.
//
// For out-of-process vstest.console, raw messages are passed to the translation layer but
// they are never read and don't get passed to the actual events handler in TW. If they
// were (as it happens for in-process vstest.console since there is no more translation
// layer) a NotImplemented exception would be raised as per the time this of writing this
// note.
//
// Consider changing this logic in the future if TW changes the handling logic for raw
// messages.
};
}

public void LogWarning(string message)
Expand Down Expand Up @@ -60,7 +72,19 @@ public RunHandlerToEventsRegistrarAdapter(ITestRunEventsHandler handler)
{
_handler = handler;
_handleLogMessage = (_, e) => _handler.HandleLogMessage(e.Level, e.Message);
_handleRawMessage = (_, e) => _handler.HandleRawMessage(e);
_handleRawMessage = (_, e) =>
{
// No-op by design.
//
// For out-of-process vstest.console, raw messages are passed to the translation layer but
// they are never read and don't get passed to the actual events handler in TW. If they
// were (as it happens for in-process vstest.console since there is no more translation
// layer) a NotImplemented exception would be raised as per the time this of writing this
// note.
//
// Consider changing this logic in the future if TW changes the handling logic for raw
// messages.
};
_handleTestRunComplete = (_, e) => _handler.HandleTestRunComplete(e, null, null, null);
_handleTestRunStatsChange = (_, e) => _handler.HandleTestRunStatsChange(e);
}
Expand Down
29 changes: 28 additions & 1 deletion src/vstest.console/InProcessVsTestConsoleWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -88,6 +89,8 @@ internal InProcessVsTestConsoleWrapper(
#endif
consoleParameters.PortNumber = port;

UpdateDotnetLookupPath();
Comment thread
cvpoienaru marked this conversation as resolved.
Outdated

// Start vstest.console.
// TODO: under VS we use consoleParameters.InheritEnvironmentVariables, we take that
// into account when starting a testhost, or clean up in the service host, and use the
Expand Down Expand Up @@ -133,6 +136,30 @@ internal InProcessVsTestConsoleWrapper(

internal ITestRequestManager? TestRequestManager { get; set; }

private void UpdateDotnetLookupPath()
{
const string dotnetRootOverrideEnvVarName = "VSTEST_WINAPPHOST_DOTNET_ROOT";
Comment thread
cvpoienaru marked this conversation as resolved.
Outdated
const string programFilesPathEnvVarName = "ProgramFiles";
const string dotnetGlobalInstallationDir = "dotnet";

// Allow users to specify a dotnet private installation path before attempting to use the
// global installation path.
if (_environmentVariableHelper.GetEnvironmentVariable(dotnetRootOverrideEnvVarName) is not null)
{
return;
}

var dotnetPathPrefix = _environmentVariableHelper.GetEnvironmentVariable(programFilesPathEnvVarName);
Comment thread
cvpoienaru marked this conversation as resolved.
Outdated
if (dotnetPathPrefix is null)
{
return;
}

_environmentVariableHelper.SetEnvironmentVariable(
Comment thread
cvpoienaru marked this conversation as resolved.
Outdated
dotnetRootOverrideEnvVarName,
Path.Combine(dotnetPathPrefix, dotnetGlobalInstallationDir));
}

/// <inheritdoc/>
public void AbortTestRun()
{
Expand Down Expand Up @@ -869,7 +896,7 @@ public async Task ProcessTestRunAttachmentsAsync(
await Task.Run(() =>
TestRequestManager?.ProcessTestRunAttachments(
attachmentProcessingPayload,
eventsHandler,
new InProcessTestRunAttachmentsProcessingEventsHandler(eventsHandler),
new ProtocolConfig { Version = _highestSupportedVersion }),
CancellationToken.None)
.ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -114,6 +115,59 @@ public void InProcessWrapperConstructorShouldSetEnvironmentVariablesReceivedAsCo
_mockEnvironmentVariableHelper.Verify(evh => evh.SetEnvironmentVariable(environmentVariableName, "1"));
}

[TestMethod]
public void InProcessWrapperConstructorShouldNotOverwriteVstestWinapphostEnvironmentVariable()
{
const string environmentVariableName = "VSTEST_WINAPPHOST_DOTNET_ROOT";

_mockEnvironmentVariableHelper.Invocations.Clear();
_mockEnvironmentVariableHelper.Setup(evh => evh.GetEnvironmentVariable(environmentVariableName))
.Returns(() => "dummy");

var consoleParams = new ConsoleParameters();
var _ = new InProcessVsTestConsoleWrapper(
consoleParams,
_mockEnvironmentVariableHelper.Object,
_mockRequestSender.Object,
_mockTestRequestManager.Object,
new Executor(_mockOutput.Object, new Mock<ITestPlatformEventSource>().Object, new ProcessHelper(), new PlatformEnvironment()),
new Mock<ITestPlatformEventSource>().Object);

_mockEnvironmentVariableHelper.Verify(evh =>
evh.GetEnvironmentVariable(environmentVariableName), Times.Once);
_mockEnvironmentVariableHelper.Verify(evh =>
evh.SetEnvironmentVariable(environmentVariableName, It.IsAny<string>()), Times.Never);
}

[TestMethod]
public void InProcessWrapperConstructorShouldSetVstestWinapphostEnvironmentVariableWhenUnset()
{
const string dotnetRootOverrideEnvVarName = "VSTEST_WINAPPHOST_DOTNET_ROOT";
const string programFilesPathEnvVarName = "ProgramFiles";

_mockEnvironmentVariableHelper.Invocations.Clear();
_mockEnvironmentVariableHelper.Setup(evh => evh.GetEnvironmentVariable(dotnetRootOverrideEnvVarName))
.Returns(() => null);
_mockEnvironmentVariableHelper.Setup(evh => evh.GetEnvironmentVariable(programFilesPathEnvVarName))
.Returns(() => Path.Combine("C:", "Program Files"));

var consoleParams = new ConsoleParameters();
var _ = new InProcessVsTestConsoleWrapper(
consoleParams,
_mockEnvironmentVariableHelper.Object,
_mockRequestSender.Object,
_mockTestRequestManager.Object,
new Executor(_mockOutput.Object, new Mock<ITestPlatformEventSource>().Object, new ProcessHelper(), new PlatformEnvironment()),
new Mock<ITestPlatformEventSource>().Object);

_mockEnvironmentVariableHelper.Verify(evh =>
evh.GetEnvironmentVariable(dotnetRootOverrideEnvVarName), Times.Once);
_mockEnvironmentVariableHelper.Verify(evh =>
evh.GetEnvironmentVariable(programFilesPathEnvVarName), Times.Once);
_mockEnvironmentVariableHelper.Verify(evh =>
evh.SetEnvironmentVariable(dotnetRootOverrideEnvVarName, Path.Combine("C:", "Program Files", "dotnet")), Times.Once);
}

[TestMethod]
public void InProcessWrapperDiscoverTestsWithThreeParamsIsSuccessfullyInvoked()
{
Expand Down