in src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs [269:518]
public void OnMessageReceived(object sender, MessageReceivedEventArgs messageReceivedArgs)
{
var message = _dataSerializer.DeserializeMessage(messageReceivedArgs.Data);
if (EqtTrace.IsInfoEnabled)
{
EqtTrace.Info("TestRequestHandler.OnMessageReceived: received message: {0}", message);
}
switch (message.MessageType)
{
case MessageType.VersionCheck:
try
{
var version = _dataSerializer.DeserializePayload<int>(message);
// choose the highest version that we both support
var negotiatedVersion = Math.Min(version, _highestSupportedVersion);
// BUT don't choose 3, because protocol version 3 has performance problems in 16.7.1-16.8. Those problems are caused
// by choosing payloadSerializer instead of payloadSerializer2 for protocol version 3.
//
// We cannot just update the code to choose the new serializer, because then that change would apply only to testhost.
// Testhost is is delivered by Microsoft.NET.Test.SDK nuget package, and can be used with an older vstest.console.
// An older vstest.console, that supports protocol version 3, would serialize its messages using payloadSerializer,
// but the fixed testhost would serialize it using payloadSerializer2, resulting in incompatible messages.
//
// Instead we must downgrade to protocol version 2 when 3 would be negotiated. Or higher when higher version
// would be negotiated.
if (negotiatedVersion != 3)
{
_protocolVersion = negotiatedVersion;
}
else
{
var flag = Environment.GetEnvironmentVariable("VSTEST_DISABLE_PROTOCOL_3_VERSION_DOWNGRADE");
var flagIsEnabled = flag != null && flag != "0";
var dowgradeIsDisabled = flagIsEnabled;
_protocolVersion = dowgradeIsDisabled ? negotiatedVersion : 2;
}
// Send the negotiated protocol to request sender
_channel.Send(_dataSerializer.SerializePayload(MessageType.VersionCheck, _protocolVersion));
// Can only do this after InitializeCommunication because TestHost cannot "Send Log" unless communications are initialized
if (!string.IsNullOrEmpty(EqtTrace.LogFile))
{
SendLog(TestMessageLevel.Informational, string.Format(CrossPlatResources.TesthostDiagLogOutputFile, EqtTrace.LogFile));
}
else if (!string.IsNullOrEmpty(EqtTrace.ErrorOnInitialization))
{
SendLog(TestMessageLevel.Warning, EqtTrace.ErrorOnInitialization);
}
}
catch (Exception ex)
{
_messageProcessingUnrecoverableError = ex;
EqtTrace.Error("Failed processing message {0}, aborting test run.", message.MessageType);
EqtTrace.Error(ex);
goto case MessageType.AbortTestRun;
}
break;
case MessageType.DiscoveryInitialize:
{
try
{
_testHostManagerFactoryReady.Wait();
var discoveryEventsHandler = new TestDiscoveryEventHandler(this);
var pathToAdditionalExtensions = _dataSerializer.DeserializePayload<IEnumerable<string>>(message);
Action job = () =>
{
EqtTrace.Info("TestRequestHandler.OnMessageReceived: Running job '{0}'.", message.MessageType);
_testHostManagerFactory.GetDiscoveryManager().Initialize(pathToAdditionalExtensions, discoveryEventsHandler);
};
_jobQueue.QueueJob(job, 0);
}
catch (Exception ex)
{
_messageProcessingUnrecoverableError = ex;
EqtTrace.Error("Failed processing message {0}, aborting test run.", message.MessageType);
EqtTrace.Error(ex);
goto case MessageType.AbortTestRun;
}
break;
}
case MessageType.StartDiscovery:
{
try
{
_testHostManagerFactoryReady.Wait();
var discoveryEventsHandler = new TestDiscoveryEventHandler(this);
var discoveryCriteria = _dataSerializer.DeserializePayload<DiscoveryCriteria>(message);
Action job = () =>
{
EqtTrace.Info("TestRequestHandler.OnMessageReceived: Running job '{0}'.", message.MessageType);
_testHostManagerFactory.GetDiscoveryManager()
.DiscoverTests(discoveryCriteria, discoveryEventsHandler);
};
_jobQueue.QueueJob(job, 0);
}
catch (Exception ex)
{
_messageProcessingUnrecoverableError = ex;
EqtTrace.Error("Failed processing message {0}, aborting test run.", message.MessageType);
EqtTrace.Error(ex);
goto case MessageType.AbortTestRun;
}
break;
}
case MessageType.ExecutionInitialize:
{
try
{
_testHostManagerFactoryReady.Wait();
var testInitializeEventsHandler = new TestInitializeEventsHandler(this);
var pathToAdditionalExtensions = _dataSerializer.DeserializePayload<IEnumerable<string>>(message);
Action job = () =>
{
EqtTrace.Info("TestRequestHandler.OnMessageReceived: Running job '{0}'.", message.MessageType);
_testHostManagerFactory.GetExecutionManager().Initialize(pathToAdditionalExtensions, testInitializeEventsHandler);
};
_jobQueue.QueueJob(job, 0);
}
catch (Exception ex)
{
_messageProcessingUnrecoverableError = ex;
EqtTrace.Error("Failed processing message {0}, aborting test run.", message.MessageType);
EqtTrace.Error(ex);
goto case MessageType.AbortTestRun;
}
break;
}
case MessageType.StartTestExecutionWithSources:
{
try
{
var testRunEventsHandler = new TestRunEventsHandler(this);
_testHostManagerFactoryReady.Wait();
var testRunCriteriaWithSources = _dataSerializer.DeserializePayload<TestRunCriteriaWithSources>(message);
Action job = () =>
{
EqtTrace.Info("TestRequestHandler.OnMessageReceived: Running job '{0}'.", message.MessageType);
_testHostManagerFactory.GetExecutionManager()
.StartTestRun(
testRunCriteriaWithSources.AdapterSourceMap,
testRunCriteriaWithSources.Package,
testRunCriteriaWithSources.RunSettings,
testRunCriteriaWithSources.TestExecutionContext,
GetTestCaseEventsHandler(testRunCriteriaWithSources.RunSettings),
testRunEventsHandler);
};
_jobQueue.QueueJob(job, 0);
}
catch (Exception ex)
{
_messageProcessingUnrecoverableError = ex;
EqtTrace.Error("Failed processing message {0}, aborting test run.", message.MessageType);
EqtTrace.Error(ex);
goto case MessageType.AbortTestRun;
}
break;
}
case MessageType.StartTestExecutionWithTests:
{
try
{
var testRunEventsHandler = new TestRunEventsHandler(this);
_testHostManagerFactoryReady.Wait();
var testRunCriteriaWithTests =
_dataSerializer.DeserializePayload<TestRunCriteriaWithTests>(message);
Action job = () =>
{
EqtTrace.Info("TestRequestHandler.OnMessageReceived: Running job '{0}'.", message.MessageType);
_testHostManagerFactory.GetExecutionManager()
.StartTestRun(
testRunCriteriaWithTests.Tests,
testRunCriteriaWithTests.Package,
testRunCriteriaWithTests.RunSettings,
testRunCriteriaWithTests.TestExecutionContext,
GetTestCaseEventsHandler(testRunCriteriaWithTests.RunSettings),
testRunEventsHandler);
};
_jobQueue.QueueJob(job, 0);
}
catch (Exception ex)
{
_messageProcessingUnrecoverableError = ex;
EqtTrace.Error("Failed processing message {0}, aborting test run.", message.MessageType);
EqtTrace.Error(ex);
goto case MessageType.AbortTestRun;
}
break;
}
case MessageType.CancelTestRun:
_jobQueue.Pause();
_testHostManagerFactoryReady.Wait();
_testHostManagerFactory.GetExecutionManager().Cancel(new TestRunEventsHandler(this));
break;
case MessageType.LaunchAdapterProcessWithDebuggerAttachedCallback:
_onLaunchAdapterProcessWithDebuggerAttachedAckReceived?.Invoke(message);
break;
case MessageType.AttachDebuggerCallback:
_onAttachDebuggerAckRecieved?.Invoke(message);
break;
case MessageType.AbortTestRun:
try
{
_jobQueue.Pause();
_testHostManagerFactoryReady.Wait();
_testHostManagerFactory.GetExecutionManager().Abort(new TestRunEventsHandler(this));
}
catch (Exception ex)
{
EqtTrace.Error("Failed processing message {0}. Stopping communication.", message.MessageType);
EqtTrace.Error(ex);
_sessionCompleted.Set();
Close();
}
break;
case MessageType.SessionEnd:
{
EqtTrace.Info("Session End message received from server. Closing the connection.");
_sessionCompleted.Set();
Close();
break;
}
case MessageType.SessionAbort:
{
// Don't do anything for now.
break;
}
default:
{
EqtTrace.Info("Invalid Message types");
break;
}
}
}