public async Task With3ClientsAnd60MessagesAndCallbacks_ShouldExecuteAllCallbacks(Protocol protocol) { var channelName = "test".AddRandomSuffix(); List <bool> successes1 = new List <bool>(); List <bool> successes2 = new List <bool>(); List <bool> successes3 = new List <bool>(); bool retry = true; int tries = 3; while (retry) { var client1 = await GetRealtimeClient(protocol); var client2 = await GetRealtimeClient(protocol); var client3 = await GetRealtimeClient(protocol); var messages = new List <Message>(); for (int i = 0; i < 20; i++) { messages.Add(new Message("name" + i, "data" + i)); } var awaiter = new TaskCountAwaiter(60); foreach (var message in messages) { client1.Channels.Get(channelName).Publish(new[] { message }, (b, info) => { successes1.Add(b); awaiter.Tick(); }); client2.Channels.Get(channelName).Publish(new[] { message }, (b, info) => { successes2.Add(b); awaiter.Tick(); }); client3.Channels.Get(channelName).Publish(new[] { message }, (b, info) => { successes3.Add(b); awaiter.Tick(); }); } await awaiter.Task; if ((successes1.Count == 20 && successes2.Count == 20 && successes3.Count == 20) || tries <= 0) { retry = false; } tries--; } successes1.Should().HaveCount(20, "Should have 20 successful callback executed"); successes2.Should().HaveCount(20, "Should have 20 successful callback executed"); successes3.Should().HaveCount(20, "Should have 20 successful callback executed"); }
public async Task PresenceMapBehaviour_ShouldConformToSpec(Protocol protocol) { Logger.LogLevel = LogLevel.Debug; var channelName = "presence_map_tests_newness".AddRandomSuffix(); var client = await GetRealtimeClient(protocol); await client.WaitForState(ConnectionState.Connected); client.Connection.State.ShouldBeEquivalentTo(ConnectionState.Connected); var channel = client.Channels.Get(channelName); channel.Attach(); await channel.WaitForState(ChannelState.Attached); channel.State.ShouldBeEquivalentTo(ChannelState.Attached); const string wontPass = "******"; List <PresenceMessage> presenceMessages = new List <PresenceMessage>(); channel.Presence.Subscribe(x => { x.Data.Should().NotBe(wontPass, "message did not pass the newness test"); presenceMessages.Add(x); }); /* Test message newness criteria as described in RTP2b */ PresenceMessage[] testData = new PresenceMessage[] { new PresenceMessage { Action = PresenceAction.Enter, ClientId = "1", ConnectionId = "1", Id = "1:0", Data = string.Empty }, new PresenceMessage { Action = PresenceAction.Enter, ClientId = "2", ConnectionId = "2", Id = "2:1:0", Timestamp = new DateTimeOffset(2000, 1, 1, 1, 1, 1, new TimeSpan()), Data = string.Empty }, /* Should be newer than previous one */ new PresenceMessage { Action = PresenceAction.Update, ClientId = "2", ConnectionId = "2", Id = "2:2:1", Timestamp = new DateTimeOffset(2000, 1, 1, 1, 1, 2, new TimeSpan()), Data = string.Empty }, /* Shouldn't pass newness test because of message serial, timestamp doesn't matter in this case */ new PresenceMessage { Action = PresenceAction.Update, ClientId = "2", ConnectionId = "2", Id = "2:1:1", Timestamp = new DateTimeOffset(2000, 1, 1, 1, 1, 3, new TimeSpan()), Data = wontPass }, /* Shouldn't pass because of message index */ new PresenceMessage { Action = PresenceAction.Update, ClientId = "2", ConnectionId = "2", Id = "2:2:0", Data = wontPass }, /* Should pass because id is not in form connId:clientId:index and timestamp is greater */ new PresenceMessage { Action = PresenceAction.Update, ClientId = "2", ConnectionId = "2", Id = "wrong_id", Timestamp = new DateTimeOffset(2000, 1, 1, 1, 1, 10, new TimeSpan()), Data = string.Empty }, /* Shouldn't pass because of timestamp */ new PresenceMessage { Action = PresenceAction.Update, ClientId = "2", ConnectionId = "2", Id = "2:3:1", Timestamp = new DateTimeOffset(2000, 1, 1, 1, 1, 5, new TimeSpan()), Data = wontPass } }; foreach (var presenceMessage in testData) { var protocolMessage = new ProtocolMessage(ProtocolMessage.MessageAction.Presence) { Channel = channelName, Presence = new PresenceMessage[] { presenceMessage } }; await client.Connection.ConnectionManager.OnTransportMessageReceived(protocolMessage); } int n = 0; foreach (var testMsg in testData) { if (testMsg.Data.ToString() == wontPass) { continue; } PresenceMessage factualMsg = n < presenceMessages.Count ? presenceMessages[n++] : null; factualMsg.Should().NotBe(null); factualMsg.Id.ShouldBeEquivalentTo(testMsg.Id); factualMsg.Action.ShouldBeEquivalentTo(testMsg.Action, "message was not emitted on the presence object with original action"); var presentMessage = await channel.Presence.GetAsync(new GetOptions { ClientId = testMsg.ClientId, WaitForSync = false }); presentMessage.FirstOrDefault().Should().NotBe(null); presentMessage.FirstOrDefault()?.Action.ShouldBeEquivalentTo(PresenceAction.Present, "message was not added to the presence map and stored with PRESENT action"); } presenceMessages.Count.ShouldBeEquivalentTo(n, "the number of messages received didn't match the number of test messages sent."); /* Repeat the process now as a part of SYNC and verify everything is exactly the same */ var channel2Name = "presence_map_tests_sync_newness".AddRandomSuffix(); var client2 = await GetRealtimeClient(protocol); await client2.WaitForState(ConnectionState.Connected); client2.Connection.State.ShouldBeEquivalentTo(ConnectionState.Connected); var channel2 = client2.Channels.Get(channel2Name); channel2.Attach(); await channel2.WaitForState(ChannelState.Attached); channel2.State.ShouldBeEquivalentTo(ChannelState.Attached); /* Send all the presence data in one SYNC message without channelSerial (RTP18c) */ ProtocolMessage syncMessage = new ProtocolMessage() { Channel = channel2Name, Action = ProtocolMessage.MessageAction.Sync, Presence = testData }; var counter = new TaskCountAwaiter(presenceMessages.Count, 5000); List <PresenceMessage> syncPresenceMessages = new List <PresenceMessage>(); channel2.Presence.Subscribe(x => { x.Data.Should().NotBe(wontPass, "message did not pass the newness test"); syncPresenceMessages.Add(x); counter.Tick(); }); await client2.Connection.ConnectionManager.OnTransportMessageReceived(syncMessage); await counter.Task; syncPresenceMessages.Count.ShouldBeEquivalentTo(presenceMessages.Count); for (int i = 0; i < syncPresenceMessages.Count; i++) { syncPresenceMessages[i].Id.ShouldBeEquivalentTo(presenceMessages[i].Id, "result should be the same in case of SYNC"); syncPresenceMessages[i].Action.ShouldBeEquivalentTo(presenceMessages[i].Action, "result should be the same in case of SYNC"); } }