using System.Buffers; using AyCode.Core; using AyCode.Core.Extensions; using AyCode.Core.Tests.TestModels; using AyCode.Services.Server.SignalRs; using AyCode.Services.SignalRs; using AyCode.Services.Tests.SignalRs; using Microsoft.AspNetCore.SignalR.Client; using Microsoft.AspNetCore.SignalR.Protocol; namespace AyCode.Services.Server.Tests.SignalRs; /// /// Testable SignalR client that allows testing without real HubConnection. /// Routes all messages through AyCodeBinaryHubProtocol with multi-segment splitting /// to exercise the full serialization/deserialization pipeline. /// public class TestableSignalRClient2 : AcSignalRClientBase, IAcSignalRHubItemServer { private HubConnectionState _connectionState = HubConnectionState.Connected; private readonly TestableSignalRHub2 _signalRHub; private readonly TestMultiSegmentProtocol _protocol; private readonly TestInvocationBinder _binder = new(); /// /// Testable SignalR client that allows testing without real HubConnection. /// public TestableSignalRClient2(TestableSignalRHub2 signalRHub, TestLogger logger, BinaryProtocolMode mode = BinaryProtocolMode.Bytes) : base(logger) { MsDelay = 0; MsFirstDelay = 0; _signalRHub = signalRHub; _protocol = new TestMultiSegmentProtocol(mode); } #region Override virtual methods for testing protected override Task MessageReceived(int messageTag, SignalParams signalParams, object data) { throw new NotImplementedException(); } protected override HubConnectionState GetConnectionState() => _connectionState; protected override bool IsConnected() => _connectionState == HubConnectionState.Connected; protected override Task StartConnectionInternal() { _connectionState = HubConnectionState.Connected; return Task.CompletedTask; } protected override Task StopConnectionInternal() { _connectionState = HubConnectionState.Disconnected; return Task.CompletedTask; } protected override ValueTask DisposeConnectionInternal() => ValueTask.CompletedTask; protected override Task SendToHubAsync(int messageTag, int? requestId, SignalParams signalParams, object? data) { // Protocol round-trip: serialize → multi-segment split → deserialize var invocation = new InvocationMessage( nameof(IAcSignalRHubClient.OnReceiveMessage), [messageTag, requestId, signalParams, data ?? Array.Empty()]); var bytes = _protocol.GetMessageBytesMultiSegment(invocation); var sequence = new ReadOnlySequence(bytes); if (!_protocol.TryParseMessage(ref sequence, _binder, out var parsed) || parsed is not InvocationMessage invMsg) throw new InvalidOperationException( $"Protocol round-trip failed. ByteCount={bytes.Length}, Parsed={parsed?.GetType().Name ?? "null"}, " + $"Tag={messageTag}, RequestId={requestId}, DataType={data?.GetType().Name ?? "null"}"); var args = invMsg.Arguments; return _signalRHub.OnReceiveMessage( (int)args[0]!, (int?)args[1], (SignalParams)args[2]!, args[3]!); } #endregion }