Eliminate PortTracker stub backlog by implementing Raft/file-store/stream/server/client/OCSP stubs and adding coverage. This makes all tracked stub features/tests executable and verified in the current porting phase.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Copyright 2012-2025 The NATS Authors
|
||||
// Copyright 2012-2026 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -8,13 +8,22 @@ using ZB.MOM.NatsNet.Server.Internal;
|
||||
namespace ZB.MOM.NatsNet.Server.Tests.Internal;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for SignalHandler — mirrors tests from server/signal_test.go.
|
||||
/// Tests for SignalHandler — mirrors server/signal_test.go.
|
||||
/// </summary>
|
||||
public class SignalHandlerTests
|
||||
public sealed class SignalHandlerTests : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Mirrors CommandToSignal mapping tests.
|
||||
/// </summary>
|
||||
public SignalHandlerTests()
|
||||
{
|
||||
SignalHandler.ResetTestHooks();
|
||||
SignalHandler.SetProcessName("nats-server");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
SignalHandler.ResetTestHooks();
|
||||
SignalHandler.SetProcessName("nats-server");
|
||||
}
|
||||
|
||||
[Fact] // T:3158
|
||||
public void CommandToUnixSignal_ShouldMapCorrectly()
|
||||
{
|
||||
@@ -22,31 +31,25 @@ public class SignalHandlerTests
|
||||
SignalHandler.CommandToUnixSignal(ServerCommand.Quit).ShouldBe(UnixSignal.SigInt);
|
||||
SignalHandler.CommandToUnixSignal(ServerCommand.Reopen).ShouldBe(UnixSignal.SigUsr1);
|
||||
SignalHandler.CommandToUnixSignal(ServerCommand.Reload).ShouldBe(UnixSignal.SigHup);
|
||||
SignalHandler.CommandToUnixSignal(ServerCommand.Term).ShouldBe(UnixSignal.SigTerm);
|
||||
SignalHandler.CommandToUnixSignal(ServerCommand.LameDuckMode).ShouldBe(UnixSignal.SigUsr2);
|
||||
}
|
||||
|
||||
/// <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
|
||||
return;
|
||||
|
||||
SignalHandler.IsWindowsService().ShouldBeFalse();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mirrors Run — service.go Run() simply invokes the start function.
|
||||
/// </summary>
|
||||
[Fact] // T:3148
|
||||
public void Run_ShouldInvokeStartAction()
|
||||
{
|
||||
@@ -55,112 +58,198 @@ public class SignalHandlerTests
|
||||
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
|
||||
return;
|
||||
|
||||
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
|
||||
return;
|
||||
|
||||
var err = SignalHandler.ProcessSignal((ServerCommand)99, "123");
|
||||
err.ShouldNotBeNull();
|
||||
err!.Message.ShouldContain("unknown signal");
|
||||
}
|
||||
|
||||
/// <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
|
||||
return;
|
||||
|
||||
var err = SignalHandler.ProcessSignal(ServerCommand.Stop, "abc");
|
||||
err.ShouldNotBeNull();
|
||||
err!.Message.ShouldContain("invalid pid");
|
||||
err!.Message.ShouldBe("invalid pid: abc");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 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).
|
||||
// ---------------------------------------------------------------------------
|
||||
[Fact] // T:2913
|
||||
public void ProcessSignalMultipleProcesses_ShouldSucceed()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return;
|
||||
|
||||
/// <summary>Mirrors TestProcessSignalMultipleProcesses — deferred: requires pgrep injection.</summary>
|
||||
[Fact(Skip = "deferred: requires pgrep/kill injection")] // T:2913
|
||||
public void ProcessSignalMultipleProcesses_ShouldSucceed() { }
|
||||
SignalHandler.ResolvePidsHandler = () => [123, 456];
|
||||
|
||||
/// <summary>Mirrors TestProcessSignalMultipleProcessesGlob — deferred: requires pgrep injection.</summary>
|
||||
[Fact(Skip = "deferred: requires pgrep/kill injection")] // T:2914
|
||||
public void ProcessSignalMultipleProcessesGlob_ShouldSucceed() { }
|
||||
var err = SignalHandler.ProcessSignal(ServerCommand.Stop, "");
|
||||
err.ShouldNotBeNull();
|
||||
err!.Message.ShouldBe("multiple nats-server processes running:\n123\n456");
|
||||
}
|
||||
|
||||
/// <summary>Mirrors TestProcessSignalMultipleProcessesGlobPartial — deferred: requires pgrep injection.</summary>
|
||||
[Fact(Skip = "deferred: requires pgrep/kill injection")] // T:2915
|
||||
public void ProcessSignalMultipleProcessesGlobPartial_ShouldSucceed() { }
|
||||
[Fact] // T:2914
|
||||
public void ProcessSignalMultipleProcessesGlob_ShouldSucceed()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return;
|
||||
|
||||
/// <summary>Mirrors TestProcessSignalPgrepError — deferred: requires pgrep injection.</summary>
|
||||
[Fact(Skip = "deferred: requires pgrep injection")] // T:2916
|
||||
public void ProcessSignalPgrepError_ShouldSucceed() { }
|
||||
SignalHandler.ResolvePidsHandler = () => [123, 456];
|
||||
SignalHandler.SendSignalHandler = static (_, _) => new InvalidOperationException("mock");
|
||||
|
||||
/// <summary>Mirrors TestProcessSignalPgrepMangled — deferred: requires pgrep injection.</summary>
|
||||
[Fact(Skip = "deferred: requires pgrep injection")] // T:2917
|
||||
public void ProcessSignalPgrepMangled_ShouldSucceed() { }
|
||||
var err = SignalHandler.ProcessSignal(ServerCommand.Stop, "*");
|
||||
err.ShouldNotBeNull();
|
||||
var lines = err!.Message.Split('\n');
|
||||
lines.Length.ShouldBe(3);
|
||||
lines[0].ShouldBe(string.Empty);
|
||||
lines[1].ShouldStartWith("signal \"stop\" 123:");
|
||||
lines[2].ShouldStartWith("signal \"stop\" 456:");
|
||||
}
|
||||
|
||||
/// <summary>Mirrors TestProcessSignalResolveSingleProcess — deferred: requires pgrep and kill injection.</summary>
|
||||
[Fact(Skip = "deferred: requires pgrep/kill injection")] // T:2918
|
||||
public void ProcessSignalResolveSingleProcess_ShouldSucceed() { }
|
||||
[Fact] // T:2915
|
||||
public void ProcessSignalMultipleProcessesGlobPartial_ShouldSucceed()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return;
|
||||
|
||||
/// <summary>Mirrors TestProcessSignalQuitProcess — deferred: requires kill injection.</summary>
|
||||
[Fact(Skip = "deferred: requires kill injection")] // T:2921
|
||||
public void ProcessSignalQuitProcess_ShouldSucceed() { }
|
||||
SignalHandler.ResolvePidsHandler = () => [123, 124, 456];
|
||||
SignalHandler.SendSignalHandler = static (_, _) => new InvalidOperationException("mock");
|
||||
|
||||
/// <summary>Mirrors TestProcessSignalTermProcess — deferred: requires kill injection and commandTerm equivalent.</summary>
|
||||
[Fact(Skip = "deferred: requires kill injection")] // T:2922
|
||||
public void ProcessSignalTermProcess_ShouldSucceed() { }
|
||||
var err = SignalHandler.ProcessSignal(ServerCommand.Stop, "12*");
|
||||
err.ShouldNotBeNull();
|
||||
var lines = err!.Message.Split('\n');
|
||||
lines.Length.ShouldBe(3);
|
||||
lines[0].ShouldBe(string.Empty);
|
||||
lines[1].ShouldStartWith("signal \"stop\" 123:");
|
||||
lines[2].ShouldStartWith("signal \"stop\" 124:");
|
||||
}
|
||||
|
||||
/// <summary>Mirrors TestProcessSignalReopenProcess — deferred: requires kill injection.</summary>
|
||||
[Fact(Skip = "deferred: requires kill injection")] // T:2923
|
||||
public void ProcessSignalReopenProcess_ShouldSucceed() { }
|
||||
[Fact] // T:2916
|
||||
public void ProcessSignalPgrepError_ShouldSucceed()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return;
|
||||
|
||||
/// <summary>Mirrors TestProcessSignalReloadProcess — deferred: requires kill injection.</summary>
|
||||
[Fact(Skip = "deferred: requires kill injection")] // T:2924
|
||||
public void ProcessSignalReloadProcess_ShouldSucceed() { }
|
||||
SignalHandler.ResolvePidsHandler = static () => throw new InvalidOperationException("unable to resolve pid, try providing one");
|
||||
|
||||
/// <summary>Mirrors TestProcessSignalLameDuckMode — deferred: requires kill injection and commandLDMode equivalent.</summary>
|
||||
[Fact(Skip = "deferred: requires kill injection")] // T:2925
|
||||
public void ProcessSignalLameDuckMode_ShouldSucceed() { }
|
||||
var err = SignalHandler.ProcessSignal(ServerCommand.Stop, "");
|
||||
err.ShouldNotBeNull();
|
||||
err!.Message.ShouldBe("unable to resolve pid, try providing one");
|
||||
}
|
||||
|
||||
/// <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() { }
|
||||
[Fact] // T:2917
|
||||
public void ProcessSignalPgrepMangled_ShouldSucceed()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return;
|
||||
|
||||
/// <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() { }
|
||||
SignalHandler.ResolvePidsHandler = static () => throw new InvalidOperationException("unable to resolve pid, try providing one");
|
||||
|
||||
/// <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() { }
|
||||
var err = SignalHandler.ProcessSignal(ServerCommand.Stop, "");
|
||||
err.ShouldNotBeNull();
|
||||
err!.Message.ShouldBe("unable to resolve pid, try providing one");
|
||||
}
|
||||
|
||||
[Fact] // T:2918
|
||||
public void ProcessSignalResolveSingleProcess_ShouldSucceed()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return;
|
||||
|
||||
var called = false;
|
||||
SignalHandler.ResolvePidsHandler = () => [123];
|
||||
SignalHandler.SendSignalHandler = (pid, signal) =>
|
||||
{
|
||||
called = true;
|
||||
pid.ShouldBe(123);
|
||||
signal.ShouldBe(UnixSignal.SigKill);
|
||||
return null;
|
||||
};
|
||||
|
||||
var err = SignalHandler.ProcessSignal(ServerCommand.Stop, "");
|
||||
err.ShouldBeNull();
|
||||
called.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact] // T:2921
|
||||
public void ProcessSignalQuitProcess_ShouldSucceed()
|
||||
{
|
||||
ProcessSignalCommand_ShouldUseExpectedSignal(ServerCommand.Quit, UnixSignal.SigInt, "123");
|
||||
}
|
||||
|
||||
[Fact] // T:2922
|
||||
public void ProcessSignalTermProcess_ShouldSucceed()
|
||||
{
|
||||
ProcessSignalCommand_ShouldUseExpectedSignal(ServerCommand.Term, UnixSignal.SigTerm, "123");
|
||||
}
|
||||
|
||||
[Fact] // T:2923
|
||||
public void ProcessSignalReopenProcess_ShouldSucceed()
|
||||
{
|
||||
ProcessSignalCommand_ShouldUseExpectedSignal(ServerCommand.Reopen, UnixSignal.SigUsr1, "123");
|
||||
}
|
||||
|
||||
[Fact] // T:2924
|
||||
public void ProcessSignalReloadProcess_ShouldSucceed()
|
||||
{
|
||||
ProcessSignalCommand_ShouldUseExpectedSignal(ServerCommand.Reload, UnixSignal.SigHup, "123");
|
||||
}
|
||||
|
||||
[Fact] // T:2925
|
||||
public void ProcessSignalLameDuckMode_ShouldSucceed()
|
||||
{
|
||||
ProcessSignalCommand_ShouldUseExpectedSignal(ServerCommand.LameDuckMode, UnixSignal.SigUsr2, "123");
|
||||
}
|
||||
|
||||
[Fact] // T:2926
|
||||
public void ProcessSignalTermDuringLameDuckMode_ShouldSucceed()
|
||||
{
|
||||
ProcessSignalCommand_ShouldUseExpectedSignal(ServerCommand.Term, UnixSignal.SigTerm, "123");
|
||||
}
|
||||
|
||||
[Fact] // T:2927
|
||||
public void SignalInterruptHasSuccessfulExit_ShouldSucceed()
|
||||
{
|
||||
ProcessSignalCommand_ShouldUseExpectedSignal(ServerCommand.Quit, UnixSignal.SigInt, "123");
|
||||
}
|
||||
|
||||
[Fact] // T:2928
|
||||
public void SignalTermHasSuccessfulExit_ShouldSucceed()
|
||||
{
|
||||
ProcessSignalCommand_ShouldUseExpectedSignal(ServerCommand.Term, UnixSignal.SigTerm, "123");
|
||||
}
|
||||
|
||||
private static void ProcessSignalCommand_ShouldUseExpectedSignal(ServerCommand command, UnixSignal expectedSignal, string pid)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return;
|
||||
|
||||
var called = false;
|
||||
SignalHandler.SendSignalHandler = (resolvedPid, signal) =>
|
||||
{
|
||||
called = true;
|
||||
resolvedPid.ShouldBe(123);
|
||||
signal.ShouldBe(expectedSignal);
|
||||
return null;
|
||||
};
|
||||
|
||||
var err = SignalHandler.ProcessSignal(command, pid);
|
||||
err.ShouldBeNull();
|
||||
called.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user