public async Task WithNackMessageReceived_CallbackIsCalledWithError() { // Arrange var client = await GetConnectedClient(); var callbacks = new List <ValueTuple <bool, ErrorInfo> >(); var message = new ProtocolMessage(ProtocolMessage.MessageAction.Message, "Test"); void Callback(bool ack, ErrorInfo err) { callbacks.Add((ack, err)); } // Act client.ExecuteCommand(SendMessageCommand.Create(message, Callback)); client.ExecuteCommand(ProcessMessageCommand.Create( new ProtocolMessage(ProtocolMessage.MessageAction.Nack) { MsgSerial = 0, Count = 1 })); client.ExecuteCommand(SendMessageCommand.Create(message, Callback)); client.ExecuteCommand(ProcessMessageCommand.Create( new ProtocolMessage(ProtocolMessage.MessageAction.Nack) { MsgSerial = 1, Count = 1 })); await client.ProcessCommands(); // Assert callbacks.Count.Should().Be(2); Assert.True(callbacks.TrueForAll(c => c.Item1 == false)); // Nack Assert.True(callbacks.TrueForAll(c => c.Item2 != null)); // Error }
public async Task WhenNackReceivedForMultipleMessage_AllCallbacksAreCalledAndErrorMessagePassed() { // Arrange var client = await GetConnectedClient(); var callbacks = new List <ValueTuple <bool, ErrorInfo> >(); var message = new ProtocolMessage(ProtocolMessage.MessageAction.Message, "Test"); void Callback(bool ack, ErrorInfo err) { callbacks.Add((ack, err)); } // Act client.ExecuteCommand(SendMessageCommand.Create(message, Callback)); client.ExecuteCommand(SendMessageCommand.Create(message, Callback)); client.ExecuteCommand(SendMessageCommand.Create(message, Callback)); var error = new ErrorInfo("reason", 123); client.ExecuteCommand(ProcessMessageCommand.Create( new ProtocolMessage(ProtocolMessage.MessageAction.Nack) { MsgSerial = 0, Count = 3, Error = error })); await client.ProcessCommands(); // Assert callbacks.Count.Should().Be(3); Assert.True(callbacks.TrueForAll(c => !c.Item1)); // Nack Assert.True(callbacks.TrueForAll(c => ReferenceEquals(c.Item2, error))); // Error }
public async Task WithBase64Message_ShouldKeepBase64DecodedPayload() { var(realtime, c) = await GetClientAndChannel(); RealtimeChannel channel = (RealtimeChannel)c; channel.SetChannelState(ChannelState.Attached); const string testString = "Testing, testing, testing"; var successfulProtocolMessage = new ProtocolMessage(ProtocolMessage.MessageAction.Message) { Channel = channel.Name, Messages = new[] { new Message { Data = testString.ToBase64(), Encoding = "base64" }, }, }; realtime.ExecuteCommand(ProcessMessageCommand.Create(successfulProtocolMessage)); await realtime.ProcessCommands(); var previousPayload = channel.MessageDecodingContext.PreviousPayload; previousPayload.StringData.Should().BeNull(); previousPayload.Encoding.Should().BeEmpty(); previousPayload.ByteData.Should().Equal(testString.GetBytes()); }
WhenMessageReceived_WithNotMatchingDeltaFromProperty_ShouldStartDecodeRecoveryAndMoveToAttachingWithError() { var(realtime, c) = await GetClientAndChannel(); RealtimeChannel channel = (RealtimeChannel)c; channel.SetChannelState(ChannelState.Attached); var awaiter = new TaskCompletionAwaiter(); ChannelStateChange stateChange = null; channel.On(ChannelEvent.Attaching, change => { stateChange = change; channel.DecodeRecovery.Should().BeTrue(); awaiter.Done(); }); realtime.ExecuteCommand(ProcessMessageCommand.Create( new ProtocolMessage(ProtocolMessage.MessageAction.Message) { Channel = channel.Name, Messages = new[] { new Message { Extras = CreateExtrasWithDelta(new DeltaExtras("1", string.Empty)) }, }, })); await awaiter.Task; stateChange.Current.Should().Be(ChannelState.Attaching); stateChange.Error.Code.Should().Be(ErrorCodes.VcDiffDecodeError); }
public async Task WithBinaryMessage_ShouldKeepItPreviousPayloadInBinaryForm() { var(realtime, c) = await GetClientAndChannel(); RealtimeChannel channel = (RealtimeChannel)c; channel.SetChannelState(ChannelState.Attached); var binaryData = new byte[] { 112, 100, 111 }; var successfulProtocolMessage = new ProtocolMessage(ProtocolMessage.MessageAction.Message) { Channel = channel.Name, Messages = new[] { new Message { Data = binaryData }, }, }; realtime.ExecuteCommand(ProcessMessageCommand.Create(successfulProtocolMessage)); await realtime.ProcessCommands(); var previousPayload = channel.MessageDecodingContext.PreviousPayload; previousPayload.StringData.Should().BeNull(); previousPayload.ByteData.Should().Equal(binaryData); }
public async Task WithStringMessage_ShouldKeepItWithoutProcessing() { var(realtime, c) = await GetClientAndChannel(); RealtimeChannel channel = (RealtimeChannel)c; channel.SetChannelState(ChannelState.Attached); var successfulProtocolMessage = new ProtocolMessage(ProtocolMessage.MessageAction.Message) { Channel = channel.Name, Messages = new[] { new Message { Data = "test", Encoding = "custom" }, }, }; realtime.ExecuteCommand(ProcessMessageCommand.Create(successfulProtocolMessage)); await realtime.ProcessCommands(); var previousPayload = channel.MessageDecodingContext.PreviousPayload; previousPayload.Encoding.Should().Be("custom"); previousPayload.StringData.Should().Be("test"); previousPayload.ByteData.Should().BeNull(); }
public async Task WhenSendingMessage_AckCallbackCalled_ForMultipleMessages() { // Arrange var client = await GetConnectedClient(); var callbacks = new List <ValueTuple <bool, ErrorInfo> >(); var message1 = new ProtocolMessage(ProtocolMessage.MessageAction.Message, "Test"); var message2 = new ProtocolMessage(ProtocolMessage.MessageAction.Message, "Test"); var message3 = new ProtocolMessage(ProtocolMessage.MessageAction.Message, "Test"); var awaiter = new TaskCompletionAwaiter(); Action <bool, ErrorInfo> GetCallback(int forCount) => (ack, err) => { if (callbacks.Count == forCount) { callbacks.Add((ack, err)); } if (callbacks.Count == 3) { awaiter.SetCompleted(); } }; var ackMessage = new ProtocolMessage(ProtocolMessage.MessageAction.Ack) { MsgSerial = 0, Count = 3 }; // Act client.Workflow.QueueAck(message1, GetCallback(0)); client.Workflow.QueueAck(message2, GetCallback(1)); client.Workflow.QueueAck(message3, GetCallback(2)); client.ExecuteCommand(ProcessMessageCommand.Create(ackMessage)); await client.ProcessCommands(); await awaiter.Task; // Assert callbacks.Count.Should().Be(3); Assert.True(callbacks.TrueForAll(c => c.Item1)); // Ack Assert.True(callbacks.TrueForAll(c => c.Item2 == null)); // No error }
WhenMessageReceivedAndFailsVcdiffDecoding_ShouldSendAttachProtocolMessageWithLastSuccessfulChannelSerial() { var(realtime, c) = await GetClientAndChannel(); RealtimeChannel channel = (RealtimeChannel)c; channel.SetChannelState(ChannelState.Attached); var successfulProtocolMessage = new ProtocolMessage(ProtocolMessage.MessageAction.Message) { Channel = channel.Name, ChannelSerial = "testSerial", Messages = new[] { new Message { Data = "test", Encoding = string.Empty }, }, }; realtime.ExecuteCommand(ProcessMessageCommand.Create(successfulProtocolMessage)); var awaiter = new TaskCompletionAwaiter(); channel.On(ChannelEvent.Attaching, change => { awaiter.Tick(); }); realtime.ExecuteCommand(ProcessMessageCommand.Create( new ProtocolMessage(ProtocolMessage.MessageAction.Message) { Channel = channel.Name, Messages = new[] { new Message { Extras = CreateExtrasWithDelta(new DeltaExtras("1", string.Empty)) }, }, })); await awaiter.Task; await realtime.ProcessCommands(); var fakeTransport = FakeTransportFactory.LastCreatedTransport; var lastMessageSend = fakeTransport.LastMessageSend; lastMessageSend.Should().NotBeNull(); lastMessageSend.Action.Should().Be(ProtocolMessage.MessageAction.Attach); lastMessageSend.ChannelSerial.Should().Be("testSerial"); }
public async Task WithInboundErrorMessage_WhenNotTokenErrorAndChannelsEmpty_GoesToFailed() { var client = GetRealtimeClient(opts => opts.RealtimeHost = "non-default.ably.io"); // Force no fallback await client.WaitForState(ConnectionState.Connecting); // Arrange ErrorInfo targetError = new ErrorInfo("test", 123); // Act client.Workflow.ProcessCommand(ProcessMessageCommand.Create(new ProtocolMessage(ProtocolMessage.MessageAction.Error) { Error = targetError })); // Assert await client.WaitForState(ConnectionState.Failed); }
public async Task WithInboundDisconnectedMessage_ShouldTransitionToDisconnectedState() { // Arrange var client = GetRealtimeClient(); client.Connect(); await client.WaitForState(ConnectionState.Connecting); var disconnectedMessage = new ProtocolMessage(ProtocolMessage.MessageAction.Disconnected) { Error = ErrorInfo.ReasonDisconnected }; // Act client.ExecuteCommand(ProcessMessageCommand.Create(disconnectedMessage)); await client.WaitForState(ConnectionState.Disconnected, TimeSpan.FromSeconds(5)); }
public async Task WhenMessageReceived_WithDeltaError_ShouldNotPassMessageToChannelSubscriber() { var(realtime, c) = await GetClientAndChannel(); RealtimeChannel channel = (RealtimeChannel)c; channel.SetChannelState(ChannelState.Attached); List <Message> receivedMessages = new List <Message>(); channel.Subscribe(receivedMessages.Add); realtime.ExecuteCommand(ProcessMessageCommand.Create( new ProtocolMessage(ProtocolMessage.MessageAction.Message) { Channel = channel.Name, Messages = new[] { new Message { Id = "goodMessage", Data = "test" }, }, })); realtime.ExecuteCommand(ProcessMessageCommand.Create( new ProtocolMessage(ProtocolMessage.MessageAction.Message) { Channel = channel.Name, Messages = new[] { new Message { Extras = CreateExtrasWithDelta(new DeltaExtras("1", string.Empty)) }, }, })); await Task.Delay(2000); // wait for 2 seconds // We want to ensure just the good message was received receivedMessages.Should().HaveCount(1); receivedMessages.Should().Contain(x => x.Id == "goodMessage"); }
internal static async Task ProcessMessage(this IRealtimeClient client, ProtocolMessage message) { ((AblyRealtime)client).Workflow.QueueCommand(ProcessMessageCommand.Create(message)); await client.ProcessCommands(); }
public async Task WhenDeltaDecodeFail_ShouldSetStateToAttachingLogTheErrorAndDiscardTheMessage(Protocol protocol) { string channelName = "delta-channel".AddRandomSuffix(); var testSink = new TestLoggerSink(); var taskAwaiter = new TaskCompletionAwaiter(5000); var firstMessageReceived = new TaskCompletionAwaiter(); using (((IInternalLogger)Logger).CreateDisposableLoggingContext(testSink)) { var realtime = await GetRealtimeClient(protocol); var channel = realtime.Channels.Get(channelName, new ChannelOptions(channelParams: new ChannelParams { { "delta", "vcdiff" } })); var received = new List <Message>(); channel.Subscribe(message => { received.Add(message); if (received.Count == 1) { firstMessageReceived.Done(); } if (received.Count == 2) { taskAwaiter.Done(); } }); await channel.AttachAsync(); // We wait for the first message to be acknowledged. Any consequent messages will be deltas await channel.PublishAsync("firstMessage", new TestData("bar", 1, "active")); (await firstMessageReceived).Should().BeTrue("First message should be received before continuing with broken message"); channel.Publish("second", "second message"); // We don't want to wait for the acknowledgement realtime.ExecuteCommand(ProcessMessageCommand.Create(new ProtocolMessage(ProtocolMessage.MessageAction.Message) { Channel = channelName, Messages = new[] { new Message { Id = "badMessage", Encoding = "vcdiff", Data = Array.Empty <byte>() }, }, })); await channel.WaitForState(ChannelState.Attaching); await channel.WaitForAttachedState(); var result = await taskAwaiter; result.Should().BeTrue("TaskAwaiter Done() Should be called."); received.Should().HaveCount(2); received[1].Data.Should().Be("second message"); // RTL17 - we make sure the message is not emitted to subscribers received.Should().NotContain(x => x.Id == "badMessage"); bool hasVcdiffErrorMessage = testSink.Messages.Any(x => x.StartsWith(LogLevel.Error.ToString()) && x.Contains(ErrorCodes.VcDiffDecodeError .ToString())); hasVcdiffErrorMessage.Should().BeTrue(); } }
void ITransportListener.OnTransportDataReceived(RealtimeTransportData data) { var message = Handler.ParseRealtimeData(data); ExecuteCommand(ProcessMessageCommand.Create(message).TriggeredBy("ConnectionManager.OnTransportDataReceived()")); }
public static void FakeProtocolMessageReceived(this AblyRealtime client, ProtocolMessage message) { client.Workflow.QueueCommand(ProcessMessageCommand.Create(message)); }