using System.IO;
using System.Net.Sockets;
using ZB.MOM.WW.CBDDC.Core;
using ZB.MOM.WW.CBDDC.Core.Network;
using ZB.MOM.WW.CBDDC.Core.Storage;
using ZB.MOM.WW.CBDDC.Network.Security;
using Microsoft.Extensions.Logging.Abstractions;
namespace ZB.MOM.WW.CBDDC.Network.Tests;
public class ConnectionTests
{
///
/// Verifies that the server rejects new clients when the configured connection limit is reached.
///
[Fact]
public async Task Server_Should_Reject_Clients_When_Limit_Reached()
{
// Arrange
var oplogStore = Substitute.For();
oplogStore.GetLatestTimestampAsync(Arg.Any())
.Returns(new HlcTimestamp(0, 0, "node"));
oplogStore.GetVectorClockAsync(Arg.Any())
.Returns(new VectorClock());
oplogStore.GetOplogAfterAsync(Arg.Any(), Arg.Any?>(), Arg.Any())
.Returns(Array.Empty());
oplogStore.GetOplogForNodeAfterAsync(Arg.Any(), Arg.Any(), Arg.Any?>(), Arg.Any())
.Returns(Array.Empty());
var configProvider = Substitute.For();
configProvider.GetConfiguration().Returns(new PeerNodeConfiguration
{
NodeId = "server-node",
AuthToken = "auth-token",
TcpPort = 0
});
var snapshotService = Substitute.For();
var documentStore = Substitute.For();
documentStore.InterestedCollection.Returns(["Users", "TodoLists"]);
var authenticator = Substitute.For();
authenticator.ValidateAsync(Arg.Any(), Arg.Any()).Returns(true);
var handshakeService = Substitute.For();
handshakeService.HandshakeAsync(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any())
.Returns((CipherState?)null);
var server = new TcpSyncServer(
oplogStore,
documentStore,
snapshotService,
configProvider,
NullLogger.Instance,
authenticator,
handshakeService);
server.MaxConnections = 2;
await server.Start();
var port = server.ListeningPort ?? throw new Exception("Server not started");
using var client1 = new TcpClient();
using var client2 = new TcpClient();
using var client3 = new TcpClient();
try
{
// Act
await client1.ConnectAsync("127.0.0.1", port);
await client2.ConnectAsync("127.0.0.1", port);
await Task.Delay(100);
await client3.ConnectAsync("127.0.0.1", port);
// Assert
var stream3 = client3.GetStream();
var buffer = new byte[10];
var read = await stream3.ReadAsync(buffer, 0, 10);
read.ShouldBe(0, "Server should close connection immediately for client 3");
client1.Connected.ShouldBeTrue();
client2.Connected.ShouldBeTrue();
}
finally
{
await server.Stop();
}
}
}