зеркало из https://github.com/microsoft/testfx.git
Prepare for multi push-only protocol (#3779)
This commit is contained in:
Родитель
54841340f9
Коммит
2d649f59dc
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Microsoft.Testing.Platform.Hosts;
|
||||
using Microsoft.Testing.Platform.ServerMode;
|
||||
using Microsoft.Testing.Platform.Services;
|
||||
|
||||
namespace Microsoft.Testing.Platform.CommandLine;
|
||||
|
@ -15,18 +16,18 @@ internal sealed class InformativeCommandLineTestHost(int returnValue, IServicePr
|
|||
{
|
||||
private readonly int _returnValue = returnValue;
|
||||
|
||||
private DotnetTestConnection? DotnetTestConnection => serviceProvider.GetService<DotnetTestConnection>();
|
||||
private IPushOnlyProtocol? PushOnlyProtocol => serviceProvider.GetService<IPushOnlyProtocol>();
|
||||
|
||||
public Task<int> RunAsync() => Task.FromResult(_returnValue);
|
||||
|
||||
public void Dispose() => DotnetTestConnection?.Dispose();
|
||||
public void Dispose() => PushOnlyProtocol?.Dispose();
|
||||
|
||||
#if NETCOREAPP
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (DotnetTestConnection is not null)
|
||||
if (PushOnlyProtocol is not null)
|
||||
{
|
||||
await DotnetTestConnection.DisposeAsync();
|
||||
await PushOnlyProtocol.DisposeAsync();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,7 @@ using Microsoft.Testing.Platform.Helpers;
|
|||
using Microsoft.Testing.Platform.Logging;
|
||||
using Microsoft.Testing.Platform.Messages;
|
||||
using Microsoft.Testing.Platform.OutputDevice;
|
||||
using Microsoft.Testing.Platform.ServerMode;
|
||||
using Microsoft.Testing.Platform.Services;
|
||||
using Microsoft.Testing.Platform.Telemetry;
|
||||
using Microsoft.Testing.Platform.TestHost;
|
||||
|
@ -17,7 +18,7 @@ internal abstract class CommonTestHost(ServiceProvider serviceProvider) : ITestH
|
|||
{
|
||||
public ServiceProvider ServiceProvider => serviceProvider;
|
||||
|
||||
protected DotnetTestConnection? DotnetTestConnection => ServiceProvider.GetService<DotnetTestConnection>();
|
||||
protected IPushOnlyProtocol? PushOnlyProtocol => ServiceProvider.GetService<IPushOnlyProtocol>();
|
||||
|
||||
protected abstract bool RunTestApplicationLifeCycleCallbacks { get; }
|
||||
|
||||
|
@ -28,18 +29,18 @@ internal abstract class CommonTestHost(ServiceProvider serviceProvider) : ITestH
|
|||
int exitCode;
|
||||
try
|
||||
{
|
||||
if (DotnetTestConnection is null || DotnetTestConnection?.IsConnected == false)
|
||||
if (PushOnlyProtocol is null || PushOnlyProtocol?.IsServerMode == false)
|
||||
{
|
||||
exitCode = await RunTestAppAsync(testApplicationCancellationToken);
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
RoslynDebug.Assert(DotnetTestConnection is not null);
|
||||
RoslynDebug.Assert(PushOnlyProtocol is not null);
|
||||
|
||||
ITestApplicationModuleInfo testApplicationModuleInfo = serviceProvider.GetTestApplicationModuleInfo();
|
||||
bool isDotnetTestHandshakeSuccessful = await DotnetTestConnection.DoHandshakeAsync(GetHostType());
|
||||
bool isValidProtocol = await PushOnlyProtocol.IsCompatibleProtocolAsync(GetHostType());
|
||||
|
||||
exitCode = isDotnetTestHandshakeSuccessful
|
||||
exitCode = isValidProtocol
|
||||
? await RunTestAppAsync(testApplicationCancellationToken)
|
||||
: ExitCodes.IncompatibleProtocolVersion;
|
||||
}
|
||||
|
@ -52,7 +53,7 @@ internal abstract class CommonTestHost(ServiceProvider serviceProvider) : ITestH
|
|||
{
|
||||
await DisposeServiceProviderAsync(ServiceProvider, isProcessShutdown: true);
|
||||
await DisposeHelper.DisposeAsync(ServiceProvider.GetService<FileLoggerProvider>());
|
||||
await DisposeHelper.DisposeAsync(DotnetTestConnection);
|
||||
await DisposeHelper.DisposeAsync(PushOnlyProtocol);
|
||||
await DisposeHelper.DisposeAsync(ServiceProvider.GetTestApplicationCancellationTokenSource());
|
||||
}
|
||||
|
||||
|
@ -99,7 +100,7 @@ internal abstract class CommonTestHost(ServiceProvider serviceProvider) : ITestH
|
|||
protected abstract Task<int> InternalRunAsync();
|
||||
|
||||
protected static async Task ExecuteRequestAsync(IPlatformOutputDevice outputDevice, ITestSessionContext testSessionInfo,
|
||||
ServiceProvider serviceProvider, BaseMessageBus baseMessageBus, ITestFramework testFramework, ClientInfo client)
|
||||
ServiceProvider serviceProvider, BaseMessageBus baseMessageBus, ITestFramework testFramework, TestHost.ClientInfo client)
|
||||
{
|
||||
CancellationToken testSessionCancellationToken = serviceProvider.GetTestSessionContext().CancellationToken;
|
||||
|
||||
|
|
|
@ -349,19 +349,19 @@ internal class TestHostBuilder(IFileSystem fileSystem, IRuntimeFeature runtimeFe
|
|||
return toolsTestHost;
|
||||
}
|
||||
|
||||
DotnetTestConnection dotnetTestConnection = new(commandLineHandler, processHandler, environment, _testApplicationModuleInfo, testApplicationCancellationTokenSource);
|
||||
bool isConnectedToDotnetTest = await dotnetTestConnection.TryConnectToDotnetTestPipeIfAvailableAsync();
|
||||
if (isConnectedToDotnetTest)
|
||||
var pushOnlyProtocol = new DotnetTestConnection(commandLineHandler, processHandler, environment, _testApplicationModuleInfo, testApplicationCancellationTokenSource);
|
||||
await pushOnlyProtocol.AfterCommonServiceSetupAsync();
|
||||
if (pushOnlyProtocol.IsServerMode)
|
||||
{
|
||||
serviceProvider.AddService(dotnetTestConnection);
|
||||
serviceProvider.AddService(pushOnlyProtocol);
|
||||
}
|
||||
|
||||
// If --help is invoked we return
|
||||
if (commandLineHandler.IsHelpInvoked())
|
||||
{
|
||||
if (isConnectedToDotnetTest)
|
||||
if (pushOnlyProtocol.IsServerMode)
|
||||
{
|
||||
await dotnetTestConnection.SendCommandLineOptionsToDotnetTestPipeAsync();
|
||||
await pushOnlyProtocol.HelpInvokedAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -625,12 +625,12 @@ internal class TestHostBuilder(IFileSystem fileSystem, IRuntimeFeature runtimeFe
|
|||
serviceProvider.AddService(testFrameworkBuilderData.MessageBusProxy);
|
||||
|
||||
// Check if we're connected to the dotnet test pipe
|
||||
DotnetTestDataConsumer? dotnetTestDataConsumer = null;
|
||||
DotnetTestConnection? dotnetTestConnection = serviceProvider.GetService<DotnetTestConnection>();
|
||||
IPushOnlyProtocolConsumer? pushOnlyProtocolDataConsumer = null;
|
||||
IPushOnlyProtocol? pushOnlyProtocol = serviceProvider.GetService<IPushOnlyProtocol>();
|
||||
|
||||
if (dotnetTestConnection?.IsConnected == true)
|
||||
if (pushOnlyProtocol?.IsServerMode == true)
|
||||
{
|
||||
dotnetTestDataConsumer = new DotnetTestDataConsumer(dotnetTestConnection, serviceProvider.GetEnvironment());
|
||||
pushOnlyProtocolDataConsumer = await pushOnlyProtocol.GetDataConsumerAsync();
|
||||
}
|
||||
|
||||
// Build and register "common non special" services - we need special treatment because extensions can start to log during the
|
||||
|
@ -703,9 +703,9 @@ internal class TestHostBuilder(IFileSystem fileSystem, IRuntimeFeature runtimeFe
|
|||
// Register the test session lifetime handlers container
|
||||
|
||||
// We register the lifetime handler if we're connected to the dotnet test pipe
|
||||
if (dotnetTestDataConsumer is not null)
|
||||
if (pushOnlyProtocolDataConsumer is not null)
|
||||
{
|
||||
testSessionLifetimeHandlers.Add(dotnetTestDataConsumer);
|
||||
testSessionLifetimeHandlers.Add(pushOnlyProtocolDataConsumer);
|
||||
}
|
||||
|
||||
TestSessionLifetimeHandlersContainer testSessionLifetimeHandlersContainer = new(testSessionLifetimeHandlers);
|
||||
|
@ -720,9 +720,9 @@ internal class TestHostBuilder(IFileSystem fileSystem, IRuntimeFeature runtimeFe
|
|||
await RegisterAsServiceOrConsumerOrBothAsync(testApplicationResult, serviceProvider, dataConsumersBuilder);
|
||||
|
||||
// We register the data consumer handler if we're connected to the dotnet test pipe
|
||||
if (dotnetTestDataConsumer is not null)
|
||||
if (pushOnlyProtocolDataConsumer is not null)
|
||||
{
|
||||
dataConsumersBuilder.Add(dotnetTestDataConsumer);
|
||||
dataConsumersBuilder.Add(pushOnlyProtocolDataConsumer);
|
||||
}
|
||||
|
||||
IDataConsumer[] dataConsumerServices = dataConsumersBuilder.ToArray();
|
||||
|
@ -740,8 +740,8 @@ internal class TestHostBuilder(IFileSystem fileSystem, IRuntimeFeature runtimeFe
|
|||
serviceProvider.GetAsyncMonitorFactory(),
|
||||
serviceProvider.GetEnvironment(),
|
||||
serviceProvider.GetTestApplicationProcessExitCode(),
|
||||
dotnetTestConnection,
|
||||
dotnetTestDataConsumer);
|
||||
pushOnlyProtocol,
|
||||
pushOnlyProtocolDataConsumer);
|
||||
await concreteMessageBusService.InitAsync();
|
||||
testFrameworkBuilderData.MessageBusProxy.SetBuiltMessageBus(concreteMessageBusService);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ using Microsoft.Testing.Platform.Logging;
|
|||
using Microsoft.Testing.Platform.Messages;
|
||||
using Microsoft.Testing.Platform.OutputDevice;
|
||||
using Microsoft.Testing.Platform.Resources;
|
||||
using Microsoft.Testing.Platform.ServerMode;
|
||||
using Microsoft.Testing.Platform.Services;
|
||||
using Microsoft.Testing.Platform.Telemetry;
|
||||
using Microsoft.Testing.Platform.TestHostControllers;
|
||||
|
@ -129,13 +130,13 @@ internal sealed class TestHostControllersTestHost : CommonTestHost, ITestHost, I
|
|||
dataConsumersBuilder.Add(dataConsumerDisplay);
|
||||
}
|
||||
|
||||
DotnetTestConnection? dotnetTestConnection = ServiceProvider.GetService<DotnetTestConnection>();
|
||||
IPushOnlyProtocol? pushOnlyProtocol = ServiceProvider.GetService<IPushOnlyProtocol>();
|
||||
// We register the DotnetTestDataConsumer as last to ensure that it will be the last one to consume the data.
|
||||
if (DotnetTestConnection?.IsConnected == true)
|
||||
if (pushOnlyProtocol?.IsServerMode == true)
|
||||
{
|
||||
RoslynDebug.Assert(dotnetTestConnection is not null);
|
||||
RoslynDebug.Assert(pushOnlyProtocol is not null);
|
||||
|
||||
dataConsumersBuilder.Add(new DotnetTestDataConsumer(dotnetTestConnection, ServiceProvider.GetEnvironment()));
|
||||
dataConsumersBuilder.Add(await pushOnlyProtocol.GetDataConsumerAsync());
|
||||
}
|
||||
|
||||
AsynchronousMessageBus concreteMessageBusService = new(
|
||||
|
|
|
@ -6,9 +6,9 @@ using Microsoft.Testing.Platform.Extensions.OutputDevice;
|
|||
using Microsoft.Testing.Platform.Extensions.TestFramework;
|
||||
using Microsoft.Testing.Platform.Extensions.TestHost;
|
||||
using Microsoft.Testing.Platform.Helpers;
|
||||
using Microsoft.Testing.Platform.IPC;
|
||||
using Microsoft.Testing.Platform.Logging;
|
||||
using Microsoft.Testing.Platform.OutputDevice;
|
||||
using Microsoft.Testing.Platform.ServerMode;
|
||||
using Microsoft.Testing.Platform.Services;
|
||||
|
||||
namespace Microsoft.Testing.Platform.Messages;
|
||||
|
@ -21,16 +21,16 @@ internal sealed class ListTestsMessageBus(
|
|||
IAsyncMonitorFactory asyncMonitorFactory,
|
||||
IEnvironment environment,
|
||||
ITestApplicationProcessExitCode testApplicationProcessExitCode,
|
||||
DotnetTestConnection? dotnetTestConnection,
|
||||
DotnetTestDataConsumer? dotnetTestDataConsumer) : BaseMessageBus, IMessageBus, IDisposable, IOutputDeviceDataProducer
|
||||
IPushOnlyProtocol? pushOnlyProtocol,
|
||||
IPushOnlyProtocolConsumer? pushOnlyProtocolConsumer) : BaseMessageBus, IMessageBus, IDisposable, IOutputDeviceDataProducer
|
||||
{
|
||||
private readonly ITestFramework _testFramework = testFramework;
|
||||
private readonly ITestApplicationCancellationTokenSource _testApplicationCancellationTokenSource = testApplicationCancellationTokenSource;
|
||||
private readonly IOutputDevice _outputDisplay = outputDisplay;
|
||||
private readonly IEnvironment _environment = environment;
|
||||
private readonly ITestApplicationProcessExitCode _testApplicationProcessExitCode = testApplicationProcessExitCode;
|
||||
private readonly DotnetTestConnection? _dotnetTestConnection = dotnetTestConnection;
|
||||
private readonly DotnetTestDataConsumer? _dotnetTestDataConsumer = dotnetTestDataConsumer;
|
||||
private readonly IPushOnlyProtocol? _pushOnlyProtocol = pushOnlyProtocol;
|
||||
private readonly IPushOnlyProtocolConsumer? _pushOnlyProtocolConsumer = pushOnlyProtocolConsumer;
|
||||
private readonly ILogger<ListTestsMessageBus> _logger = loggerFactory.CreateLogger<ListTestsMessageBus>();
|
||||
private readonly IAsyncMonitor _asyncMonitor = asyncMonitorFactory.Create();
|
||||
private bool _printTitle = true;
|
||||
|
@ -75,11 +75,11 @@ internal sealed class ListTestsMessageBus(
|
|||
return;
|
||||
}
|
||||
|
||||
if (_dotnetTestConnection?.IsConnected == true)
|
||||
if (_pushOnlyProtocol?.IsServerMode == true)
|
||||
{
|
||||
RoslynDebug.Assert(_dotnetTestDataConsumer is not null);
|
||||
RoslynDebug.Assert(_pushOnlyProtocolConsumer is not null);
|
||||
|
||||
await _dotnetTestDataConsumer.ConsumeAsync(dataProducer, data, _testApplicationCancellationTokenSource.CancellationToken);
|
||||
await _pushOnlyProtocolConsumer.ConsumeAsync(dataProducer, data, _testApplicationCancellationTokenSource.CancellationToken);
|
||||
}
|
||||
|
||||
// Send the information to the ITestApplicationProcessExitCode to correctly handle the ZeroTest case.
|
||||
|
|
|
@ -10,12 +10,13 @@ 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;
|
||||
|
||||
internal sealed class DotnetTestConnection :
|
||||
internal sealed class DotnetTestConnection : IPushOnlyProtocol,
|
||||
#if NETCOREAPP
|
||||
IAsyncDisposable,
|
||||
#endif
|
||||
|
@ -38,7 +39,14 @@ internal sealed class DotnetTestConnection :
|
|||
_cancellationTokenSource = cancellationTokenSource;
|
||||
}
|
||||
|
||||
public async Task<bool> TryConnectToDotnetTestPipeIfAvailableAsync()
|
||||
public bool IsServerMode => _dotnetTestPipeClient?.IsConnected == true;
|
||||
|
||||
public string Name => PlatformCommandLineProvider.DotnetTestCliProtocolName;
|
||||
|
||||
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.
|
||||
|
@ -57,14 +65,10 @@ internal sealed class DotnetTestConnection :
|
|||
_dotnetTestPipeClient.RegisterAllSerializers();
|
||||
|
||||
await _dotnetTestPipeClient.ConnectAsync(_cancellationTokenSource.CancellationToken);
|
||||
|
||||
return _dotnetTestPipeClient.IsConnected;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task SendCommandLineOptionsToDotnetTestPipeAsync()
|
||||
public async Task HelpInvokedAsync()
|
||||
{
|
||||
RoslynDebug.Assert(_dotnetTestPipeClient is not null);
|
||||
|
||||
|
@ -89,7 +93,7 @@ internal sealed class DotnetTestConnection :
|
|||
await _dotnetTestPipeClient.RequestReplyAsync<CommandLineOptionMessages, VoidResponse>(new CommandLineOptionMessages(_testApplicationModuleInfo.GetCurrentTestApplicationFullPath(), commandLineHelpOptions.OrderBy(option => option.Name).ToArray()), _cancellationTokenSource.CancellationToken);
|
||||
}
|
||||
|
||||
public async Task<bool> DoHandshakeAsync(string hostType)
|
||||
public async Task<bool> IsCompatibleProtocolAsync(string hostType)
|
||||
{
|
||||
RoslynDebug.Assert(_dotnetTestPipeClient is not null);
|
||||
|
||||
|
@ -138,8 +142,6 @@ internal sealed class DotnetTestConnection :
|
|||
}
|
||||
}
|
||||
|
||||
public bool IsConnected => _dotnetTestPipeClient?.IsConnected ?? false;
|
||||
|
||||
public void Dispose() => _dotnetTestPipeClient?.Dispose();
|
||||
|
||||
#if NETCOREAPP
|
|
@ -2,14 +2,14 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Microsoft.Testing.Platform.Extensions.Messages;
|
||||
using Microsoft.Testing.Platform.Extensions.TestHost;
|
||||
using Microsoft.Testing.Platform.Helpers;
|
||||
using Microsoft.Testing.Platform.IPC.Models;
|
||||
using Microsoft.Testing.Platform.ServerMode;
|
||||
using Microsoft.Testing.Platform.TestHost;
|
||||
|
||||
namespace Microsoft.Testing.Platform.IPC;
|
||||
|
||||
internal class DotnetTestDataConsumer : IDataConsumer, ITestSessionLifetimeHandler
|
||||
internal class DotnetTestDataConsumer : IPushOnlyProtocolConsumer
|
||||
{
|
||||
private readonly DotnetTestConnection? _dotnetTestConnection;
|
||||
private readonly IEnvironment _environment;
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.Testing.Platform.ServerMode;
|
||||
|
||||
internal interface IPushOnlyProtocol :
|
||||
#if NETCOREAPP
|
||||
IAsyncDisposable,
|
||||
#endif
|
||||
IDisposable
|
||||
{
|
||||
string Name { get; }
|
||||
|
||||
bool IsServerMode { get; }
|
||||
|
||||
Task AfterCommonServiceSetupAsync();
|
||||
|
||||
Task HelpInvokedAsync();
|
||||
|
||||
Task<bool> IsCompatibleProtocolAsync(string testHostType);
|
||||
|
||||
Task<IPushOnlyProtocolConsumer> GetDataConsumerAsync();
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// 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.Extensions.TestHost;
|
||||
|
||||
namespace Microsoft.Testing.Platform.ServerMode;
|
||||
|
||||
internal interface IPushOnlyProtocolConsumer : IDataConsumer, ITestSessionLifetimeHandler
|
||||
{
|
||||
}
|
Загрузка…
Ссылка в новой задаче