- Add RemovePassFromTrace, RemoveAuthTokenFromTrace, RemoveSecretsFromTrace static methods to ServerLogging (mirrors removeSecretsFromTrace/redact in server/client.go); uses same regex patterns as Go source to redact only the first match's value with [REDACTED]. - Update ClientConnection.RemoveSecretsFromTrace stub to delegate to ServerLogging.RemoveSecretsFromTrace. - Add 2 unit tests to SignalHandlerTests (T:2919 invalid command, T:2920 invalid PID); mark 14 process-injection/subprocess tests as deferred ([Fact(Skip=…)]). - Create ServerLoggerTests with 3 test methods (T:2020, T:2021, T:2022) covering NoPasswordsFromConnectTrace, RemovePassFromTrace (8 theory cases), RemoveAuthTokenFromTrace (8 theory cases). - DB: 3 log tests → complete, 2 signal tests → complete, 14 signal tests → deferred. - All 663 unit tests pass (was 645), 14 deferred skipped.
167 lines
7.3 KiB
C#
167 lines
7.3 KiB
C#
// Copyright 2012-2025 The NATS Authors
|
|
// Licensed under the Apache License, Version 2.0
|
|
|
|
using System.Runtime.InteropServices;
|
|
using Shouldly;
|
|
using ZB.MOM.NatsNet.Server.Internal;
|
|
|
|
namespace ZB.MOM.NatsNet.Server.Tests.Internal;
|
|
|
|
/// <summary>
|
|
/// Tests for SignalHandler — mirrors tests from server/signal_test.go.
|
|
/// </summary>
|
|
public class SignalHandlerTests
|
|
{
|
|
/// <summary>
|
|
/// Mirrors CommandToSignal mapping tests.
|
|
/// </summary>
|
|
[Fact] // T:3158
|
|
public void CommandToUnixSignal_ShouldMapCorrectly()
|
|
{
|
|
SignalHandler.CommandToUnixSignal(ServerCommand.Stop).ShouldBe(UnixSignal.SigKill);
|
|
SignalHandler.CommandToUnixSignal(ServerCommand.Quit).ShouldBe(UnixSignal.SigInt);
|
|
SignalHandler.CommandToUnixSignal(ServerCommand.Reopen).ShouldBe(UnixSignal.SigUsr1);
|
|
SignalHandler.CommandToUnixSignal(ServerCommand.Reload).ShouldBe(UnixSignal.SigHup);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Mirrors SetProcessName test.
|
|
/// </summary>
|
|
[Fact] // T:3155
|
|
public void SetProcessName_ShouldNotThrow()
|
|
{
|
|
Should.NotThrow(() => SignalHandler.SetProcessName("test-server"));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verify IsWindowsService returns false on non-Windows.
|
|
/// </summary>
|
|
[Fact] // T:3149
|
|
public void IsWindowsService_ShouldReturnFalse()
|
|
{
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
return; // Skip on Windows
|
|
SignalHandler.IsWindowsService().ShouldBeFalse();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Mirrors Run — service.go Run() simply invokes the start function.
|
|
/// </summary>
|
|
[Fact] // T:3148
|
|
public void Run_ShouldInvokeStartAction()
|
|
{
|
|
var called = false;
|
|
SignalHandler.Run(() => called = true);
|
|
called.ShouldBeTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// ProcessSignal with invalid PID expression should return error.
|
|
/// </summary>
|
|
[Fact] // T:3157
|
|
public void ProcessSignal_InvalidPid_ShouldReturnError()
|
|
{
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
return; // Skip on Windows
|
|
|
|
var err = SignalHandler.ProcessSignal(ServerCommand.Stop, "not-a-pid");
|
|
err.ShouldNotBeNull();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Tests ported from server/signal_test.go
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// <summary>
|
|
/// Mirrors TestProcessSignalInvalidCommand.
|
|
/// An out-of-range ServerCommand enum value is treated as an unknown signal
|
|
/// and ProcessSignal returns a non-null error.
|
|
/// </summary>
|
|
[Fact] // T:2919
|
|
public void ProcessSignalInvalidCommand_ShouldSucceed()
|
|
{
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
return; // Skip on Windows
|
|
|
|
var err = SignalHandler.ProcessSignal((ServerCommand)99, "123");
|
|
err.ShouldNotBeNull();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Mirrors TestProcessSignalInvalidPid.
|
|
/// A non-numeric PID string returns an error containing "invalid pid".
|
|
/// </summary>
|
|
[Fact] // T:2920
|
|
public void ProcessSignalInvalidPid_ShouldSucceed()
|
|
{
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
return; // Skip on Windows
|
|
|
|
var err = SignalHandler.ProcessSignal(ServerCommand.Stop, "abc");
|
|
err.ShouldNotBeNull();
|
|
err!.Message.ShouldContain("invalid pid");
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Deferred signal tests — require pgrep/kill injection or real OS process spawning.
|
|
// These cannot be unit-tested without refactoring SignalHandler to accept
|
|
// injectable pgrep/kill delegates (as the Go source does).
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// <summary>Mirrors TestProcessSignalMultipleProcesses — deferred: requires pgrep injection.</summary>
|
|
[Fact(Skip = "deferred: requires pgrep/kill injection")] // T:2913
|
|
public void ProcessSignalMultipleProcesses_ShouldSucceed() { }
|
|
|
|
/// <summary>Mirrors TestProcessSignalMultipleProcessesGlob — deferred: requires pgrep injection.</summary>
|
|
[Fact(Skip = "deferred: requires pgrep/kill injection")] // T:2914
|
|
public void ProcessSignalMultipleProcessesGlob_ShouldSucceed() { }
|
|
|
|
/// <summary>Mirrors TestProcessSignalMultipleProcessesGlobPartial — deferred: requires pgrep injection.</summary>
|
|
[Fact(Skip = "deferred: requires pgrep/kill injection")] // T:2915
|
|
public void ProcessSignalMultipleProcessesGlobPartial_ShouldSucceed() { }
|
|
|
|
/// <summary>Mirrors TestProcessSignalPgrepError — deferred: requires pgrep injection.</summary>
|
|
[Fact(Skip = "deferred: requires pgrep injection")] // T:2916
|
|
public void ProcessSignalPgrepError_ShouldSucceed() { }
|
|
|
|
/// <summary>Mirrors TestProcessSignalPgrepMangled — deferred: requires pgrep injection.</summary>
|
|
[Fact(Skip = "deferred: requires pgrep injection")] // T:2917
|
|
public void ProcessSignalPgrepMangled_ShouldSucceed() { }
|
|
|
|
/// <summary>Mirrors TestProcessSignalResolveSingleProcess — deferred: requires pgrep and kill injection.</summary>
|
|
[Fact(Skip = "deferred: requires pgrep/kill injection")] // T:2918
|
|
public void ProcessSignalResolveSingleProcess_ShouldSucceed() { }
|
|
|
|
/// <summary>Mirrors TestProcessSignalQuitProcess — deferred: requires kill injection.</summary>
|
|
[Fact(Skip = "deferred: requires kill injection")] // T:2921
|
|
public void ProcessSignalQuitProcess_ShouldSucceed() { }
|
|
|
|
/// <summary>Mirrors TestProcessSignalTermProcess — deferred: requires kill injection and commandTerm equivalent.</summary>
|
|
[Fact(Skip = "deferred: requires kill injection")] // T:2922
|
|
public void ProcessSignalTermProcess_ShouldSucceed() { }
|
|
|
|
/// <summary>Mirrors TestProcessSignalReopenProcess — deferred: requires kill injection.</summary>
|
|
[Fact(Skip = "deferred: requires kill injection")] // T:2923
|
|
public void ProcessSignalReopenProcess_ShouldSucceed() { }
|
|
|
|
/// <summary>Mirrors TestProcessSignalReloadProcess — deferred: requires kill injection.</summary>
|
|
[Fact(Skip = "deferred: requires kill injection")] // T:2924
|
|
public void ProcessSignalReloadProcess_ShouldSucceed() { }
|
|
|
|
/// <summary>Mirrors TestProcessSignalLameDuckMode — deferred: requires kill injection and commandLDMode equivalent.</summary>
|
|
[Fact(Skip = "deferred: requires kill injection")] // T:2925
|
|
public void ProcessSignalLameDuckMode_ShouldSucceed() { }
|
|
|
|
/// <summary>Mirrors TestProcessSignalTermDuringLameDuckMode — deferred: requires full server (RunServer) and real OS signal.</summary>
|
|
[Fact(Skip = "deferred: requires RunServer and real OS SIGTERM")] // T:2926
|
|
public void ProcessSignalTermDuringLameDuckMode_ShouldSucceed() { }
|
|
|
|
/// <summary>Mirrors TestSignalInterruptHasSuccessfulExit — deferred: requires spawning a subprocess to test exit code on SIGINT.</summary>
|
|
[Fact(Skip = "deferred: requires subprocess process spawning")] // T:2927
|
|
public void SignalInterruptHasSuccessfulExit_ShouldSucceed() { }
|
|
|
|
/// <summary>Mirrors TestSignalTermHasSuccessfulExit — deferred: requires spawning a subprocess to test exit code on SIGTERM.</summary>
|
|
[Fact(Skip = "deferred: requires subprocess process spawning")] // T:2928
|
|
public void SignalTermHasSuccessfulExit_ShouldSucceed() { }
|
|
}
|