Beispiel #1
0
        public static async Task <bool> TEST_ServerWorksIfClientDoesntAccept()
        {
            string serverName = ReverseServer.MakeServerAddress();

            Logger.logger.Log($"Server name is '{serverName}'");
            var server = new ReverseServer(serverName);

            await RunSubprocess(
                serverName : serverName,
                duringExecution : async(int pid) =>
            {
                var config = new SessionConfiguration(
                    circularBufferSizeMB: 10,
                    format: EventPipeSerializationFormat.NetTrace,
                    providers: new List <Provider> {
                    new Provider("Microsoft-DotNETCore-SampleProfiler")
                });
                Logger.logger.Log("Starting EventPipeSession over standard connection");
                using Stream stream = EventPipeClient.CollectTracing(pid, config, out var sessionId);
                Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}");
                using var source = new EventPipeEventSource(stream);
                Task readerTask  = Task.Run(() => source.Process());
                await Task.Delay(500);
                Logger.logger.Log("Stopping EventPipeSession over standard connection");
                EventPipeClient.StopTracing(pid, sessionId);
                await readerTask;
                Logger.logger.Log("Stopped EventPipeSession over standard connection");
            }
                );

            server.Shutdown();

            return(true);
        }
Beispiel #2
0
        public static async Task <bool> TEST_CanConnectServerAndClientAtSameTime()
        {
            bool   fSuccess   = true;
            string serverName = ReverseServer.MakeServerAddress();

            Logger.logger.Log($"Server name is '{serverName}'");
            var         server         = new ReverseServer(serverName);
            Task <bool> subprocessTask = Utils.RunSubprocess(
                currentAssembly: Assembly.GetExecutingAssembly(),
                environment: new Dictionary <string, string>
            {
                { Utils.DiagnosticsMonitorAddressEnvKey, serverName },
                { Utils.DiagnosticsMonitorPauseOnStartEnvKey, "0" }
            },
                duringExecution: async(int pid) =>
            {
                Task reverseTask = Task.Run(async() =>
                {
                    Logger.logger.Log($"Waiting for reverse connection");
                    Stream reverseStream = await server.AcceptAsync();
                    Logger.logger.Log("Got reverse connection");
                    IpcAdvertise advertise = IpcAdvertise.Parse(reverseStream);
                    Logger.logger.Log(advertise.ToString());
                });

                Task regularTask = Task.Run(async() =>
                {
                    var config = new SessionConfiguration(
                        circularBufferSizeMB: 1000,
                        format: EventPipeSerializationFormat.NetTrace,
                        providers: new List <Provider> {
                        new Provider("Microsoft-DotNETCore-SampleProfiler")
                    });
                    Logger.logger.Log("Starting EventPipeSession over standard connection");
                    using Stream stream = EventPipeClient.CollectTracing(pid, config, out var sessionId);
                    Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}");
                    using var source = new EventPipeEventSource(stream);
                    Task readerTask  = Task.Run(() => source.Process());
                    await Task.Delay(500);
                    Logger.logger.Log("Stopping EventPipeSession over standard connection");
                    EventPipeClient.StopTracing(pid, sessionId);
                    await readerTask;
                    Logger.logger.Log("Stopped EventPipeSession over standard connection");
                });

                await Task.WhenAll(reverseTask, regularTask);
            }
                );

            fSuccess &= await Utils.WaitTillTimeout(subprocessTask, TimeSpan.FromMinutes(1));

            server.Shutdown();

            return(fSuccess);
        }
Beispiel #3
0
        public static async Task <bool> TEST_ServerIsResilientToNoBufferAgent()
        {
            bool fSuccess = true;
            // N.B. - this test is only testing behavior on Windows since Unix Domain Sockets get their buffer size from the
            // system configuration and isn't set here.  Tests passing on Windows should indicate it would pass on Unix systems as well.
            string serverName = ReverseServer.MakeServerAddress();

            Logger.logger.Log($"Server name is '{serverName}'");
            var         server         = new ReverseServer(serverName, 0);
            Task <bool> subprocessTask = Utils.RunSubprocess(
                currentAssembly: Assembly.GetExecutingAssembly(),
                environment: new Dictionary <string, string>
            {
                { Utils.DiagnosticsMonitorAddressEnvKey, serverName },
                { Utils.DiagnosticsMonitorPauseOnStartEnvKey, "0" }
            },
                duringExecution: async(int pid) =>
            {
                var config = new SessionConfiguration(
                    circularBufferSizeMB: 10,
                    format: EventPipeSerializationFormat.NetTrace,
                    providers: new List <Provider> {
                    new Provider("Microsoft-DotNETCore-SampleProfiler")
                });
                Logger.logger.Log("Starting EventPipeSession over standard connection");
                using Stream stream = EventPipeClient.CollectTracing(pid, config, out var sessionId);
                Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}");
                using var source = new EventPipeEventSource(stream);
                Task readerTask  = Task.Run(() => source.Process());
                await Task.Delay(500);
                Logger.logger.Log("Stopping EventPipeSession over standard connection");
                EventPipeClient.StopTracing(pid, sessionId);
                await readerTask;
                Logger.logger.Log("Stopped EventPipeSession over standard connection");
            }
                );

            fSuccess &= await Utils.WaitTillTimeout(subprocessTask, TimeSpan.FromMinutes(1));

            server.Shutdown();

            return(fSuccess);
        }
Beispiel #4
0
        public static async Task <bool> TEST_ServerWorksIfClientDoesntAccept()
        {
            bool   fSuccess   = true;
            string serverName = ReverseServer.MakeServerAddress();

            Logger.logger.Log($"Server name is '{serverName}'");
            var         server         = new ReverseServer(serverName);
            Task <bool> subprocessTask = Utils.RunSubprocess(
                currentAssembly: Assembly.GetExecutingAssembly(),
                environment: new Dictionary <string, string>
            {
                { Utils.DiagnosticsMonitorAddressEnvKey, serverName },
                { Utils.DiagnosticsMonitorPauseOnStartEnvKey, "0" }
            },
                duringExecution: async(int pid) =>
            {
                var config = new SessionConfiguration(
                    circularBufferSizeMB: 10,
                    format: EventPipeSerializationFormat.NetTrace,
                    providers: new List <Provider> {
                    new Provider("Microsoft-DotNETCore-SampleProfiler")
                });
                Logger.logger.Log("Starting EventPipeSession over standard connection");
                using Stream stream = EventPipeClient.CollectTracing(pid, config, out var sessionId);
                Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}");
                using var source = new EventPipeEventSource(stream);
                Task readerTask  = Task.Run(() => source.Process());
                await Task.Delay(500);
                Logger.logger.Log("Stopping EventPipeSession over standard connection");
                EventPipeClient.StopTracing(pid, sessionId);
                await readerTask;
                Logger.logger.Log("Stopped EventPipeSession over standard connection");
            }
                );

            fSuccess &= await subprocessTask;
            server.Shutdown();

            return(true);
        }
Beispiel #5
0
        public static async Task <bool> TEST_ServerIsResilientToNoBufferAgent()
        {
            // N.B. - this test is only testing behavior on Windows since Unix Domain Sockets get their buffer size from the
            // system configuration and isn't set here.  Tests passing on Windows should indicate it would pass on Unix systems as well.
            string serverName = ReverseServer.MakeServerAddress();

            Logger.logger.Log($"Server name is '{serverName}'");
            var server = new ReverseServer(serverName, 0);

            await RunSubprocess(
                serverName : serverName,
                duringExecution : async(int pid) =>
            {
                var config = new SessionConfiguration(
                    circularBufferSizeMB: 10,
                    format: EventPipeSerializationFormat.NetTrace,
                    providers: new List <Provider> {
                    new Provider("Microsoft-DotNETCore-SampleProfiler")
                });
                Logger.logger.Log("Starting EventPipeSession over standard connection");
                using Stream stream = EventPipeClient.CollectTracing(pid, config, out var sessionId);
                Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}");
                using var source = new EventPipeEventSource(stream);
                Task readerTask  = Task.Run(() => source.Process());
                await Task.Delay(500);
                Logger.logger.Log("Stopping EventPipeSession over standard connection");
                EventPipeClient.StopTracing(pid, sessionId);
                await readerTask;
                Logger.logger.Log("Stopped EventPipeSession over standard connection");
            }
                );

            server.Shutdown();

            return(true);
        }
Beispiel #6
0
        public static async Task <bool> TEST_MultipleConnectPortsSuspend()
        {
            bool   fSuccess              = true;
            var    serverAndNames        = new List <(ReverseServer, string)>();
            string dotnetDiagnosticPorts = "";

            for (int i = 0; i < s_NumberOfPorts; i++)
            {
                string serverName = ReverseServer.MakeServerAddress();
                var    server     = new ReverseServer(serverName);
                Logger.logger.Log($"Server {i} address is '{serverName}'");
                serverAndNames.Add((server, serverName));
                dotnetDiagnosticPorts += $"{serverName};";
            }
            Logger.logger.Log($"export DOTNET_DiagnosticPorts={dotnetDiagnosticPorts}");

            var    advertisements = new List <IpcAdvertise>();
            Object sync           = new Object();

            int         subprocessId   = -1;
            Task <bool> subprocessTask = Utils.RunSubprocess(
                currentAssembly: Assembly.GetExecutingAssembly(),
                environment: new Dictionary <string, string>
            {
                { Utils.DiagnosticPortsEnvKey, dotnetDiagnosticPorts }
            },
                duringExecution: async(int pid) =>
            {
                subprocessId = pid;
                // Create an eventpipe session that will tell us when
                // the EEStartupStarted event happens.  This will tell us
                // the the runtime has been resumed.  This should only happen
                // AFTER all suspend ports have sent the resume command.
                var config = new SessionConfiguration(
                    circularBufferSizeMB: 1000,
                    format: EventPipeSerializationFormat.NetTrace,
                    providers: new List <Provider> {
                    new Provider("Microsoft-Windows-DotNETRuntimePrivate", 0x80000000, EventLevel.Verbose),
                    // workaround for https://github.com/dotnet/runtime/issues/44072 which happens because the
                    // above provider only sends 2 events and that can cause EventPipeEventSource (from TraceEvent)
                    // to not dispatch the events if the EventBlock is a size not divisible by 8 (the reading alignment in TraceEvent).
                    // Adding this provider keeps data flowing over the pipe so the reader doesn't get stuck waiting for data
                    // that won't come otherwise.
                    new Provider("Microsoft-DotNETCore-SampleProfiler")
                });
                Logger.logger.Log("Starting EventPipeSession over standard connection");
                using Stream eventStream = EventPipeClient.CollectTracing(pid, config, out var sessionId);
                Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}");

                var mre = new ManualResetEvent(false);

                Task readerTask = Task.Run(async() =>
                {
                    Logger.logger.Log($"Creating EventPipeEventSource");
                    using var source              = new EventPipeEventSource(eventStream);
                    var parser                    = new ClrPrivateTraceEventParser(source);
                    parser.StartupEEStartupStart += (eventData) => mre.Set();
                    Logger.logger.Log($"Created EventPipeEventSource");
                    Logger.logger.Log($"Starting processing");
                    await Task.Run(() => source.Process());
                    Logger.logger.Log($"Finished processing");
                });

                for (int i = 0; i < s_NumberOfPorts; i++)
                {
                    fSuccess &= !mre.WaitOne(0);
                    Logger.logger.Log($"Runtime HAS NOT resumed (expects: true): {fSuccess}");
                    var(server, _)         = serverAndNames[i];
                    int serverIndex        = i;
                    Stream stream          = await server.AcceptAsync();
                    IpcAdvertise advertise = IpcAdvertise.Parse(stream);
                    lock (sync)
                        advertisements.Add(advertise);
                    Logger.logger.Log($"Server {serverIndex} got advertise {advertise.ToString()}");

                    // send resume command on this connection
                    var message = new IpcMessage(0x04, 0x01);
                    Logger.logger.Log($"Port {serverIndex} sent: {message.ToString()}");
                    IpcMessage response = IpcClient.SendMessage(stream, message);
                    Logger.logger.Log($"Port {serverIndex} received: {response.ToString()}");
                }

                Logger.logger.Log($"Waiting on EEStartupStarted event");
                mre.WaitOne();
                Logger.logger.Log($"Saw EEStartupStarted Event");

                Logger.logger.Log($"Stopping EventPipeSession");
                EventPipeClient.StopTracing(pid, sessionId);
                await readerTask;
                Logger.logger.Log($"Stopped EventPipeSession");

                // runtime should have resumed now
                fSuccess &= mre.WaitOne(0);
                Logger.logger.Log($"Runtime HAS resumed (expects: true): {fSuccess}");
            }
                );


            fSuccess &= await subprocessTask;
            foreach (var(server, _) in serverAndNames)
            {
                server.Shutdown();
            }

            if (advertisements.Count() > 0)
            {
                Guid referenceCookie = advertisements[0].RuntimeInstanceCookie;
                foreach (var adv in advertisements)
                {
                    fSuccess &= (int)adv.ProcessId == subprocessId;
                    fSuccess &= adv.RuntimeInstanceCookie.Equals(referenceCookie);
                }
            }
            else
            {
                fSuccess &= false;
            }

            return(fSuccess);
        }
Beispiel #7
0
        public static async Task <bool> TEST_ConfigValidation()
        {
            // load the env var with good and bad configs.  Operation of good configs shouldn't be impeded by bad ones.
            // This test assumes all good configs have a server at the other end of the specified path.
            // Note that while a bad config might not crash the application, it may still degrade the process, e.g.,
            // a bad configuration that specifies at least a path, will most likely still be built and consume resources polling
            // for a server that won't exist.
            bool   fSuccess              = true;
            var    serverAndNames        = new List <(ReverseServer, string)>();
            string dotnetDiagnosticPorts = "";

            // TODO: Make sure these don't hang the test when the default is suspend
            dotnetDiagnosticPorts += ";;;;;;";                                                                         // empty configs shouldn't cause a crash
            dotnetDiagnosticPorts += "  ; ; ; ; ; ; ; ; ;";                                                            // whitespace only configs shouldn't cause a crash
            dotnetDiagnosticPorts += " , , , , , ,;,,,,,;;";                                                           // whitespace configs and empty tags with no path shouldn't cause a crash
            dotnetDiagnosticPorts += "connect,connect,connect,nosuspend,nosuspend,nosuspend,,,;";                      // path that is the same as a tag name and duplicate tags shouldn't cause a crash
            dotnetDiagnosticPorts += "SomeRandomPath,nosuspend,suspend,suspend,suspend,suspend;";                      // only the first tag from a pair is respected (this should result in a nosuspend port)
            dotnetDiagnosticPorts += "%%bad_Path^* fasdf----##2~~,bad tag$$@#@%_)*)@!#(&%.>,   , , , ,nosuspend,:::;"; // invalid path chars and tag chars won't cause a crash
            for (int i = 0; i < s_NumberOfPorts; i++)
            {
                string serverName = ReverseServer.MakeServerAddress();
                var    server     = new ReverseServer(serverName);
                Logger.logger.Log($"Server {i} address is '{serverName}'");
                serverAndNames.Add((server, serverName));
                dotnetDiagnosticPorts += $"{serverName},nosuspend;";
                dotnetDiagnosticPorts += $"{serverName},nosuspend;"; // duplicating port configs shouldn't cause issues
            }
            Logger.logger.Log($"export DOTNET_DiagnosticPorts={dotnetDiagnosticPorts}");
            var         advertisements = new List <IpcAdvertise>();
            Object      sync           = new Object();
            int         subprocessId   = -1;
            Task <bool> subprocessTask = Utils.RunSubprocess(
                currentAssembly: Assembly.GetExecutingAssembly(),
                environment: new Dictionary <string, string>
            {
                { Utils.DiagnosticPortsEnvKey, dotnetDiagnosticPorts }
            },
                duringExecution: async(int pid) =>
            {
                subprocessId = pid;
                var tasks    = new List <Task>();
                for (int i = 0; i < s_NumberOfPorts; i++)
                {
                    var(server, _)  = serverAndNames[i];
                    int serverIndex = i;
                    tasks.Add(Task.Run(async() =>
                    {
                        Stream stream          = await server.AcceptAsync();
                        IpcAdvertise advertise = IpcAdvertise.Parse(stream);
                        lock (sync)
                            advertisements.Add(advertise);
                        Logger.logger.Log($"Server {serverIndex} got advertise {advertise.ToString()}");
                    }));
                }

                await Task.WhenAll(tasks);
            }
                );

            fSuccess &= await subprocessTask;

            foreach (var(server, _) in serverAndNames)
            {
                server.Shutdown();
            }

            Guid referenceCookie = advertisements[0].RuntimeInstanceCookie;

            foreach (var adv in advertisements)
            {
                fSuccess &= (int)adv.ProcessId == subprocessId;
                fSuccess &= adv.RuntimeInstanceCookie.Equals(referenceCookie);
            }

            return(fSuccess);
        }
Beispiel #8
0
        public static async Task <bool> TEST_MultipleConnectPortsNoSuspend()
        {
            bool   fSuccess              = true;
            var    serverAndNames        = new List <(ReverseServer, string)>();
            string dotnetDiagnosticPorts = "";

            for (int i = 0; i < s_NumberOfPorts; i++)
            {
                string serverName = ReverseServer.MakeServerAddress();
                var    server     = new ReverseServer(serverName);
                Logger.logger.Log($"Server {i} address is '{serverName}'");
                serverAndNames.Add((server, serverName));
                dotnetDiagnosticPorts += $"{serverName},nosuspend;";
            }
            Logger.logger.Log($"export DOTNET_DiagnosticPorts={dotnetDiagnosticPorts}");
            var         advertisements = new List <IpcAdvertise>();
            Object      sync           = new Object();
            int         subprocessId   = -1;
            Task <bool> subprocessTask = Utils.RunSubprocess(
                currentAssembly: Assembly.GetExecutingAssembly(),
                environment: new Dictionary <string, string>
            {
                { Utils.DiagnosticPortsEnvKey, dotnetDiagnosticPorts }
            },
                duringExecution: async(int pid) =>
            {
                subprocessId = pid;
                var tasks    = new List <Task>();
                for (int i = 0; i < s_NumberOfPorts; i++)
                {
                    var(server, _)  = serverAndNames[i];
                    int serverIndex = i;
                    tasks.Add(Task.Run(async() =>
                    {
                        Stream stream          = await server.AcceptAsync();
                        IpcAdvertise advertise = IpcAdvertise.Parse(stream);
                        lock (sync)
                            advertisements.Add(advertise);
                        Logger.logger.Log($"Server {serverIndex} got advertise {advertise.ToString()}");
                    }));
                }

                await Task.WhenAll(tasks);
            }
                );

            fSuccess &= await subprocessTask;

            foreach (var(server, _) in serverAndNames)
            {
                server.Shutdown();
            }

            Guid referenceCookie = advertisements[0].RuntimeInstanceCookie;

            foreach (var adv in advertisements)
            {
                fSuccess &= (int)adv.ProcessId == subprocessId;
                fSuccess &= adv.RuntimeInstanceCookie.Equals(referenceCookie);
            }

            return(fSuccess);
        }