-
Notifications
You must be signed in to change notification settings - Fork 292
Expand file tree
/
Copy pathDotnetTestConnection.cs
More file actions
148 lines (119 loc) · 7.64 KB
/
DotnetTestConnection.cs
File metadata and controls
148 lines (119 loc) · 7.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.Testing.Platform.CommandLine;
using Microsoft.Testing.Platform.Extensions.CommandLine;
using Microsoft.Testing.Platform.Helpers;
using Microsoft.Testing.Platform.IPC;
using Microsoft.Testing.Platform.IPC.Models;
using Microsoft.Testing.Platform.IPC.Serializers;
using Microsoft.Testing.Platform.ServerMode;
using Microsoft.Testing.Platform.Services;
using Microsoft.Testing.Platform.Tools;
namespace Microsoft.Testing.Platform;
[UnsupportedOSPlatform("browser")]
internal sealed class DotnetTestConnection : IPushOnlyProtocol, IDisposable
{
private readonly CommandLineHandler _commandLineHandler;
private readonly IEnvironment _environment;
private readonly ITestApplicationModuleInfo _testApplicationModuleInfo;
private readonly ITestApplicationCancellationTokenSource _cancellationTokenSource;
private NamedPipeClient? _dotnetTestPipeClient;
public static string InstanceId { get; } = Guid.NewGuid().ToString("N");
public DotnetTestConnection(CommandLineHandler commandLineHandler, IEnvironment environment, ITestApplicationModuleInfo testApplicationModuleInfo, ITestApplicationCancellationTokenSource cancellationTokenSource)
{
_commandLineHandler = commandLineHandler;
_environment = environment;
_testApplicationModuleInfo = testApplicationModuleInfo;
_cancellationTokenSource = cancellationTokenSource;
}
public bool IsServerMode => _dotnetTestPipeClient?.IsConnected == true;
public Task<IPushOnlyProtocolConsumer> GetDataConsumerAsync()
=> Task.FromResult((IPushOnlyProtocolConsumer)new DotnetTestDataConsumer(this, _environment));
public async Task AfterCommonServiceSetupAsync()
{
// If we are in server mode and the pipe name is provided
// then, we need to connect to the pipe server.
if (_commandLineHandler.HasDotnetTestServerOption() &&
_commandLineHandler.TryGetOptionArgumentList(PlatformCommandLineProvider.DotNetTestPipeOptionKey, out string[]? arguments))
{
// The execution id is used to identify the test execution
// We are storing it as an env var so that it can be read by the test host, test host controller and the test host orchestrator
// If it already exists, we don't overwrite it
if (RoslynString.IsNullOrEmpty(_environment.GetEnvironmentVariable(EnvironmentVariableConstants.TESTINGPLATFORM_DOTNETTEST_EXECUTIONID)))
{
_environment.SetEnvironmentVariable(EnvironmentVariableConstants.TESTINGPLATFORM_DOTNETTEST_EXECUTIONID, Guid.NewGuid().ToString("N"));
}
_dotnetTestPipeClient = new(arguments[0], _environment);
_dotnetTestPipeClient.RegisterAllSerializers();
await _dotnetTestPipeClient.ConnectAsync(_cancellationTokenSource.CancellationToken).ConfigureAwait(false);
}
}
public async Task HelpInvokedAsync()
{
RoslynDebug.Assert(_dotnetTestPipeClient is not null);
List<CommandLineOptionMessage> commandLineHelpOptions = [];
foreach (ICommandLineOptionsProvider commandLineOptionProvider in _commandLineHandler.CommandLineOptionsProviders)
{
if (commandLineOptionProvider is IToolCommandLineOptionsProvider)
{
continue;
}
foreach (CommandLineOption commandLineOption in commandLineOptionProvider.GetCommandLineOptions())
{
commandLineHelpOptions.Add(new CommandLineOptionMessage(
commandLineOption.Name,
commandLineOption.Description,
commandLineOption.IsHidden,
commandLineOption.IsBuiltIn,
commandLineOption.ObsolescenceMessage));
}
}
await _dotnetTestPipeClient.RequestReplyAsync<CommandLineOptionMessages, VoidResponse>(new CommandLineOptionMessages(_testApplicationModuleInfo.GetCurrentTestApplicationFullPath(), [.. commandLineHelpOptions.OrderBy(option => option.Name)]), _cancellationTokenSource.CancellationToken).ConfigureAwait(false);
}
public bool IsIDE { get; private set; }
public async Task<bool> IsCompatibleProtocolAsync(string hostType)
{
RoslynDebug.Assert(_dotnetTestPipeClient is not null);
const string supportedProtocolVersions = ProtocolConstants.SupportedVersions;
HandshakeMessage handshakeMessage = new(new Dictionary<byte, string>
{
{ HandshakeMessagePropertyNames.PID, _environment.ProcessId.ToString(CultureInfo.InvariantCulture) },
{ HandshakeMessagePropertyNames.Architecture, RuntimeInformation.ProcessArchitecture.ToString() },
{ HandshakeMessagePropertyNames.Framework, RuntimeInformation.FrameworkDescription },
{ HandshakeMessagePropertyNames.OS, RuntimeInformation.OSDescription },
{ HandshakeMessagePropertyNames.SupportedProtocolVersions, supportedProtocolVersions },
{ HandshakeMessagePropertyNames.HostType, hostType },
{ HandshakeMessagePropertyNames.ModulePath, _testApplicationModuleInfo?.GetCurrentTestApplicationFullPath() ?? string.Empty },
{ HandshakeMessagePropertyNames.ExecutionId, _environment.GetEnvironmentVariable(EnvironmentVariableConstants.TESTINGPLATFORM_DOTNETTEST_EXECUTIONID) ?? string.Empty },
{ HandshakeMessagePropertyNames.InstanceId, InstanceId },
});
HandshakeMessage response = await _dotnetTestPipeClient.RequestReplyAsync<HandshakeMessage, HandshakeMessage>(handshakeMessage, _cancellationTokenSource.CancellationToken).ConfigureAwait(false);
IsIDE = response.Properties?.TryGetValue(HandshakeMessagePropertyNames.IsIDE, out string? isIDEValue) == true &&
bool.TryParse(isIDEValue, out bool isIDE) &&
isIDE;
return response.Properties?.TryGetValue(HandshakeMessagePropertyNames.SupportedProtocolVersions, out string? protocolVersion) == true &&
IsVersionCompatible(protocolVersion, supportedProtocolVersions);
}
public static bool IsVersionCompatible(string protocolVersion, string supportedProtocolVersions) => supportedProtocolVersions.Split(';').Contains(protocolVersion);
public async Task SendMessageAsync(IRequest message)
{
RoslynDebug.Assert(_dotnetTestPipeClient is not null);
switch (message)
{
case DiscoveredTestMessages discoveredTestMessages:
await _dotnetTestPipeClient.RequestReplyAsync<DiscoveredTestMessages, VoidResponse>(discoveredTestMessages, _cancellationTokenSource.CancellationToken).ConfigureAwait(false);
break;
case TestResultMessages testResultMessages:
await _dotnetTestPipeClient.RequestReplyAsync<TestResultMessages, VoidResponse>(testResultMessages, _cancellationTokenSource.CancellationToken).ConfigureAwait(false);
break;
case FileArtifactMessages fileArtifactMessages:
await _dotnetTestPipeClient.RequestReplyAsync<FileArtifactMessages, VoidResponse>(fileArtifactMessages, _cancellationTokenSource.CancellationToken).ConfigureAwait(false);
break;
case TestSessionEvent testSessionEvent:
await _dotnetTestPipeClient.RequestReplyAsync<TestSessionEvent, VoidResponse>(testSessionEvent, _cancellationTokenSource.CancellationToken).ConfigureAwait(false);
break;
}
}
public Task OnExitAsync() => Task.CompletedTask;
public void Dispose() => _dotnetTestPipeClient?.Dispose();
}