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(); } } }