コード例 #1
0
        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);
        }
コード例 #2
0
 public void Reset()
 {
     if (_tcpServerEndpointInfo.Endpoint != null)
     {
         _tcpServer.RemoveConnection(_tcpServerEndpointInfo.RuntimeInstanceCookie);
         _tcpServerEndpointInfo = new IpcEndpointInfo();
     }
 }
コード例 #3
0
        /// <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;
            }));
        }
コード例 #4
0
        /// <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()}");
        }
コード例 #5
0
        /// <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}");
        }
コード例 #6
0
 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));
     }
 }
コード例 #7
0
        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();
        }
コード例 #8
0
        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}");
            }
        }
コード例 #9
0
        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}");
            }
        }
コード例 #10
0
        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());
        }
コード例 #11
0
        /// <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.");
        }
コード例 #12
0
        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);
        }
コード例 #13
0
 public static string ToTestString(this IpcEndpointInfo info)
 {
     return($"PID={info.ProcessId}, COOKIE={info.RuntimeInstanceCookie}");
 }