private async Task VerifyWaitForConnection(IpcEndpointInfo info, bool useAsync, bool expectTimeout = false) { var shim = new IpcEndpointApiShim(info.Endpoint, useAsync); TimeSpan timeout = expectTimeout ? DefaultNegativeVerificationTimeout : DefaultPositiveVerificationTimeout; await shim.WaitForConnection(timeout, expectTimeout); }
public void Reset() { if (_tcpServerEndpointInfo.Endpoint != null) { _tcpServer.RemoveConnection(_tcpServerEndpointInfo.RuntimeInstanceCookie); _tcpServerEndpointInfo = new IpcEndpointInfo(); } }
/// <summary> /// Verifies that an event stream does provide events. /// </summary> private Task VerifyEventStreamProvidesEventsAsync(IpcEndpointInfo info, EventPipeSession session, int sessionNumber) { Assert.NotNull(session); Assert.NotNull(session.EventStream); return(Task.Run(async() => { _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Session #{sessionNumber} - Creating event source."); // This blocks for a while due to this bug: https://github.com/microsoft/perfview/issues/1172 using var eventSource = new EventPipeEventSource(session.EventStream); _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Session #{sessionNumber} - Setup event handlers."); // Create task completion source that is completed when any events are provided; cancel it if cancellation is requested var receivedEventsSource = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); using var cancellation = new CancellationTokenSource(TimeSpan.FromMinutes(1)); using var _ = cancellation.Token.Register(() => { if (receivedEventsSource.TrySetCanceled()) { _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Session #{sessionNumber} - Cancelled event processing."); } }); // Create continuation task that stops the session (which immediately stops event processing). Task stoppedProcessingTask = receivedEventsSource.Task .ContinueWith(_ => { _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Session #{sessionNumber} - Stopping session."); session.Stop(); }); // Signal task source when an event is received. Action <TraceEvent> allEventsHandler = _ => { if (receivedEventsSource.TrySetResult(null)) { _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Session #{sessionNumber} - Received an event and set result on completion source."); } }; _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Session #{sessionNumber} - Start processing events."); eventSource.Dynamic.All += allEventsHandler; eventSource.Process(); eventSource.Dynamic.All -= allEventsHandler; _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Session #{sessionNumber} - Stopped processing events."); // Wait on the task source to verify if it ran to completion or was cancelled. await receivedEventsSource.Task; _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Session #{sessionNumber} - Waiting for session to stop."); await stoppedProcessingTask; })); }
/// <summary> /// Verifies basic information on the endpoint info and that it matches the target process from the runner. /// </summary> private async Task VerifyEndpointInfo(TestRunner runner, IpcEndpointInfo info, bool expectValid = true) { _outputHelper.WriteLine($"Verifying connection information for process ID {runner.Pid}."); Assert.NotNull(runner); Assert.Equal(runner.Pid, info.ProcessId); Assert.NotEqual(Guid.Empty, info.RuntimeInstanceCookie); Assert.NotNull(info.Endpoint); await VerifyWaitForConnection(info, expectValid); _outputHelper.WriteLine($"Connection: {info.ToTestString()}"); }
/// <summary> /// Verifies basic information on the endpoint info and that it matches the target process from the runner. /// </summary> private async Task VerifyEndpointInfo(TestRunner runner, IpcEndpointInfo info, bool useAsync, bool expectTimeout = false) { _outputHelper.WriteLine($"Verifying connection information for process ID {runner.Pid}."); Assert.NotNull(runner); Assert.Equal(runner.Pid, info.ProcessId); Assert.NotEqual(Guid.Empty, info.RuntimeInstanceCookie); Assert.NotNull(info.Endpoint); await VerifyWaitForConnection(info, useAsync, expectTimeout); _outputHelper.WriteLine($"Connection: {info.DebuggerDisplay}"); }
private async Task VerifyWaitForConnection(IpcEndpointInfo info, bool expectValid = true) { using var connectionCancellation = new CancellationTokenSource(TimeSpan.FromSeconds(15)); if (expectValid) { await info.Endpoint.WaitForConnectionAsync(connectionCancellation.Token); } else { await Assert.ThrowsAsync <TaskCanceledException>( () => info.Endpoint.WaitForConnectionAsync(connectionCancellation.Token)); } }
protected TcpServerRouterFactory(string tcpServer, int runtimeTimeoutMs, ILogger logger) : base(logger) { _tcpServerAddress = IpcTcpSocketEndPoint.NormalizeTcpIpEndPoint(string.IsNullOrEmpty(tcpServer) ? "127.0.0.1:0" : tcpServer); _auto_shutdown = runtimeTimeoutMs != Timeout.Infinite; if (runtimeTimeoutMs != Timeout.Infinite) { RuntimeTimeoutMs = runtimeTimeoutMs; } _tcpServer = new ReversedDiagnosticsServer(_tcpServerAddress, enableTcpIpProtocol: true); _tcpServerEndpointInfo = new IpcEndpointInfo(); }
private void ResumeRuntime(IpcEndpointInfo info) { var client = new DiagnosticsClient(info.Endpoint); _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Resuming runtime instance."); try { client.ResumeRuntime(); _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Resumed successfully."); } catch (ServerErrorException ex) { // Runtime likely does not understand the ResumeRuntime command. _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: {ex.Message}"); } }
private async Task ResumeRuntime(IpcEndpointInfo info, bool useAsync) { var clientShim = new DiagnosticsClientApiShim(new DiagnosticsClient(info.Endpoint), useAsync); _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Resuming runtime instance."); try { await clientShim.ResumeRuntime(DefaultPositiveVerificationTimeout); _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Resumed successfully."); } catch (ServerErrorException ex) { // Runtime likely does not understand the ResumeRuntime command. _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: {ex.Message}"); } }
public async Task ReversedServerNoCreateTransportAfterDispose() { var transportCallback = new IpcServerTransportCallback(); int transportVersion = 0; TestRunner runner = null; try { await using var server = CreateReversedServer(out string transportName); server.TransportCallback = transportCallback; server.Start(); // Start client pointing to diagnostics server runner = StartTracee(transportName); // Get client connection IpcEndpointInfo info = await AcceptEndpointInfo(server, useAsync : true); await VerifyEndpointInfo(runner, info, useAsync : true); // There should not be any new endpoint infos await VerifyNoNewEndpointInfos(server, useAsync : true); ResumeRuntime(info); await VerifyWaitForConnection(info, useAsync : true); transportVersion = await transportCallback.GetStableTransportVersion(); // Server will be disposed } finally { _outputHelper.WriteLine("Stopping tracee."); runner?.Stop(); } // Check that the reversed server did not create a new server transport upon disposal. Assert.Equal(transportVersion, await transportCallback.GetStableTransportVersion()); }
/// <summary> /// Verifies that a client can handle multiple operations simultaneously. /// </summary> private async Task VerifySingleSession(IpcEndpointInfo info) { await VerifyWaitForConnection(info); var client = new DiagnosticsClient(info.Endpoint); _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Creating session #1."); var providers = new List <EventPipeProvider>(); providers.Add(new EventPipeProvider( "System.Runtime", EventLevel.Informational, 0, new Dictionary <string, string>() { { "EventCounterIntervalSec", "1" } })); using var session = client.StartEventPipeSession(providers); _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Verifying session produces events."); await VerifyEventStreamProvidesEventsAsync(info, session, 1); _outputHelper.WriteLine($"{info.RuntimeInstanceCookie}: Session verification complete."); }
public async Task <Stream> AcceptTcpStreamAsync(CancellationToken token) { Stream tcpServerStream; _logger?.LogDebug($"Waiting for a new tcp connection at endpoint \"{_tcpServerAddress}\"."); if (_tcpServerEndpointInfo.Endpoint == null) { using var acceptTimeoutTokenSource = new CancellationTokenSource(); using var acceptTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token, acceptTimeoutTokenSource.Token); try { // If no new runtime instance connects, timeout. acceptTimeoutTokenSource.CancelAfter(RuntimeTimeoutMs); _tcpServerEndpointInfo = await _tcpServer.AcceptAsync(acceptTokenSource.Token).ConfigureAwait(false); } catch (OperationCanceledException) { if (acceptTimeoutTokenSource.IsCancellationRequested) { _logger?.LogDebug("No runtime instance connected before timeout."); if (_auto_shutdown) { throw new RuntimeTimeoutException(RuntimeTimeoutMs); } } throw; } } using var connectTimeoutTokenSource = new CancellationTokenSource(); using var connectTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token, connectTimeoutTokenSource.Token); try { // Get next connected tcp stream. Should timeout if no endpoint appears within timeout. // If that happens we need to remove endpoint since it might indicate a unresponsive runtime. connectTimeoutTokenSource.CancelAfter(TcpServerTimeoutMs); tcpServerStream = await _tcpServerEndpointInfo.Endpoint.ConnectAsync(connectTokenSource.Token).ConfigureAwait(false); } catch (OperationCanceledException) { if (connectTimeoutTokenSource.IsCancellationRequested) { _logger?.LogDebug("No tcp stream connected before timeout."); throw new BackendStreamTimeoutException(TcpServerTimeoutMs); } throw; } if (tcpServerStream != null) { _logger?.LogDebug($"Successfully connected tcp stream, runtime id={RuntimeInstanceId}, runtime pid={RuntimeProcessId}."); } return(tcpServerStream); }
public static string ToTestString(this IpcEndpointInfo info) { return($"PID={info.ProcessId}, COOKIE={info.RuntimeInstanceCookie}"); }