refactor: extract NATS.Server.Gateways.Tests project

Move 25 gateway-related test files from NATS.Server.Tests into a
dedicated NATS.Server.Gateways.Tests project. Update namespaces,
replace private ReadUntilAsync with SocketTestHelper from TestUtilities,
inline TestServerFactory usage, add InternalsVisibleTo, and register
the project in the solution file. All 261 tests pass.
This commit is contained in:
Joseph Doherty
2026-03-12 15:10:50 -04:00
parent a6be5e11ed
commit 9972b74bc3
29 changed files with 101 additions and 58 deletions

View File

@@ -0,0 +1,99 @@
using System.Text;
using NATS.Server.Gateways;
using Shouldly;
namespace NATS.Server.Gateways.Tests.Gateways;
// Go reference: gateway.go:90-120 — gateway protocol constants and command formatting.
public class GatewayCommandTests
{
[Fact]
public void FormatSub_produces_correct_wire_format()
{
// Go reference: gateway.go — RS+ propagation, sendGatewaySubsToGateway
var bytes = GatewayCommands.FormatSub("$G", "orders.>");
var line = Encoding.UTF8.GetString(bytes);
line.ShouldBe("GS+ $G orders.>\r\n");
}
[Fact]
public void FormatUnsub_produces_correct_wire_format()
{
// Go reference: gateway.go — RS- propagation, sendGatewayUnsubToGateway
var bytes = GatewayCommands.FormatUnsub("$G", "orders.>");
var line = Encoding.UTF8.GetString(bytes);
line.ShouldBe("GS- $G orders.>\r\n");
}
[Fact]
public void FormatMode_optimistic_produces_O()
{
// Go reference: gateway.go — GMODE command, "O" = Optimistic mode
var bytes = GatewayCommands.FormatMode("$G", GatewayInterestMode.Optimistic);
var line = Encoding.UTF8.GetString(bytes);
line.ShouldBe("GMODE $G O\r\n");
}
[Fact]
public void FormatMode_interest_only_produces_I()
{
// Go reference: gateway.go — GMODE command, "I" = InterestOnly mode
var bytes = GatewayCommands.FormatMode("$G", GatewayInterestMode.InterestOnly);
var line = Encoding.UTF8.GetString(bytes);
line.ShouldBe("GMODE $G I\r\n");
}
[Fact]
public void ParseCommandType_identifies_sub()
{
// Go reference: gateway.go — processGatewayMsg dispatch on GS+
var line = Encoding.UTF8.GetBytes("GS+ ACC foo.bar\r\n");
var result = GatewayCommands.ParseCommandType(line);
result.ShouldBe(GatewayCommandType.Sub);
}
[Fact]
public void ParseCommandType_identifies_unsub()
{
// Go reference: gateway.go — processGatewayMsg dispatch on GS-
var line = Encoding.UTF8.GetBytes("GS- ACC foo.bar\r\n");
var result = GatewayCommands.ParseCommandType(line);
result.ShouldBe(GatewayCommandType.Unsub);
}
[Fact]
public void ParseCommandType_identifies_ping()
{
// Go reference: gateway.go — keepalive GPING command
var result = GatewayCommands.ParseCommandType(GatewayCommands.Ping);
result.ShouldBe(GatewayCommandType.Ping);
}
[Fact]
public void ParseCommandType_identifies_pong()
{
// Go reference: gateway.go — keepalive GPONG response
var result = GatewayCommands.ParseCommandType(GatewayCommands.Pong);
result.ShouldBe(GatewayCommandType.Pong);
}
[Fact]
public void ParseCommandType_returns_null_for_unknown()
{
// Unrecognized commands should return null for graceful handling
var line = Encoding.UTF8.GetBytes("UNKNOWN something\r\n");
var result = GatewayCommands.ParseCommandType(line);
result.ShouldBeNull();
}
[Fact]
public void Wire_format_constants_end_correctly()
{
// Go reference: gateway.go — all gateway commands use CRLF line endings
var crlf = new byte[] { (byte)'\r', (byte)'\n' };
GatewayCommands.Ping.TakeLast(2).ShouldBe(crlf);
GatewayCommands.Pong.TakeLast(2).ShouldBe(crlf);
GatewayCommands.Crlf.ShouldBe(crlf);
}
}