From 8cb15774ab5299411ee427ddca9bfd627e604e6b Mon Sep 17 00:00:00 2001 From: ManickaP Date: Wed, 20 Apr 2022 18:04:16 +0200 Subject: [PATCH 1/2] TestEventListener --- .../tests/TestUtilities/TestEventListener.cs | 65 +++++++++++++++++++ .../tests/TestUtilities/TestUtilities.csproj | 2 + 2 files changed, 67 insertions(+) create mode 100644 src/libraries/Common/tests/TestUtilities/TestEventListener.cs diff --git a/src/libraries/Common/tests/TestUtilities/TestEventListener.cs b/src/libraries/Common/tests/TestUtilities/TestEventListener.cs new file mode 100644 index 00000000000000..7b29189350ad08 --- /dev/null +++ b/src/libraries/Common/tests/TestUtilities/TestEventListener.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics.Tracing; +using System.Text; +using Xunit.Abstractions; + +namespace TestUtilities; + +/// +/// Logging helper for tests. +/// Logs event source events into test output. +/// +public sealed class TestEventListener : EventListener +{ + private readonly ITestOutputHelper _output; + private readonly HashSet _sourceNames; + + // Until https://github.com/dotnet/runtime/issues/63979 is solved. + private List _eventSources = new List(); + + public TestEventListener(ITestOutputHelper output, params string[] sourceNames) + { + _output = output; + _sourceNames = new HashSet(sourceNames); + foreach (var eventSource in _eventSources) + { + OnEventSourceCreated(eventSource); + } + _eventSources = null; + } + + protected override void OnEventSourceCreated(EventSource eventSource) + { + // We're called from base ctor, just save the event source for later initialization. + if (_sourceNames is null) + { + _eventSources.Add(eventSource); + return; + } + + // Second pass called from our ctor, allow logging for specified source names. + if (_sourceNames.Contains(eventSource.Name)) + { + EnableEvents(eventSource, EventLevel.LogAlways); + } + } + + protected override void OnEventWritten(EventWrittenEventArgs eventData) + { + var sb = new StringBuilder().Append($"{eventData.TimeStamp:HH:mm:ss.fffffff}[{eventData.EventName}] "); + for (int i = 0; i < eventData.Payload?.Count; i++) + { + if (i > 0) + sb.Append(", "); + sb.Append(eventData.PayloadNames?[i]).Append(": ").Append(eventData.Payload[i]); + } + try + { + _output.WriteLine(sb.ToString()); + } + catch { } + } +} diff --git a/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj b/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj index 657ccf8f5ef224..ad1ab67e89c947 100644 --- a/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj +++ b/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj @@ -47,6 +47,8 @@ + + From 6266394dcd34ba6f94d3ce481be13cb06a1ca7b6 Mon Sep 17 00:00:00 2001 From: ManickaP Date: Thu, 21 Apr 2022 12:20:22 +0200 Subject: [PATCH 2/2] Feedback --- .../tests/TestUtilities/TestEventListener.cs | 76 +++++++++++++++---- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/src/libraries/Common/tests/TestUtilities/TestEventListener.cs b/src/libraries/Common/tests/TestUtilities/TestEventListener.cs index 7b29189350ad08..e41987992c80b6 100644 --- a/src/libraries/Common/tests/TestUtilities/TestEventListener.cs +++ b/src/libraries/Common/tests/TestUtilities/TestEventListener.cs @@ -1,8 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Collections.Generic; using System.Diagnostics.Tracing; +using System.IO; using System.Text; using Xunit.Abstractions; @@ -11,45 +13,87 @@ namespace TestUtilities; /// /// Logging helper for tests. /// Logs event source events into test output. +/// Example usage: +/// // Put the following line into your test method: +/// using var listener = new TestEventListener(_output, TestEventListener.NetworkingEvents); /// public sealed class TestEventListener : EventListener { - private readonly ITestOutputHelper _output; + public static string[] NetworkingEvents => new[] + { + "System.Net.Http", + "System.Net.NameResolution", + "System.Net.Sockets", + "System.Net.Security", + "System.Net.TestLogging", + "Private.InternalDiagnostics.System.Net.Http", + "Private.InternalDiagnostics.System.Net.NameResolution", + "Private.InternalDiagnostics.System.Net.Sockets", + "Private.InternalDiagnostics.System.Net.Security", + "Private.InternalDiagnostics.System.Net.Quic", + "Private.InternalDiagnostics.System.Net.Http.WinHttpHandler", + "Private.InternalDiagnostics.System.Net.HttpListener", + "Private.InternalDiagnostics.System.Net.Mail", + "Private.InternalDiagnostics.System.Net.NetworkInformation", + "Private.InternalDiagnostics.System.Net.Ping", + "Private.InternalDiagnostics.System.Net.Primitives", + "Private.InternalDiagnostics.System.Net.Requests", + }; + + private readonly Action _writeFunc; private readonly HashSet _sourceNames; // Until https://github.com/dotnet/runtime/issues/63979 is solved. private List _eventSources = new List(); + public TestEventListener(TextWriter output, params string[] sourceNames) + : this(str => output.WriteLine(str), sourceNames) + { } + public TestEventListener(ITestOutputHelper output, params string[] sourceNames) + : this(str => output.WriteLine(str), sourceNames) + { } + + public TestEventListener(Action writeFunc, params string[] sourceNames) { - _output = output; - _sourceNames = new HashSet(sourceNames); - foreach (var eventSource in _eventSources) + lock (this) { - OnEventSourceCreated(eventSource); + _writeFunc = writeFunc; + _sourceNames = new HashSet(sourceNames); + foreach (var eventSource in _eventSources) + { + OnEventSourceCreated(eventSource); + } + _eventSources = null; } - _eventSources = null; } protected override void OnEventSourceCreated(EventSource eventSource) { - // We're called from base ctor, just save the event source for later initialization. - if (_sourceNames is null) + lock (this) { - _eventSources.Add(eventSource); - return; - } + // We're called from base ctor, just save the event source for later initialization. + if (_sourceNames is null) + { + _eventSources.Add(eventSource); + return; + } - // Second pass called from our ctor, allow logging for specified source names. - if (_sourceNames.Contains(eventSource.Name)) - { - EnableEvents(eventSource, EventLevel.LogAlways); + // Second pass called from our ctor, allow logging for specified source names. + if (_sourceNames.Contains(eventSource.Name)) + { + EnableEvents(eventSource, EventLevel.LogAlways); + } } } protected override void OnEventWritten(EventWrittenEventArgs eventData) { +#if NETCOREAPP2_2_OR_GREATER || NETSTANDARD2_1_OR_GREATER var sb = new StringBuilder().Append($"{eventData.TimeStamp:HH:mm:ss.fffffff}[{eventData.EventName}] "); +#else + var sb = new StringBuilder().Append($"[{eventData.EventName}] "); +#endif for (int i = 0; i < eventData.Payload?.Count; i++) { if (i > 0) @@ -58,7 +102,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) } try { - _output.WriteLine(sb.ToString()); + _writeFunc(sb.ToString()); } catch { } }