Implement deferred core utility parity APIs/tests and refresh tracking artifacts

This commit is contained in:
Joseph Doherty
2026-02-27 10:27:05 -05:00
parent c0aaae9236
commit b94a67be6e
17 changed files with 842 additions and 9 deletions

View File

@@ -11,7 +11,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
using System.Net;
using System.Text.Json;
using Shouldly;
using ZB.MOM.NatsNet.Server;
using ZB.MOM.NatsNet.Server.Internal;
namespace ZB.MOM.NatsNet.Server.Tests.Internal;
@@ -191,4 +194,86 @@ public sealed class ServerUtilitiesTests
$"VersionAtLeast({version}, {major}, {minor}, {update})");
}
}
[Fact]
public void RefCountedUrlSet_Wrappers_ShouldTrackRefCounts()
{
var set = new RefCountedUrlSet();
ServerUtilities.AddUrl(set, "nats://a:4222").ShouldBeTrue();
ServerUtilities.AddUrl(set, "nats://a:4222").ShouldBeFalse();
ServerUtilities.AddUrl(set, "nats://b:4222").ShouldBeTrue();
ServerUtilities.RemoveUrl(set, "nats://a:4222").ShouldBeFalse();
ServerUtilities.RemoveUrl(set, "nats://a:4222").ShouldBeTrue();
var urls = ServerUtilities.GetAsStringSlice(set);
urls.Length.ShouldBe(1);
urls[0].ShouldBe("nats://b:4222");
}
[Fact]
public async Task NatsDialTimeout_ShouldConnectWithinTimeout()
{
using var listener = new System.Net.Sockets.TcpListener(IPAddress.Loopback, 0);
listener.Start();
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
var acceptTask = listener.AcceptTcpClientAsync();
using var client = await ServerUtilities.NatsDialTimeout(
"tcp",
$"127.0.0.1:{port}",
TimeSpan.FromSeconds(2));
client.Connected.ShouldBeTrue();
using var accepted = await acceptTask;
accepted.Connected.ShouldBeTrue();
}
[Fact]
public void GenerateInfoJSON_ShouldEmitInfoLineWithCRLF()
{
var info = new ServerInfo
{
Id = "S1",
Name = "n1",
Host = "127.0.0.1",
Port = 4222,
Version = "2.0.0",
Proto = 1,
GoVersion = "go1.23",
};
var bytes = ServerUtilities.GenerateInfoJSON(info);
var line = System.Text.Encoding.UTF8.GetString(bytes);
line.ShouldStartWith("INFO ");
line.ShouldEndWith("\r\n");
var json = line["INFO ".Length..^2];
var payload = JsonSerializer.Deserialize<ServerInfo>(json);
payload.ShouldNotBeNull();
payload!.Id.ShouldBe("S1");
}
[Fact]
public async Task ParallelTaskQueue_ShouldExecuteQueuedActions()
{
var writer = ServerUtilities.ParallelTaskQueue(maxParallelism: 2);
var ran = 0;
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
for (var i = 0; i < 4; i++)
{
var accepted = writer.TryWrite(() =>
{
if (Interlocked.Increment(ref ran) == 4)
tcs.TrySetResult();
});
accepted.ShouldBeTrue();
}
writer.TryComplete().ShouldBeTrue();
var finished = await Task.WhenAny(tcs.Task, Task.Delay(TimeSpan.FromSeconds(2)));
finished.ShouldBe(tcs.Task);
ran.ShouldBe(4);
}
}