diff --git a/NatsDotNet.slnx b/NatsDotNet.slnx
index 5dc31f2..7fed1de 100644
--- a/NatsDotNet.slnx
+++ b/NatsDotNet.slnx
@@ -6,6 +6,7 @@
+
diff --git a/src/NATS.Server/NATS.Server.csproj b/src/NATS.Server/NATS.Server.csproj
index 8b5edc5..719e71b 100644
--- a/src/NATS.Server/NATS.Server.csproj
+++ b/src/NATS.Server/NATS.Server.csproj
@@ -1,6 +1,7 @@
+
diff --git a/tests/NATS.Server.TestUtilities/SocketTestHelper.cs b/tests/NATS.Server.TestUtilities/SocketTestHelper.cs
index fbb3ee6..867cd10 100644
--- a/tests/NATS.Server.TestUtilities/SocketTestHelper.cs
+++ b/tests/NATS.Server.TestUtilities/SocketTestHelper.cs
@@ -18,4 +18,18 @@ public static class SocketTestHelper
}
return sb.ToString();
}
+
+ public static async Task ReadUntilAsync(Stream stream, string expected, int timeoutMs = 5000)
+ {
+ using var cts = new CancellationTokenSource(timeoutMs);
+ var sb = new StringBuilder();
+ var buf = new byte[4096];
+ while (!sb.ToString().Contains(expected, StringComparison.Ordinal))
+ {
+ var n = await stream.ReadAsync(buf, cts.Token);
+ if (n == 0) break;
+ sb.Append(Encoding.ASCII.GetString(buf, 0, n));
+ }
+ return sb.ToString();
+ }
}
diff --git a/tests/NATS.Server.TestUtilities/TestCertHelper.cs b/tests/NATS.Server.TestUtilities/TestCertHelper.cs
new file mode 100644
index 0000000..c3acb55
--- /dev/null
+++ b/tests/NATS.Server.TestUtilities/TestCertHelper.cs
@@ -0,0 +1,31 @@
+using System.Net;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+
+namespace NATS.Server.TestUtilities;
+
+public static class TestCertHelper
+{
+ public static (string certPath, string keyPath) GenerateTestCertFiles()
+ {
+ var (cert, key) = GenerateTestCert();
+ var certPath = Path.GetTempFileName();
+ var keyPath = Path.GetTempFileName();
+ File.WriteAllText(certPath, cert.ExportCertificatePem());
+ File.WriteAllText(keyPath, key.ExportPkcs8PrivateKeyPem());
+ return (certPath, keyPath);
+ }
+
+ public static (X509Certificate2 cert, RSA key) GenerateTestCert()
+ {
+ var key = RSA.Create(2048);
+ var req = new CertificateRequest("CN=localhost", key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
+ req.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, false));
+ var sanBuilder = new SubjectAlternativeNameBuilder();
+ sanBuilder.AddIpAddress(IPAddress.Loopback);
+ sanBuilder.AddDnsName("localhost");
+ req.CertificateExtensions.Add(sanBuilder.Build());
+ var cert = req.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(1));
+ return (cert, key);
+ }
+}
diff --git a/tests/NATS.Server.Tests/MonitorTests.cs b/tests/NATS.Server.Tests/MonitorTests.cs
index bb1356a..0993c41 100644
--- a/tests/NATS.Server.Tests/MonitorTests.cs
+++ b/tests/NATS.Server.Tests/MonitorTests.cs
@@ -5,6 +5,7 @@ using System.Net.Sockets;
using System.Text;
using Microsoft.Extensions.Logging.Abstractions;
using NATS.Server.Monitoring;
+using NATS.Server.TestUtilities;
namespace NATS.Server.Tests;
@@ -310,7 +311,7 @@ public class MonitorTlsTests : IAsyncLifetime
{
_natsPort = GetFreePort();
_monitorPort = GetFreePort();
- (_certPath, _keyPath) = TlsHelperTests.GenerateTestCertFiles();
+ (_certPath, _keyPath) = TestCertHelper.GenerateTestCertFiles();
_server = new NatsServer(
new NatsOptions
{
diff --git a/tests/NATS.Server.Tests/MsgTraceGoParityTests.cs b/tests/NATS.Server.Tests/MsgTraceGoParityTests.cs
index 41afc82..00aa7e7 100644
--- a/tests/NATS.Server.Tests/MsgTraceGoParityTests.cs
+++ b/tests/NATS.Server.Tests/MsgTraceGoParityTests.cs
@@ -15,6 +15,7 @@ using NATS.Server;
using NATS.Server.Auth;
using NATS.Server.Monitoring;
using NATS.Server.Protocol;
+using NATS.Server.TestUtilities;
namespace NATS.Server.Tests;
@@ -784,7 +785,7 @@ public class MsgTraceGoParityTests : IAsyncLifetime
public async Task ClosedConns_tls_handshake_close_reason_tracked()
{
// Go: TestClosedTLSHandshake (closed_conns_test.go:247)
- var (certPath, keyPath) = TlsHelperTests.GenerateTestCertFiles();
+ var (certPath, keyPath) = TestCertHelper.GenerateTestCertFiles();
try
{
var port = GetFreePort();
diff --git a/tests/NATS.Server.Tests/IO/AdaptiveReadBufferShortReadTests.cs b/tests/NATS.Server.Transport.Tests/IO/AdaptiveReadBufferShortReadTests.cs
similarity index 99%
rename from tests/NATS.Server.Tests/IO/AdaptiveReadBufferShortReadTests.cs
rename to tests/NATS.Server.Transport.Tests/IO/AdaptiveReadBufferShortReadTests.cs
index 658e6ac..ea0f387 100644
--- a/tests/NATS.Server.Tests/IO/AdaptiveReadBufferShortReadTests.cs
+++ b/tests/NATS.Server.Transport.Tests/IO/AdaptiveReadBufferShortReadTests.cs
@@ -1,7 +1,7 @@
using NATS.Server.IO;
using Shouldly;
-namespace NATS.Server.Tests.IO;
+namespace NATS.Server.Transport.Tests.IO;
///
/// Tests for the consecutive short-read counter in AdaptiveReadBuffer.
diff --git a/tests/NATS.Server.Tests/IO/AdaptiveReadBufferTests.cs b/tests/NATS.Server.Transport.Tests/IO/AdaptiveReadBufferTests.cs
similarity index 91%
rename from tests/NATS.Server.Tests/IO/AdaptiveReadBufferTests.cs
rename to tests/NATS.Server.Transport.Tests/IO/AdaptiveReadBufferTests.cs
index 945dc64..64a881e 100644
--- a/tests/NATS.Server.Tests/IO/AdaptiveReadBufferTests.cs
+++ b/tests/NATS.Server.Transport.Tests/IO/AdaptiveReadBufferTests.cs
@@ -1,6 +1,6 @@
using NATS.Server.IO;
-namespace NATS.Server.Tests;
+namespace NATS.Server.Transport.Tests;
public class AdaptiveReadBufferTests
{
diff --git a/tests/NATS.Server.Tests/IO/DynamicBufferPoolTests.cs b/tests/NATS.Server.Transport.Tests/IO/DynamicBufferPoolTests.cs
similarity index 99%
rename from tests/NATS.Server.Tests/IO/DynamicBufferPoolTests.cs
rename to tests/NATS.Server.Transport.Tests/IO/DynamicBufferPoolTests.cs
index 92ca8fd..fc3af5f 100644
--- a/tests/NATS.Server.Tests/IO/DynamicBufferPoolTests.cs
+++ b/tests/NATS.Server.Transport.Tests/IO/DynamicBufferPoolTests.cs
@@ -4,7 +4,7 @@ using Shouldly;
// Go reference: client.go — dynamic buffer sizing and broadcast flush coalescing for fan-out.
-namespace NATS.Server.Tests.IO;
+namespace NATS.Server.Transport.Tests.IO;
public class DynamicBufferPoolTests
{
diff --git a/tests/NATS.Server.Tests/IO/OutboundBufferPoolTests.cs b/tests/NATS.Server.Transport.Tests/IO/OutboundBufferPoolTests.cs
similarity index 91%
rename from tests/NATS.Server.Tests/IO/OutboundBufferPoolTests.cs
rename to tests/NATS.Server.Transport.Tests/IO/OutboundBufferPoolTests.cs
index e5a0b23..66fc325 100644
--- a/tests/NATS.Server.Tests/IO/OutboundBufferPoolTests.cs
+++ b/tests/NATS.Server.Transport.Tests/IO/OutboundBufferPoolTests.cs
@@ -1,6 +1,6 @@
using NATS.Server.IO;
-namespace NATS.Server.Tests;
+namespace NATS.Server.Transport.Tests;
public class OutboundBufferPoolTests
{
diff --git a/tests/NATS.Server.Transport.Tests/NATS.Server.Transport.Tests.csproj b/tests/NATS.Server.Transport.Tests/NATS.Server.Transport.Tests.csproj
new file mode 100644
index 0000000..da6c6f1
--- /dev/null
+++ b/tests/NATS.Server.Transport.Tests/NATS.Server.Transport.Tests.csproj
@@ -0,0 +1,26 @@
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/NATS.Server.Tests/Networking/NetworkingGoParityTests.cs b/tests/NATS.Server.Transport.Tests/Networking/NetworkingGoParityTests.cs
similarity index 91%
rename from tests/NATS.Server.Tests/Networking/NetworkingGoParityTests.cs
rename to tests/NATS.Server.Transport.Tests/Networking/NetworkingGoParityTests.cs
index bd72983..cda7cff 100644
--- a/tests/NATS.Server.Tests/Networking/NetworkingGoParityTests.cs
+++ b/tests/NATS.Server.Transport.Tests/Networking/NetworkingGoParityTests.cs
@@ -10,6 +10,7 @@ using NATS.Server.Gateways;
using NATS.Server.LeafNodes;
using NATS.Server.Routes;
using NATS.Server.Subscriptions;
+using NATS.Server.TestUtilities;
namespace NATS.Server.Tests.Networking;
@@ -177,9 +178,7 @@ public class NetworkingGoParityTests
await using var sub = await conn.SubscribeCoreAsync("gw.interest.test");
await conn.PingAsync();
- using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!timeout.IsCancellationRequested && !fixture.Local.HasRemoteInterest("gw.interest.test"))
- await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
+ await PollHelper.WaitUntilAsync(() => fixture.Local.HasRemoteInterest("gw.interest.test"));
fixture.Local.HasRemoteInterest("gw.interest.test").ShouldBeTrue();
}
@@ -204,9 +203,7 @@ public class NetworkingGoParityTests
await using var sub = await remoteConn.SubscribeCoreAsync("gw.fwd.test");
await remoteConn.PingAsync();
- using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!timeout.IsCancellationRequested && !fixture.Local.HasRemoteInterest("gw.fwd.test"))
- await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
+ await PollHelper.WaitUntilAsync(() => fixture.Local.HasRemoteInterest("gw.fwd.test"));
await localConn.PublishAsync("gw.fwd.test", "gateway-msg");
@@ -229,18 +226,14 @@ public class NetworkingGoParityTests
var sub = await conn.SubscribeCoreAsync("gw.unsub.test");
await conn.PingAsync();
- using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!timeout.IsCancellationRequested && !fixture.Local.HasRemoteInterest("gw.unsub.test"))
- await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
+ await PollHelper.WaitUntilAsync(() => fixture.Local.HasRemoteInterest("gw.unsub.test"));
fixture.Local.HasRemoteInterest("gw.unsub.test").ShouldBeTrue();
await sub.DisposeAsync();
await conn.PingAsync();
- using var unsTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!unsTimeout.IsCancellationRequested && fixture.Local.HasRemoteInterest("gw.unsub.test"))
- await Task.Delay(50, unsTimeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
+ await PollHelper.WaitUntilAsync(() => !(fixture.Local.HasRemoteInterest("gw.unsub.test")));
fixture.Local.HasRemoteInterest("gw.unsub.test").ShouldBeFalse();
}
@@ -260,9 +253,7 @@ public class NetworkingGoParityTests
await using var sub = await conn.SubscribeCoreAsync("gw.wild.>");
await conn.PingAsync();
- using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!timeout.IsCancellationRequested && !fixture.Local.HasRemoteInterest("gw.wild.test"))
- await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
+ await PollHelper.WaitUntilAsync(() => fixture.Local.HasRemoteInterest("gw.wild.test"));
fixture.Local.HasRemoteInterest("gw.wild.test").ShouldBeTrue();
fixture.Local.HasRemoteInterest("gw.wild.deep.nested").ShouldBeTrue();
@@ -410,9 +401,7 @@ public class NetworkingGoParityTests
try
{
- using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!timeout.IsCancellationRequested && serverA.Stats.Routes < 3)
- await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
+ await PollHelper.WaitUntilAsync(() => !(serverA.Stats.Routes < 3));
serverA.Stats.Routes.ShouldBeGreaterThanOrEqualTo(3);
}
@@ -488,9 +477,7 @@ public class NetworkingGoParityTests
try
{
- using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!timeout.IsCancellationRequested && serverA.Stats.Routes < 3)
- await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
+ await PollHelper.WaitUntilAsync(() => !(serverA.Stats.Routes < 3));
await using var conn = new NatsConnection(new NatsOpts
{
@@ -501,9 +488,7 @@ public class NetworkingGoParityTests
await using var sub = await conn.SubscribeCoreAsync("route.sub.test");
await conn.PingAsync();
- using var interest = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!interest.IsCancellationRequested && !serverA.HasRemoteInterest("route.sub.test"))
- await Task.Delay(50, interest.Token).ContinueWith(_ => { }, TaskScheduler.Default);
+ await PollHelper.WaitUntilAsync(() => serverA.HasRemoteInterest("route.sub.test"));
serverA.HasRemoteInterest("route.sub.test").ShouldBeTrue();
}
@@ -582,9 +567,7 @@ public class NetworkingGoParityTests
try
{
- using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!timeout.IsCancellationRequested && serverA.Stats.Routes < 3)
- await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
+ await PollHelper.WaitUntilAsync(() => !(serverA.Stats.Routes < 3));
await using var subConn = new NatsConnection(new NatsOpts
{
@@ -601,9 +584,7 @@ public class NetworkingGoParityTests
await using var sub = await subConn.SubscribeCoreAsync("route.fwd.test");
await subConn.PingAsync();
- using var interest = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!interest.IsCancellationRequested && !serverA.HasRemoteInterest("route.fwd.test"))
- await Task.Delay(50, interest.Token).ContinueWith(_ => { }, TaskScheduler.Default);
+ await PollHelper.WaitUntilAsync(() => serverA.HasRemoteInterest("route.fwd.test"));
await pubConn.PublishAsync("route.fwd.test", "routed-msg");
@@ -852,7 +833,7 @@ public class NetworkingGoParityTests
leaf.StartLoop(cts.Token);
await WriteLineAsync(remoteSocket, "LS+ $G events.>", cts.Token);
- await Task.Delay(100);
+ await PollHelper.YieldForAsync(100);
await WriteLineAsync(remoteSocket, "LS- $G events.>", cts.Token);
var result = await received.Task.WaitAsync(cts.Token);
@@ -1132,9 +1113,7 @@ internal sealed class TwoGatewayFixture : IAsyncDisposable
_ = remote.StartAsync(remoteCts.Token);
await remote.WaitForReadyAsync();
- using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!timeout.IsCancellationRequested && (local.Stats.Gateways == 0 || remote.Stats.Gateways == 0))
- await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
+ await PollHelper.WaitUntilAsync(() => !((local.Stats.Gateways == 0 || remote.Stats.Gateways == 0)));
return new TwoGatewayFixture(local, remote, localCts, remoteCts);
}
@@ -1205,37 +1184,23 @@ internal sealed class LeafFixture : IAsyncDisposable
_ = spoke.StartAsync(spokeCts.Token);
await spoke.WaitForReadyAsync();
- using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!timeout.IsCancellationRequested && (hub.Stats.Leafs == 0 || spoke.Stats.Leafs == 0))
- await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
+ await PollHelper.WaitUntilAsync(() => !((hub.Stats.Leafs == 0 || spoke.Stats.Leafs == 0)));
return new LeafFixture(hub, spoke, hubCts, spokeCts);
}
public async Task WaitForRemoteInterestOnHubAsync(string subject)
{
- using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!timeout.IsCancellationRequested)
- {
- if (Hub.HasRemoteInterest(subject))
- return;
- await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
- }
-
- throw new TimeoutException($"Timed out waiting for remote interest on hub for '{subject}'.");
+ await PollHelper.WaitOrThrowAsync(
+ () => Hub.HasRemoteInterest(subject),
+ $"Timed out waiting for remote interest on hub for '{subject}'.");
}
public async Task WaitForRemoteInterestOnSpokeAsync(string subject)
{
- using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
- while (!timeout.IsCancellationRequested)
- {
- if (Spoke.HasRemoteInterest(subject))
- return;
- await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
- }
-
- throw new TimeoutException($"Timed out waiting for remote interest on spoke for '{subject}'.");
+ await PollHelper.WaitOrThrowAsync(
+ () => Spoke.HasRemoteInterest(subject),
+ $"Timed out waiting for remote interest on spoke for '{subject}'.");
}
public async ValueTask DisposeAsync()
diff --git a/tests/NATS.Server.Tests/OcspConfigTests.cs b/tests/NATS.Server.Transport.Tests/OcspConfigTests.cs
similarity index 98%
rename from tests/NATS.Server.Tests/OcspConfigTests.cs
rename to tests/NATS.Server.Transport.Tests/OcspConfigTests.cs
index 42122ac..8639f84 100644
--- a/tests/NATS.Server.Tests/OcspConfigTests.cs
+++ b/tests/NATS.Server.Transport.Tests/OcspConfigTests.cs
@@ -1,6 +1,6 @@
using NATS.Server.Tls;
-namespace NATS.Server.Tests;
+namespace NATS.Server.Transport.Tests;
public class OcspConfigTests
{
diff --git a/tests/NATS.Server.Tests/OcspStaplingTests.cs b/tests/NATS.Server.Transport.Tests/OcspStaplingTests.cs
similarity index 98%
rename from tests/NATS.Server.Tests/OcspStaplingTests.cs
rename to tests/NATS.Server.Transport.Tests/OcspStaplingTests.cs
index 9c19dc0..f959d4d 100644
--- a/tests/NATS.Server.Tests/OcspStaplingTests.cs
+++ b/tests/NATS.Server.Transport.Tests/OcspStaplingTests.cs
@@ -1,6 +1,6 @@
using NATS.Server.Tls;
-namespace NATS.Server.Tests;
+namespace NATS.Server.Transport.Tests;
public class OcspStaplingTests
{
diff --git a/tests/NATS.Server.Tests/TlsConnectionWrapperTests.cs b/tests/NATS.Server.Transport.Tests/TlsConnectionWrapperTests.cs
similarity index 96%
rename from tests/NATS.Server.Tests/TlsConnectionWrapperTests.cs
rename to tests/NATS.Server.Transport.Tests/TlsConnectionWrapperTests.cs
index 55df6cc..de92fc5 100644
--- a/tests/NATS.Server.Tests/TlsConnectionWrapperTests.cs
+++ b/tests/NATS.Server.Transport.Tests/TlsConnectionWrapperTests.cs
@@ -6,9 +6,10 @@ using System.Security.Cryptography.X509Certificates;
using Microsoft.Extensions.Logging.Abstractions;
using NATS.Server;
using NATS.Server.Protocol;
+using NATS.Server.TestUtilities;
using NATS.Server.Tls;
-namespace NATS.Server.Tests;
+namespace NATS.Server.Transport.Tests;
public class TlsConnectionWrapperTests
{
@@ -32,7 +33,7 @@ public class TlsConnectionWrapperTests
[Fact]
public async Task TlsRequired_upgrades_to_ssl()
{
- var (cert, _) = TlsHelperTests.GenerateTestCert();
+ var (cert, _) = TestCertHelper.GenerateTestCert();
var (serverSocket, clientSocket) = await CreateSocketPairAsync();
using var clientNetStream = new NetworkStream(clientSocket, ownsSocket: true);
@@ -85,7 +86,7 @@ public class TlsConnectionWrapperTests
[Fact]
public async Task MixedMode_allows_plaintext_when_AllowNonTls()
{
- var (cert, _) = TlsHelperTests.GenerateTestCert();
+ var (cert, _) = TestCertHelper.GenerateTestCert();
var (serverSocket, clientSocket) = await CreateSocketPairAsync();
using var clientNetStream = new NetworkStream(clientSocket, ownsSocket: true);
@@ -133,7 +134,7 @@ public class TlsConnectionWrapperTests
[Fact]
public async Task TlsRequired_rejects_plaintext()
{
- var (cert, _) = TlsHelperTests.GenerateTestCert();
+ var (cert, _) = TestCertHelper.GenerateTestCert();
var (serverSocket, clientSocket) = await CreateSocketPairAsync();
using var clientNetStream = new NetworkStream(clientSocket, ownsSocket: true);
@@ -180,7 +181,7 @@ public class TlsConnectionWrapperTests
[Fact]
public async Task TlsFirst_handshakes_before_sending_info()
{
- var (cert, _) = TlsHelperTests.GenerateTestCert();
+ var (cert, _) = TestCertHelper.GenerateTestCert();
var (serverSocket, clientSocket) = await CreateSocketPairAsync();
using var clientNetStream = new NetworkStream(clientSocket, ownsSocket: true);
diff --git a/tests/NATS.Server.Tests/TlsHelperTests.cs b/tests/NATS.Server.Transport.Tests/TlsHelperTests.cs
similarity index 76%
rename from tests/NATS.Server.Tests/TlsHelperTests.cs
rename to tests/NATS.Server.Transport.Tests/TlsHelperTests.cs
index 7394f21..52c340b 100644
--- a/tests/NATS.Server.Tests/TlsHelperTests.cs
+++ b/tests/NATS.Server.Transport.Tests/TlsHelperTests.cs
@@ -2,16 +2,17 @@ using System.Net;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using NATS.Server;
+using NATS.Server.TestUtilities;
using NATS.Server.Tls;
-namespace NATS.Server.Tests;
+namespace NATS.Server.Transport.Tests;
public class TlsHelperTests
{
[Fact]
public void LoadCertificate_loads_pem_cert_and_key()
{
- var (certPath, keyPath) = GenerateTestCertFiles();
+ var (certPath, keyPath) = TestCertHelper.GenerateTestCertFiles();
try
{
var cert = TlsHelper.LoadCertificate(certPath, keyPath);
@@ -24,7 +25,7 @@ public class TlsHelperTests
[Fact]
public void BuildServerAuthOptions_creates_valid_options()
{
- var (certPath, keyPath) = GenerateTestCertFiles();
+ var (certPath, keyPath) = TestCertHelper.GenerateTestCertFiles();
try
{
var opts = new NatsOptions { TlsCert = certPath, TlsKey = keyPath };
@@ -38,7 +39,7 @@ public class TlsHelperTests
[Fact]
public void LoadCaCertificates_rejects_non_certificate_pem_block()
{
- var (_, key) = GenerateTestCert();
+ var (_, key) = TestCertHelper.GenerateTestCert();
var pemPath = Path.GetTempFileName();
try
{
@@ -123,27 +124,10 @@ public class TlsHelperTests
await limiter.WaitAsync(cts.Token);
}
- // Public helper methods used by other test classes
+ // Delegate to shared TestCertHelper in TestUtilities
public static (string certPath, string keyPath) GenerateTestCertFiles()
- {
- var (cert, key) = GenerateTestCert();
- var certPath = Path.GetTempFileName();
- var keyPath = Path.GetTempFileName();
- File.WriteAllText(certPath, cert.ExportCertificatePem());
- File.WriteAllText(keyPath, key.ExportPkcs8PrivateKeyPem());
- return (certPath, keyPath);
- }
+ => TestCertHelper.GenerateTestCertFiles();
public static (X509Certificate2 cert, RSA key) GenerateTestCert()
- {
- var key = RSA.Create(2048);
- var req = new CertificateRequest("CN=localhost", key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
- req.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, false));
- var sanBuilder = new SubjectAlternativeNameBuilder();
- sanBuilder.AddIpAddress(IPAddress.Loopback);
- sanBuilder.AddDnsName("localhost");
- req.CertificateExtensions.Add(sanBuilder.Build());
- var cert = req.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(1));
- return (cert, key);
- }
+ => TestCertHelper.GenerateTestCert();
}
diff --git a/tests/NATS.Server.Tests/TlsMapAuthenticatorTests.cs b/tests/NATS.Server.Transport.Tests/TlsMapAuthenticatorTests.cs
similarity index 98%
rename from tests/NATS.Server.Tests/TlsMapAuthenticatorTests.cs
rename to tests/NATS.Server.Transport.Tests/TlsMapAuthenticatorTests.cs
index e3e27ed..605a9b0 100644
--- a/tests/NATS.Server.Tests/TlsMapAuthenticatorTests.cs
+++ b/tests/NATS.Server.Transport.Tests/TlsMapAuthenticatorTests.cs
@@ -2,7 +2,7 @@ using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using NATS.Server.Auth;
-namespace NATS.Server.Tests;
+namespace NATS.Server.Transport.Tests;
public class TlsMapAuthenticatorTests
{
diff --git a/tests/NATS.Server.Tests/TlsOcspParityBatch1Tests.cs b/tests/NATS.Server.Transport.Tests/TlsOcspParityBatch1Tests.cs
similarity index 95%
rename from tests/NATS.Server.Tests/TlsOcspParityBatch1Tests.cs
rename to tests/NATS.Server.Transport.Tests/TlsOcspParityBatch1Tests.cs
index 0bdc881..98b50c2 100644
--- a/tests/NATS.Server.Tests/TlsOcspParityBatch1Tests.cs
+++ b/tests/NATS.Server.Transport.Tests/TlsOcspParityBatch1Tests.cs
@@ -1,9 +1,10 @@
using System.Security.Cryptography;
using System.Text.Json;
using NATS.Server.Configuration;
+using NATS.Server.TestUtilities;
using NATS.Server.Tls;
-namespace NATS.Server.Tests;
+namespace NATS.Server.Transport.Tests;
public class TlsOcspParityBatch1Tests
{
@@ -84,7 +85,7 @@ public class TlsOcspParityBatch1Tests
[Fact]
public void GenerateFingerprint_uses_raw_certificate_sha256()
{
- var (cert, _) = TlsHelperTests.GenerateTestCert();
+ var (cert, _) = TestCertHelper.GenerateTestCert();
var expected = Convert.ToBase64String(SHA256.HashData(cert.RawData));
TlsHelper.GenerateFingerprint(cert).ShouldBe(expected);
@@ -104,7 +105,7 @@ public class TlsOcspParityBatch1Tests
[Fact]
public void Subject_and_issuer_dn_helpers_return_values_and_empty_for_null()
{
- var (cert, _) = TlsHelperTests.GenerateTestCert();
+ var (cert, _) = TestCertHelper.GenerateTestCert();
TlsHelper.GetSubjectDNForm(cert).ShouldNotBeNullOrWhiteSpace();
TlsHelper.GetIssuerDNForm(cert).ShouldNotBeNullOrWhiteSpace();
diff --git a/tests/NATS.Server.Tests/TlsOcspParityBatch2Tests.cs b/tests/NATS.Server.Transport.Tests/TlsOcspParityBatch2Tests.cs
similarity index 98%
rename from tests/NATS.Server.Tests/TlsOcspParityBatch2Tests.cs
rename to tests/NATS.Server.Transport.Tests/TlsOcspParityBatch2Tests.cs
index 7832216..5f9b819 100644
--- a/tests/NATS.Server.Tests/TlsOcspParityBatch2Tests.cs
+++ b/tests/NATS.Server.Transport.Tests/TlsOcspParityBatch2Tests.cs
@@ -1,9 +1,10 @@
using System.Formats.Asn1;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
+using NATS.Server.TestUtilities;
using NATS.Server.Tls;
-namespace NATS.Server.Tests;
+namespace NATS.Server.Transport.Tests;
public class TlsOcspParityBatch2Tests
{
@@ -24,7 +25,7 @@ public class TlsOcspParityBatch2Tests
[Fact]
public void CertOCSPEligible_returns_false_when_leaf_has_no_ocsp_servers()
{
- var (leaf, _) = TlsHelperTests.GenerateTestCert();
+ var (leaf, _) = TestCertHelper.GenerateTestCert();
var link = new ChainLink { Leaf = leaf };
TlsHelper.CertOCSPEligible(link).ShouldBeFalse();
diff --git a/tests/NATS.Server.Tests/TlsRateLimiterTests.cs b/tests/NATS.Server.Transport.Tests/TlsRateLimiterTests.cs
similarity index 87%
rename from tests/NATS.Server.Tests/TlsRateLimiterTests.cs
rename to tests/NATS.Server.Transport.Tests/TlsRateLimiterTests.cs
index 2e7e210..cac4382 100644
--- a/tests/NATS.Server.Tests/TlsRateLimiterTests.cs
+++ b/tests/NATS.Server.Transport.Tests/TlsRateLimiterTests.cs
@@ -1,6 +1,7 @@
+using NATS.Server.TestUtilities;
using NATS.Server.Tls;
-namespace NATS.Server.Tests;
+namespace NATS.Server.Transport.Tests;
public class TlsRateLimiterTests
{
@@ -39,8 +40,8 @@ public class TlsRateLimiterTests
await limiter.WaitAsync(CancellationToken.None);
await limiter.WaitAsync(CancellationToken.None);
- // Wait for refill
- await Task.Delay(1200);
+ // Wait for refill (rate limiter refills tokens after 1 second)
+ await PollHelper.YieldForAsync(1200);
// Should have tokens again
using var cts = new CancellationTokenSource(200);
diff --git a/tests/NATS.Server.Tests/TlsServerTests.cs b/tests/NATS.Server.Transport.Tests/TlsServerTests.cs
similarity index 82%
rename from tests/NATS.Server.Tests/TlsServerTests.cs
rename to tests/NATS.Server.Transport.Tests/TlsServerTests.cs
index 703b1bf..ea7db4a 100644
--- a/tests/NATS.Server.Tests/TlsServerTests.cs
+++ b/tests/NATS.Server.Transport.Tests/TlsServerTests.cs
@@ -4,8 +4,9 @@ using System.Net.Sockets;
using System.Text;
using Microsoft.Extensions.Logging.Abstractions;
using NATS.Server;
+using NATS.Server.TestUtilities;
-namespace NATS.Server.Tests;
+namespace NATS.Server.Transport.Tests;
public class TlsServerTests : IAsyncLifetime
{
@@ -17,8 +18,8 @@ public class TlsServerTests : IAsyncLifetime
public TlsServerTests()
{
- _port = GetFreePort();
- (_certPath, _keyPath) = TlsHelperTests.GenerateTestCertFiles();
+ _port = TestPortAllocator.GetFreePort();
+ (_certPath, _keyPath) = TestCertHelper.GenerateTestCertFiles();
_server = new NatsServer(
new NatsOptions
{
@@ -98,25 +99,11 @@ public class TlsServerTests : IAsyncLifetime
await ssl2.FlushAsync();
// Client 1 should receive MSG (may arrive across multiple TLS records)
- var msg = await ReadUntilAsync(ssl1, "hello");
+ var msg = await SocketTestHelper.ReadUntilAsync(ssl1, "hello");
msg.ShouldContain("MSG test 1 5");
msg.ShouldContain("hello");
}
- private static async Task ReadUntilAsync(Stream stream, string expected, int timeoutMs = 5000)
- {
- using var cts = new CancellationTokenSource(timeoutMs);
- var sb = new StringBuilder();
- var buf = new byte[4096];
- while (!sb.ToString().Contains(expected))
- {
- var n = await stream.ReadAsync(buf, cts.Token);
- if (n == 0) break;
- sb.Append(Encoding.ASCII.GetString(buf, 0, n));
- }
- return sb.ToString();
- }
-
private static async Task UpgradeToTlsAsync(TcpClient tcp)
{
var netStream = tcp.GetStream();
@@ -127,13 +114,6 @@ public class TlsServerTests : IAsyncLifetime
await ssl.AuthenticateAsClientAsync("localhost");
return ssl;
}
-
- private static int GetFreePort()
- {
- using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- sock.Bind(new IPEndPoint(IPAddress.Loopback, 0));
- return ((IPEndPoint)sock.LocalEndPoint!).Port;
- }
}
public class TlsMixedModeTests : IAsyncLifetime
@@ -146,8 +126,8 @@ public class TlsMixedModeTests : IAsyncLifetime
public TlsMixedModeTests()
{
- _port = GetFreePort();
- (_certPath, _keyPath) = TlsHelperTests.GenerateTestCertFiles();
+ _port = TestPortAllocator.GetFreePort();
+ (_certPath, _keyPath) = TestCertHelper.GenerateTestCertFiles();
_server = new NatsServer(
new NatsOptions
{
@@ -215,11 +195,4 @@ public class TlsMixedModeTests : IAsyncLifetime
var pong = Encoding.ASCII.GetString(pongBuf, 0, read);
pong.ShouldContain("PONG");
}
-
- private static int GetFreePort()
- {
- using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- sock.Bind(new IPEndPoint(IPAddress.Loopback, 0));
- return ((IPEndPoint)sock.LocalEndPoint!).Port;
- }
}
diff --git a/tests/NATS.Server.Tests/WebSocket/WebSocketOptionsTests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WebSocketOptionsTests.cs
similarity index 96%
rename from tests/NATS.Server.Tests/WebSocket/WebSocketOptionsTests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WebSocketOptionsTests.cs
index a4c9443..3836fba 100644
--- a/tests/NATS.Server.Tests/WebSocket/WebSocketOptionsTests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WebSocketOptionsTests.cs
@@ -1,7 +1,7 @@
using Shouldly;
using NATS.Server.WebSocket;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
public class WebSocketOptionsTests
{
diff --git a/tests/NATS.Server.Tests/WebSocket/WebSocketOptionsValidatorParityBatch2Tests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WebSocketOptionsValidatorParityBatch2Tests.cs
similarity index 99%
rename from tests/NATS.Server.Tests/WebSocket/WebSocketOptionsValidatorParityBatch2Tests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WebSocketOptionsValidatorParityBatch2Tests.cs
index e5706a4..87b4961 100644
--- a/tests/NATS.Server.Tests/WebSocket/WebSocketOptionsValidatorParityBatch2Tests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WebSocketOptionsValidatorParityBatch2Tests.cs
@@ -1,7 +1,7 @@
using NATS.Server.Auth;
using NATS.Server.WebSocket;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
public class WebSocketOptionsValidatorParityBatch2Tests
{
diff --git a/tests/NATS.Server.Tests/WebSocket/WebSocketTlsTests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WebSocketTlsTests.cs
similarity index 98%
rename from tests/NATS.Server.Tests/WebSocket/WebSocketTlsTests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WebSocketTlsTests.cs
index 2c99e54..8975eab 100644
--- a/tests/NATS.Server.Tests/WebSocket/WebSocketTlsTests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WebSocketTlsTests.cs
@@ -3,7 +3,7 @@
using NATS.Server.WebSocket;
using Shouldly;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
///
/// Tests for — WebSocket-specific TLS configuration
diff --git a/tests/NATS.Server.Tests/WebSocket/WsCompressionNegotiationTests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WsCompressionNegotiationTests.cs
similarity index 99%
rename from tests/NATS.Server.Tests/WebSocket/WsCompressionNegotiationTests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WsCompressionNegotiationTests.cs
index efef0c4..58c87e2 100644
--- a/tests/NATS.Server.Tests/WebSocket/WsCompressionNegotiationTests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WsCompressionNegotiationTests.cs
@@ -6,7 +6,7 @@
using System.Text;
using NATS.Server.WebSocket;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
public class WsCompressionNegotiationTests
{
diff --git a/tests/NATS.Server.Tests/WebSocket/WsCompressionTests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WsCompressionTests.cs
similarity index 97%
rename from tests/NATS.Server.Tests/WebSocket/WsCompressionTests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WsCompressionTests.cs
index 425534c..ab59a62 100644
--- a/tests/NATS.Server.Tests/WebSocket/WsCompressionTests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WsCompressionTests.cs
@@ -1,7 +1,7 @@
using NATS.Server.WebSocket;
using Shouldly;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
public class WsCompressionTests
{
diff --git a/tests/NATS.Server.Tests/WebSocket/WsConnectionTests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WsConnectionTests.cs
similarity index 98%
rename from tests/NATS.Server.Tests/WebSocket/WsConnectionTests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WsConnectionTests.cs
index 8f30768..9f5e1f9 100644
--- a/tests/NATS.Server.Tests/WebSocket/WsConnectionTests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WsConnectionTests.cs
@@ -1,7 +1,7 @@
using System.Buffers.Binary;
using NATS.Server.WebSocket;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
public class WsConnectionTests
{
diff --git a/tests/NATS.Server.Tests/WebSocket/WsConstantsTests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WsConstantsTests.cs
similarity index 96%
rename from tests/NATS.Server.Tests/WebSocket/WsConstantsTests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WsConstantsTests.cs
index 3dd0b33..3e6d123 100644
--- a/tests/NATS.Server.Tests/WebSocket/WsConstantsTests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WsConstantsTests.cs
@@ -1,7 +1,7 @@
using NATS.Server.WebSocket;
using Shouldly;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
public class WsConstantsTests
{
diff --git a/tests/NATS.Server.Tests/WebSocket/WsFrameReadTests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WsFrameReadTests.cs
similarity index 99%
rename from tests/NATS.Server.Tests/WebSocket/WsFrameReadTests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WsFrameReadTests.cs
index 7e0e9df..38e678e 100644
--- a/tests/NATS.Server.Tests/WebSocket/WsFrameReadTests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WsFrameReadTests.cs
@@ -2,7 +2,7 @@ using System.Buffers.Binary;
using NATS.Server.WebSocket;
using Shouldly;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
public class WsFrameReadTests
{
diff --git a/tests/NATS.Server.Tests/WebSocket/WsFrameWriterTests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WsFrameWriterTests.cs
similarity index 99%
rename from tests/NATS.Server.Tests/WebSocket/WsFrameWriterTests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WsFrameWriterTests.cs
index 153b120..41b2ee2 100644
--- a/tests/NATS.Server.Tests/WebSocket/WsFrameWriterTests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WsFrameWriterTests.cs
@@ -2,7 +2,7 @@ using System.Buffers.Binary;
using NATS.Server.WebSocket;
using Shouldly;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
public class WsFrameWriterTests
{
diff --git a/tests/NATS.Server.Tests/WebSocket/WsGoParityTests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WsGoParityTests.cs
similarity index 99%
rename from tests/NATS.Server.Tests/WebSocket/WsGoParityTests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WsGoParityTests.cs
index efd6090..a5ad655 100644
--- a/tests/NATS.Server.Tests/WebSocket/WsGoParityTests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WsGoParityTests.cs
@@ -8,7 +8,7 @@ using System.Buffers.Binary;
using System.Text;
using NATS.Server.WebSocket;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
///
/// Parity tests ported from Go server/websocket_test.go exercising WebSocket
diff --git a/tests/NATS.Server.Tests/WebSocket/WsIntegrationTests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WsIntegrationTests.cs
similarity index 93%
rename from tests/NATS.Server.Tests/WebSocket/WsIntegrationTests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WsIntegrationTests.cs
index c20edee..e2faa3a 100644
--- a/tests/NATS.Server.Tests/WebSocket/WsIntegrationTests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WsIntegrationTests.cs
@@ -5,7 +5,7 @@ using System.Security.Cryptography;
using System.Text;
using NATS.Server.WebSocket;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
public class WsIntegrationTests : IAsyncLifetime
{
@@ -67,8 +67,12 @@ public class WsIntegrationTests : IAsyncLifetime
using var sub = await ConnectWsClient();
using var pub = await ConnectWsClient();
- await SendWsText(sub, "CONNECT {}\r\nSUB test.ws 1\r\n");
- await Task.Delay(200);
+ await SendWsText(sub, "CONNECT {}\r\nSUB test.ws 1\r\nPING\r\n");
+
+ // Wait for PONG to confirm subscription is registered
+ using var subCts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
+ var pong = await ReadWsFrameAsync(sub, subCts.Token);
+ Encoding.ASCII.GetString(pong).ShouldContain("PONG");
await SendWsText(pub, "CONNECT {}\r\nPUB test.ws 5\r\nHello\r\n");
diff --git a/tests/NATS.Server.Tests/WebSocket/WsJwtAuthTests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WsJwtAuthTests.cs
similarity index 99%
rename from tests/NATS.Server.Tests/WebSocket/WsJwtAuthTests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WsJwtAuthTests.cs
index 7f90df2..3269eda 100644
--- a/tests/NATS.Server.Tests/WebSocket/WsJwtAuthTests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WsJwtAuthTests.cs
@@ -6,7 +6,7 @@
using System.Text;
using NATS.Server.WebSocket;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
public class WsJwtAuthTests
{
diff --git a/tests/NATS.Server.Tests/WebSocket/WsOriginCheckerTests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WsOriginCheckerTests.cs
similarity index 98%
rename from tests/NATS.Server.Tests/WebSocket/WsOriginCheckerTests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WsOriginCheckerTests.cs
index ebd3531..4557a73 100644
--- a/tests/NATS.Server.Tests/WebSocket/WsOriginCheckerTests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WsOriginCheckerTests.cs
@@ -1,7 +1,7 @@
using NATS.Server.WebSocket;
using Shouldly;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
public class WsOriginCheckerTests
{
diff --git a/tests/NATS.Server.Tests/WebSocket/WsUpgradeHelperParityBatch1Tests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WsUpgradeHelperParityBatch1Tests.cs
similarity index 97%
rename from tests/NATS.Server.Tests/WebSocket/WsUpgradeHelperParityBatch1Tests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WsUpgradeHelperParityBatch1Tests.cs
index 45004cf..948107f 100644
--- a/tests/NATS.Server.Tests/WebSocket/WsUpgradeHelperParityBatch1Tests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WsUpgradeHelperParityBatch1Tests.cs
@@ -1,7 +1,7 @@
using System.Text;
using NATS.Server.WebSocket;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
public class WsUpgradeHelperParityBatch1Tests
{
diff --git a/tests/NATS.Server.Tests/WebSocket/WsUpgradeTests.cs b/tests/NATS.Server.Transport.Tests/WebSocket/WsUpgradeTests.cs
similarity index 99%
rename from tests/NATS.Server.Tests/WebSocket/WsUpgradeTests.cs
rename to tests/NATS.Server.Transport.Tests/WebSocket/WsUpgradeTests.cs
index a5e1168..a92c916 100644
--- a/tests/NATS.Server.Tests/WebSocket/WsUpgradeTests.cs
+++ b/tests/NATS.Server.Transport.Tests/WebSocket/WsUpgradeTests.cs
@@ -1,7 +1,7 @@
using System.Text;
using NATS.Server.WebSocket;
-namespace NATS.Server.Tests.WebSocket;
+namespace NATS.Server.Transport.Tests.WebSocket;
public class WsUpgradeTests
{