From 6289d317833502aeb20f5fdcea6add1474bf9f82 Mon Sep 17 00:00:00 2001 From: jburnett Date: Thu, 20 Nov 2025 17:02:46 -0500 Subject: [PATCH] Raise CCov to 91%; add tests, rm unused namespaces --- .../IP/Internal/NullExternalScopeProvider.cs | 4 +- .../IP/Internal/NullScope.cs | 2 + .../IP/UdpLoggerProcessor.cs | 10 +-- .../IP/UdpLoggerProvider.cs | 8 ++- .../IP/UdpLoggerProcessorTests.cs | 44 ++++++++++++ .../IP/UdpLoggerProviderTests.cs | 54 ++++++++++++--- .../IP/UdpLoggerTests.cs | 68 ++++++++++++++----- .../IP/Utils/UdpReceiver.cs | 18 ++++- Test.AMT.Extensions.System/ConvertTests.cs | 16 +++++ 9 files changed, 188 insertions(+), 36 deletions(-) create mode 100644 Test.AMT.Extensions.Logging/IP/UdpLoggerProcessorTests.cs diff --git a/AMT.Extensions.Logging/IP/Internal/NullExternalScopeProvider.cs b/AMT.Extensions.Logging/IP/Internal/NullExternalScopeProvider.cs index 9163a4d..6aac5ba 100644 --- a/AMT.Extensions.Logging/IP/Internal/NullExternalScopeProvider.cs +++ b/AMT.Extensions.Logging/IP/Internal/NullExternalScopeProvider.cs @@ -6,13 +6,15 @@ using Microsoft.Extensions.Logging; using System; +using System.Diagnostics.CodeAnalysis; namespace AMT.Extensions.Logging.IP { /// /// Scope provider that does nothing. /// - internal class NullExternalScopeProvider : IExternalScopeProvider + [ExcludeFromCodeCoverage] + public class NullExternalScopeProvider : IExternalScopeProvider { private NullExternalScopeProvider() { diff --git a/AMT.Extensions.Logging/IP/Internal/NullScope.cs b/AMT.Extensions.Logging/IP/Internal/NullScope.cs index 43525b5..ecefa1b 100644 --- a/AMT.Extensions.Logging/IP/Internal/NullScope.cs +++ b/AMT.Extensions.Logging/IP/Internal/NullScope.cs @@ -5,12 +5,14 @@ // due to it being internal access there. using System; +using System.Diagnostics.CodeAnalysis; namespace AMT.Extensions.Logging.IP { /// /// An empty scope without any logic /// + [ExcludeFromCodeCoverage] internal class NullScope : IDisposable { public static NullScope Instance { get; } = new NullScope(); diff --git a/AMT.Extensions.Logging/IP/UdpLoggerProcessor.cs b/AMT.Extensions.Logging/IP/UdpLoggerProcessor.cs index 335a490..0f0d7db 100644 --- a/AMT.Extensions.Logging/IP/UdpLoggerProcessor.cs +++ b/AMT.Extensions.Logging/IP/UdpLoggerProcessor.cs @@ -49,11 +49,7 @@ public virtual void EnqueueMessage(LogMessageEntry message) } // Adding is completed so just log the message - try - { - WriteMessage(message); - } - catch (Exception) { } + WriteMessage(message); } internal virtual void WriteMessage(LogMessageEntry entry) @@ -96,13 +92,17 @@ public void Dispose() _messageQueue.CompleteAdding(); _shutdown = true; + // Give the sender time to complete its tasks try { + // TODO: use a config value for timeout _outputThread.Join(1500); // with timeout in-case Console is locked by user input } catch (ThreadStateException) { } _udpSender.Dispose(); + // Clear any messages + _messageQueue.Dispose(); } #endregion IDisposable impl diff --git a/AMT.Extensions.Logging/IP/UdpLoggerProvider.cs b/AMT.Extensions.Logging/IP/UdpLoggerProvider.cs index 64e44c7..4c9019a 100644 --- a/AMT.Extensions.Logging/IP/UdpLoggerProvider.cs +++ b/AMT.Extensions.Logging/IP/UdpLoggerProvider.cs @@ -37,7 +37,13 @@ public ILogger CreateLogger(string category) public void SetScopeProvider(IExternalScopeProvider scopeProvider) { - _scopeProvider = scopeProvider; + if (null == scopeProvider) + { + _scopeProvider = NullExternalScopeProvider.Instance; + } else + { + _scopeProvider = scopeProvider; + } } #endregion ISupportExternalScope impl diff --git a/Test.AMT.Extensions.Logging/IP/UdpLoggerProcessorTests.cs b/Test.AMT.Extensions.Logging/IP/UdpLoggerProcessorTests.cs new file mode 100644 index 0000000..1b084a1 --- /dev/null +++ b/Test.AMT.Extensions.Logging/IP/UdpLoggerProcessorTests.cs @@ -0,0 +1,44 @@ +// Copyright (c) AltaModa Technologies. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Ext = AMT.Extensions.Logging.IP; +using FluentAssertions; +using System; +using System.Diagnostics.CodeAnalysis; +using Xunit; +using AMT.Extensions.Logging.IP; + + +namespace Test.AMT.Extensions.Logging.IP +{ + [ExcludeFromCodeCoverage] + public class UdpLoggerProcessorTests + { + + [Fact] + public void excp_on_null_options() + { + Action act = () => new Ext.UdpLoggerProcessor(null); + act.Should().Throw(); + } + + + #region IDisposable tests + + [Fact] + public void verify_disposable() + { + using (var proc = new Ext.UdpLoggerProcessor(_opts)) + { + var udpProv = new Ext.UdpLoggerProvider(_opts); + } + + } + + #endregion IDisposable tests + + + private static readonly UdpLoggerOptions _opts = new UdpLoggerOptions(); + } + +} diff --git a/Test.AMT.Extensions.Logging/IP/UdpLoggerProviderTests.cs b/Test.AMT.Extensions.Logging/IP/UdpLoggerProviderTests.cs index 7042e72..4460966 100644 --- a/Test.AMT.Extensions.Logging/IP/UdpLoggerProviderTests.cs +++ b/Test.AMT.Extensions.Logging/IP/UdpLoggerProviderTests.cs @@ -8,7 +8,6 @@ using Xunit; using AMT.Extensions.Logging.IP; using Microsoft.Extensions.Logging; -using System.Configuration.Provider; namespace Test.AMT.Extensions.Logging.IP @@ -17,6 +16,16 @@ namespace Test.AMT.Extensions.Logging.IP public class UdpLoggerProviderTests { + [Fact] + public void excp_on_null_category() + { + var provider = new Ext.UdpLoggerProvider(_opts); + Action act = () => provider.CreateLogger(null); + + act.Should().Throw(); + } + + [Fact] public void excp_on_null_options() { @@ -28,21 +37,48 @@ public void excp_on_null_options() #region ILoggerProvider tests [Fact] - public void foo() + public void can_log_to_category() { - var udpProv = new Ext.UdpLoggerProvider(_opts); + using (var udpProv = new Ext.UdpLoggerProvider(_opts)) + { + ILoggerProvider prov = udpProv as ILoggerProvider; + Assert.NotNull(prov); + + ILogger l = prov.CreateLogger("randomCategory"); + Assert.NotNull(l); + + l.LogInformation("using ILogger.LogInformation..."); + } + } + + #endregion ILoggerProvider tests - ILoggerProvider prov = udpProv as ILoggerProvider; - Assert.NotNull(prov); - ILogger l = prov.CreateLogger("randomCategory"); - Assert.NotNull(l); + #region ISupportExternalScope tests - l.LogInformation("using ILogger.LogInformation..."); + [Fact] + public void can_set_scope_provider() + { + var testEsps = new IExternalScopeProvider[] { + null, + NullExternalScopeProvider.Instance + }; + // TODO: consider disabling null + foreach (IExternalScopeProvider esp in testEsps ) { + using (var udpProv = new Ext.UdpLoggerProvider(_opts)) + { + udpProv.SetScopeProvider(esp); + ILogger l = udpProv.CreateLogger("randomCategory"); + Assert.NotNull(l); + + l.LogInformation("using ILogger.LogInformation..."); + } + } } - #endregion ILoggerProvider tests + #endregion ISupportExternalScope tests + private static readonly UdpLoggerOptions _opts = new UdpLoggerOptions(); diff --git a/Test.AMT.Extensions.Logging/IP/UdpLoggerTests.cs b/Test.AMT.Extensions.Logging/IP/UdpLoggerTests.cs index 6ddd528..19266f2 100644 --- a/Test.AMT.Extensions.Logging/IP/UdpLoggerTests.cs +++ b/Test.AMT.Extensions.Logging/IP/UdpLoggerTests.cs @@ -8,6 +8,8 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using Xunit; +using System.Net; +using System.Runtime.CompilerServices; namespace Test.AMT.Extensions.Logging.IP @@ -19,30 +21,31 @@ public class UdpLoggerTests [Fact] public void verify_each_loglevel() { - // Prepare listener to receive messages - var opts = new Ext.UdpLoggerOptions(); + // Prepare listener to receive messages; isolate port for message count + var opts = new Ext.UdpLoggerOptions(new IPEndPoint(IPAddress.Loopback, 17460)); using (_receiver = new UdpReceiver()) { _receiver.Start(opts); // Add options to provider before create logger - _provider = new Ext.UdpLoggerProvider(opts); - var logger = _provider.CreateLogger("test") as Ext.UdpLogger; - - // Log a message of each LogLevel - foreach (int level in _logLevels) - { - logger.Log((LogLevel)level, DEFAULT_EVENTID, DEFAULT_STATE, DEFAULT_EXCEPTION, setStringFormatter); + using (_provider = new Ext.UdpLoggerProvider(opts)) { + _logger = _provider.CreateLogger("test") as Ext.UdpLogger; + + // Log a message of each LogLevel + foreach (int level in _logLevels) + { + _logger.Log((LogLevel)level, DEFAULT_EVENTID, DEFAULT_STATE, DEFAULT_EXCEPTION, setStringFormatter); + } + + // Brief wait, then stop listener + System.Threading.Thread.Sleep(100); + _receiver.Stop(); + + // NOTE: RetrieveMessages returns a _consuming_ enumerator, so it can only be used once. + // LogLevel.None filtered, so reduce by 1. + _receiver.RetrieveMessages().Count().Should().Be(_logLevels.Length - 1); } - - // Brief wait, then stop listener - System.Threading.Thread.Sleep(100); - _receiver.Stop(); - - // NOTE: RetrieveMessages returns a _consuming_ enumerator, so it can only be used once. - // 2024.09.17, JB: previously None was filtered, but it seems that changed in logging fx. - _receiver.RetrieveMessages().Count().Should().Be(_logLevels.Length); } } @@ -119,6 +122,36 @@ public void verify_few_log_messages() } + [Fact] + public void verify_begin_scope() + { + // Prepare listener to receive messages + var opts = new Ext.UdpLoggerOptions(); + + using (_receiver = new UdpReceiver()) + { + _receiver.Start(opts); + + // Add options to provider before create logger + using (_provider = new Ext.UdpLoggerProvider(opts)) { + _logger = _provider.CreateLogger("test") as Ext.UdpLogger; + + using (_logger.BeginScope("SCOPE L1: ", null)) + { + _logger.Log(LogLevel.Trace, "some log message"); + using (_logger.BeginScope("SCOPE L2: ", null)) + { + _logger.Log(LogLevel.Trace, "some log message"); + } + + // TODO: confirm scope messages? + } + + } + } + } + + private LogLevel GetRandomLogLevel(bool excludeNone = true) { return (LogLevel)_randomizer.Next(0, excludeNone ? _logLevels.Length - 1 : _logLevels.Length); @@ -139,6 +172,7 @@ public UdpLoggerTests(Xunit.Abstractions.ITestOutputHelper outputHelper) private ILoggerProvider _provider; + private ILogger _logger; private UdpReceiver _receiver; private readonly object DEFAULT_STATE = "### Default state for testing ###"; private readonly object NULL_STATE = "[null-state]"; // TODO: use null; diff --git a/Test.AMT.Extensions.Logging/IP/Utils/UdpReceiver.cs b/Test.AMT.Extensions.Logging/IP/Utils/UdpReceiver.cs index 783a245..cd5e06f 100644 --- a/Test.AMT.Extensions.Logging/IP/Utils/UdpReceiver.cs +++ b/Test.AMT.Extensions.Logging/IP/Utils/UdpReceiver.cs @@ -17,7 +17,7 @@ namespace Test.AMT.Extensions.Logging.IP internal class UdpReceiver : IDisposable { private static int _maxQueuedMessages = 1024; - private readonly BlockingCollection _messageQueue = new BlockingCollection(_maxQueuedMessages); + private BlockingCollection _messageQueue = new BlockingCollection(_maxQueuedMessages); private bool _stopListener = false; private UdpClient _client; @@ -54,14 +54,27 @@ public void Stop() } + private static IEnumerable emptyList = new List(); public IEnumerable RetrieveMessages() { - return _messageQueue.GetConsumingEnumerable(); + if (_messageQueue.Count > 0) + { + return _messageQueue.GetConsumingEnumerable(); + } else + { + return emptyList; + } } #region IDisposable impl public void Dispose() { + // Drain the queue + if (_messageQueue != null) + { + _messageQueue = null; + } + if (null != _client) { _client.Close(); @@ -71,6 +84,5 @@ public void Dispose() } #endregion IDisposable impl - } } \ No newline at end of file diff --git a/Test.AMT.Extensions.System/ConvertTests.cs b/Test.AMT.Extensions.System/ConvertTests.cs index 5753b26..7c06c31 100644 --- a/Test.AMT.Extensions.System/ConvertTests.cs +++ b/Test.AMT.Extensions.System/ConvertTests.cs @@ -67,6 +67,14 @@ public void excp_on_null() }; act.Should().Throw(); + + + // Verify proper exception when encoded is null + act = () => { + Ext.Convert.FromBase64UrlString(null); + }; + + act.Should().Throw(); } @@ -79,6 +87,14 @@ public void excp_on_empty_string() }; act.Should().Throw(); + + + // Verify proper exception when encoded is empty + act = () => { + Ext.Convert.FromBase64UrlString(string.Empty); + }; + + act.Should().Throw(); }