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

@@ -8,6 +8,7 @@
<Project Path="tests/NATS.Server.Tests/NATS.Server.Tests.csproj" />
<Project Path="tests/NATS.Server.Transport.Tests/NATS.Server.Transport.Tests.csproj" />
<Project Path="tests/NATS.Server.Mqtt.Tests/NATS.Server.Mqtt.Tests.csproj" />
<Project Path="tests/NATS.Server.Gateways.Tests/NATS.Server.Gateways.Tests.csproj" />
<Project Path="tests/NATS.E2E.Tests/NATS.E2E.Tests.csproj" />
</Folder>
</Solution>

View File

@@ -3,6 +3,7 @@
<InternalsVisibleTo Include="NATS.Server.Tests" />
<InternalsVisibleTo Include="NATS.Server.Transport.Tests" />
<InternalsVisibleTo Include="NATS.Server.Mqtt.Tests" />
<InternalsVisibleTo Include="NATS.Server.Gateways.Tests" />
</ItemGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />

View File

@@ -1,6 +1,6 @@
using NATS.Server.Gateways;
namespace NATS.Server.Tests;
namespace NATS.Server.Gateways.Tests;
public class GatewayAdvancedRemapRuntimeTests
{

View File

@@ -1,6 +1,6 @@
using NATS.Server.Gateways;
namespace NATS.Server.Tests;
namespace NATS.Server.Gateways.Tests;
public class GatewayAdvancedSemanticsTests
{

View File

@@ -0,0 +1,45 @@
using Microsoft.Extensions.Logging.Abstractions;
using NATS.Server.Configuration;
namespace NATS.Server.Gateways.Tests;
public class GatewayLeafBootstrapTests
{
[Fact]
public async Task Server_bootstraps_gateway_and_leaf_managers_when_configured()
{
var options = new NatsOptions
{
Host = "127.0.0.1",
Port = 0,
Gateway = new GatewayOptions
{
Name = "G1",
Host = "127.0.0.1",
Port = 0,
},
LeafNode = new LeafNodeOptions
{
Host = "127.0.0.1",
Port = 0,
},
};
var server = new NatsServer(options, NullLoggerFactory.Instance);
var cts = new CancellationTokenSource();
_ = server.StartAsync(cts.Token);
await server.WaitForReadyAsync();
try
{
server.Stats.Gateways.ShouldBeGreaterThanOrEqualTo(0);
server.Stats.Leafs.ShouldBeGreaterThanOrEqualTo(0);
}
finally
{
await cts.CancelAsync();
server.Dispose();
cts.Dispose();
}
}
}

View File

@@ -3,8 +3,9 @@ using System.Net.Sockets;
using System.Text;
using Microsoft.Extensions.Logging.Abstractions;
using NATS.Server.Configuration;
using NATS.Server.TestUtilities;
namespace NATS.Server.Tests;
namespace NATS.Server.Gateways.Tests;
public class GatewayProtocolTests
{
@@ -87,7 +88,7 @@ internal sealed class GatewayFixture : IAsyncDisposable
_ = await ReadLineAsync(sock); // INFO
await sock.SendAsync(Encoding.ASCII.GetBytes($"CONNECT {{}}\r\nSUB {subject} 1\r\nPING\r\n"));
await ReadUntilAsync(sock, "PONG");
await SocketTestHelper.ReadUntilAsync(sock, "PONG");
}
public async Task PublishLocalClusterAsync(string subject, string payload)
@@ -100,11 +101,11 @@ internal sealed class GatewayFixture : IAsyncDisposable
_localPublisher = sock;
_ = await ReadLineAsync(sock); // INFO
await sock.SendAsync(Encoding.ASCII.GetBytes("CONNECT {}\r\nPING\r\n"));
await ReadUntilAsync(sock, "PONG");
await SocketTestHelper.ReadUntilAsync(sock, "PONG");
}
await sock.SendAsync(Encoding.ASCII.GetBytes($"PUB {subject} {payload.Length}\r\n{payload}\r\nPING\r\n"));
await ReadUntilAsync(sock, "PONG");
await SocketTestHelper.ReadUntilAsync(sock, "PONG");
}
public Task<string> ReadRemoteClusterMessageAsync()
@@ -112,7 +113,7 @@ internal sealed class GatewayFixture : IAsyncDisposable
if (_remoteSubscriber == null)
throw new InvalidOperationException("Remote subscriber was not initialized.");
return ReadUntilAsync(_remoteSubscriber, "MSG ");
return SocketTestHelper.ReadUntilAsync(_remoteSubscriber, "MSG ");
}
public async ValueTask DisposeAsync()
@@ -134,20 +135,4 @@ internal sealed class GatewayFixture : IAsyncDisposable
return Encoding.ASCII.GetString(buf, 0, n);
}
private static async Task<string> ReadUntilAsync(Socket sock, string expected)
{
var sb = new StringBuilder();
var buf = new byte[4096];
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
while (!sb.ToString().Contains(expected, StringComparison.Ordinal))
{
var n = await sock.ReceiveAsync(buf, SocketFlags.None, cts.Token);
if (n == 0)
break;
sb.Append(Encoding.ASCII.GetString(buf, 0, n));
}
return sb.ToString();
}
}

View File

@@ -5,7 +5,7 @@ using System.Net.Sockets;
using NATS.Server.Gateways;
using Shouldly;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
/// <summary>
/// Unit tests for account-specific subscription tracking on GatewayConnection.

View File

@@ -3,7 +3,7 @@ using NATS.Client.Core;
using NATS.Server.Auth;
using NATS.Server.Configuration;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
public class GatewayAccountScopedDeliveryTests
{

View File

@@ -2,7 +2,7 @@ using Microsoft.Extensions.Logging.Abstractions;
using NATS.Client.Core;
using NATS.Server.Configuration;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
/// <summary>
/// Ports TestGatewayBasic and TestGatewayDoesntSendBackToItself from

View File

@@ -2,7 +2,7 @@ using System.Text;
using NATS.Server.Gateways;
using Shouldly;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
// Go reference: gateway.go:90-120 — gateway protocol constants and command formatting.

View File

@@ -3,7 +3,7 @@ using NATS.Server.Configuration;
using NATS.Server.Gateways;
using NATS.Server.Monitoring;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
/// <summary>
/// Gateway configuration validation, options parsing, monitoring endpoint,

View File

@@ -1,7 +1,7 @@
using Microsoft.Extensions.Logging.Abstractions;
using NATS.Server.Configuration;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
public class GatewayConnectionDirectionParityBatch2Tests
{

View File

@@ -7,7 +7,7 @@ using NATS.Server.Configuration;
using NATS.Server.Gateways;
using NATS.Server.Subscriptions;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
/// <summary>
/// Gateway connection establishment, handshake, lifecycle, and reconnection tests.

View File

@@ -8,7 +8,7 @@ using NATS.Server.Configuration;
using NATS.Server.Gateways;
using NATS.Server.Subscriptions;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
/// <summary>
/// Gateway message forwarding, reply mapping, queue subscription delivery,

View File

@@ -7,7 +7,7 @@ using NATS.Server.Configuration;
using NATS.Server.Gateways;
using NATS.Server.Subscriptions;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
/// <summary>
/// Go-parity tests for gateway functionality, ported from

View File

@@ -4,7 +4,7 @@ using System.Text;
using NATS.Server.Gateways;
using NATS.Server.Subscriptions;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
public class GatewayInterestIdempotencyTests
{

View File

@@ -8,7 +8,7 @@ using NATS.Server.Configuration;
using NATS.Server.Gateways;
using NATS.Server.Subscriptions;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
/// <summary>
/// Gateway interest-only mode, account interest, subject interest propagation,

View File

@@ -1,7 +1,7 @@
using NATS.Server.Gateways;
using NATS.Server.Subscriptions;
namespace NATS.Server.Tests;
namespace NATS.Server.Gateways.Tests;
public class GatewayInterestOnlyParityTests
{

View File

@@ -1,7 +1,7 @@
// Go: gateway.go:100-150 (InterestMode enum), gateway.go:1500-1600 (switchToInterestOnlyMode)
using NATS.Server.Gateways;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
/// <summary>
/// Unit tests for GatewayInterestTracker — the per-connection interest mode state machine.

View File

@@ -3,7 +3,7 @@ using NATS.Server.Configuration;
using NATS.Server.Gateways;
using Shouldly;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
/// <summary>
/// Tests for GatewayReconnectPolicy and GatewayManager reconnection tracking.

View File

@@ -3,7 +3,7 @@ using NATS.Server.Configuration;
using NATS.Server.Gateways;
using Shouldly;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
/// <summary>
/// Tests for gateway connection registration and state tracking (Gap 11.7).

View File

@@ -1,6 +1,6 @@
using NATS.Server.Configuration;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
public class GatewayRemoteConfigParityBatch3Tests
{

View File

@@ -1,7 +1,7 @@
using NATS.Server.Configuration;
using NATS.Server.Gateways;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
public class GatewayReplyAndConfigParityBatch1Tests
{

View File

@@ -1,7 +1,7 @@
using Microsoft.Extensions.Logging.Abstractions;
using NATS.Server.Configuration;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
public class GatewayServerAccessorParityBatch4Tests
{

View File

@@ -3,7 +3,7 @@ using System.Net.Sockets;
using NATS.Server.Gateways;
using Shouldly;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
/// <summary>
/// Tests for queue group subscription tracking on GatewayConnection.

View File

@@ -1,7 +1,7 @@
using NATS.Server.Gateways;
using Shouldly;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
/// <summary>
/// Tests for the ReplyMapCache LRU cache with TTL expiration.

View File

@@ -1,6 +1,6 @@
using NATS.Server.Gateways;
namespace NATS.Server.Tests.Gateways;
namespace NATS.Server.Gateways.Tests.Gateways;
/// <summary>
/// Tests for the expanded ReplyMapper with hash support.

View File

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="NATS.Client.Core" />
<PackageReference Include="NSubstitute" />
<PackageReference Include="Shouldly" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
<Using Include="Shouldly" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\NATS.Server\NATS.Server.csproj" />
<ProjectReference Include="..\NATS.Server.TestUtilities\NATS.Server.TestUtilities.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,14 +0,0 @@
namespace NATS.Server.Tests;
public class GatewayLeafBootstrapTests
{
[Fact]
public async Task Server_bootstraps_gateway_and_leaf_managers_when_configured()
{
await using var server = await TestServerFactory.CreateWithGatewayAndLeafAsync();
await server.WaitForReadyAsync();
server.Stats.Gateways.ShouldBeGreaterThanOrEqualTo(0);
server.Stats.Leafs.ShouldBeGreaterThanOrEqualTo(0);
}
}