- NatsLogger.cs: INatsLogger interface (Noticef/Warnf/Fatalf/Errorf/Debugf/Tracef), ServerLogging state class with atomic debug/trace flags, rate-limited logging (RateLimitWarnf/RateLimitDebugf), error variants (Errors/Errorc/Errorsc), MicrosoftLoggerAdapter bridging to ILogger - SignalHandler.cs: ProcessSignal (Unix kill via Process), CommandToUnixSignal mapping (Stop→SIGKILL, Quit→SIGINT, Reopen→SIGUSR1, Reload→SIGHUP), ResolvePids via pgrep, SetProcessName, Run/IsWindowsService stubs for non-Windows - 11 tests (6 logger, 5 signal/service) - WASM/Windows signal stubs already n/a - All 141 tests pass (140 unit + 1 integration) - DB: features 368/3673 complete, tests 155/3257 complete (9.6% overall)
132 lines
4.6 KiB
C#
132 lines
4.6 KiB
C#
// Copyright 2012-2025 The NATS Authors
|
|
// Licensed under the Apache License, Version 2.0
|
|
|
|
using Shouldly;
|
|
using ZB.MOM.NatsNet.Server.Internal;
|
|
|
|
namespace ZB.MOM.NatsNet.Server.Tests.Internal;
|
|
|
|
/// <summary>
|
|
/// Tests for NatsLogger / ServerLogging — mirrors tests from server/log_test.go.
|
|
/// </summary>
|
|
public class NatsLoggerTests
|
|
{
|
|
private sealed class TestLogger : INatsLogger
|
|
{
|
|
public List<string> Messages { get; } = [];
|
|
|
|
public void Noticef(string format, params object[] args) => Messages.Add($"[INF] {string.Format(format, args)}");
|
|
public void Warnf(string format, params object[] args) => Messages.Add($"[WRN] {string.Format(format, args)}");
|
|
public void Fatalf(string format, params object[] args) => Messages.Add($"[FTL] {string.Format(format, args)}");
|
|
public void Errorf(string format, params object[] args) => Messages.Add($"[ERR] {string.Format(format, args)}");
|
|
public void Debugf(string format, params object[] args) => Messages.Add($"[DBG] {string.Format(format, args)}");
|
|
public void Tracef(string format, params object[] args) => Messages.Add($"[TRC] {string.Format(format, args)}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Mirrors TestSetLogger — verify logger assignment and atomic flags.
|
|
/// </summary>
|
|
[Fact] // T:2017
|
|
public void SetLogger_ShouldSetLoggerAndFlags()
|
|
{
|
|
var logging = new ServerLogging();
|
|
var testLog = new TestLogger();
|
|
|
|
logging.SetLoggerV2(testLog, true, true, false);
|
|
logging.IsDebug.ShouldBeTrue();
|
|
logging.IsTrace.ShouldBeTrue();
|
|
logging.IsTraceSysAcc.ShouldBeFalse();
|
|
logging.GetLogger().ShouldBe(testLog);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verify all log methods produce output when flags enabled.
|
|
/// </summary>
|
|
[Fact] // T:2017 (continuation)
|
|
public void AllLogMethods_ShouldProduceOutput()
|
|
{
|
|
var logging = new ServerLogging();
|
|
var testLog = new TestLogger();
|
|
logging.SetLoggerV2(testLog, true, true, false);
|
|
|
|
logging.Noticef("notice {0}", "test");
|
|
logging.Errorf("error {0}", "test");
|
|
logging.Warnf("warn {0}", "test");
|
|
logging.Fatalf("fatal {0}", "test");
|
|
logging.Debugf("debug {0}", "test");
|
|
logging.Tracef("trace {0}", "test");
|
|
|
|
testLog.Messages.Count.ShouldBe(6);
|
|
testLog.Messages[0].ShouldContain("[INF]");
|
|
testLog.Messages[1].ShouldContain("[ERR]");
|
|
testLog.Messages[4].ShouldContain("[DBG]");
|
|
testLog.Messages[5].ShouldContain("[TRC]");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Debug/Trace should not produce output when flags disabled.
|
|
/// </summary>
|
|
[Fact] // T:2017 (continuation)
|
|
public void DebugTrace_ShouldBeNoOpWhenDisabled()
|
|
{
|
|
var logging = new ServerLogging();
|
|
var testLog = new TestLogger();
|
|
logging.SetLoggerV2(testLog, false, false, false);
|
|
|
|
logging.Debugf("debug");
|
|
logging.Tracef("trace");
|
|
|
|
testLog.Messages.ShouldBeEmpty();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verify null logger does not throw.
|
|
/// </summary>
|
|
[Fact]
|
|
public void NullLogger_ShouldNotThrow()
|
|
{
|
|
var logging = new ServerLogging();
|
|
Should.NotThrow(() => logging.Noticef("test"));
|
|
Should.NotThrow(() => logging.Errorf("test"));
|
|
Should.NotThrow(() => logging.Debugf("test"));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verify rate-limited logging suppresses duplicate messages.
|
|
/// </summary>
|
|
[Fact] // T:2017 (RateLimitWarnf behavior)
|
|
public void RateLimitWarnf_ShouldSuppressDuplicates()
|
|
{
|
|
var logging = new ServerLogging();
|
|
var testLog = new TestLogger();
|
|
logging.SetLoggerV2(testLog, false, false, false);
|
|
|
|
logging.RateLimitWarnf("duplicate message");
|
|
logging.RateLimitWarnf("duplicate message");
|
|
logging.RateLimitWarnf("different message");
|
|
|
|
// Should only log 2 unique messages, not 3.
|
|
testLog.Messages.Count.ShouldBe(2);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verify Errors/Errorc/Errorsc convenience methods.
|
|
/// </summary>
|
|
[Fact]
|
|
public void ErrorVariants_ShouldFormatCorrectly()
|
|
{
|
|
var logging = new ServerLogging();
|
|
var testLog = new TestLogger();
|
|
logging.SetLoggerV2(testLog, false, false, false);
|
|
|
|
logging.Errors("client", new Exception("conn reset"));
|
|
logging.Errorc("TLS", new Exception("cert expired"));
|
|
logging.Errorsc("route", "cluster", new Exception("timeout"));
|
|
|
|
testLog.Messages.Count.ShouldBe(3);
|
|
testLog.Messages[0].ShouldContain("client - conn reset");
|
|
testLog.Messages[1].ShouldContain("TLS: cert expired");
|
|
testLog.Messages[2].ShouldContain("route - cluster: timeout");
|
|
}
|
|
}
|