Skip to content

Commit

Permalink
Refactored test for ack/nack to fail when connection goes into discon…
Browse files Browse the repository at this point in the history
…nected state
  • Loading branch information
sacOO7 committed Sep 25, 2023
1 parent 575f396 commit 9386789
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public async Task<TimeSpan> Wait(TimeSpan timeout)
DefaultLogger.Debug($"[{_id} Timeout exceeded. Throwing TimeoutException");
RemoveListener();
throw new TimeoutException(
$"Expected ''{_awaitedStates.Select(x => x.ToString()).JoinStrings()}' but current state was '{_connection.State}'");
$"Expected '{_awaitedStates.Select(x => x.ToString()).JoinStrings()}' but current state was '{_connection.State}'");
}
}
}
121 changes: 80 additions & 41 deletions src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1657,78 +1657,117 @@ public async Task ChannelStateCondition_WhenQueueMessagesIsFalse_WhenChannelIsIn
[Theory]
[ProtocolData]
[Trait("spec", "RTP16b")]
[Trait("spec", "RTP19a")]
public async Task ChannelStateCondition_WhenQueueMessagesIsFalse_ShouldFailAckQueueMessages_WhenSendFails(Protocol protocol)
public async Task ChannelStateCondition_WhenQueueMessagesIsFalse_WhenChannelIsInitializedOrAttaching_MessageAreNotPublished(Protocol protocol)
{
var transportFactory = new TestTransportFactory
var client = await GetRealtimeClient(protocol, (options, settings) =>
{
BeforeMessageSent = message =>
options.ClientId = "RTP16b";
options.QueueMessages = false;
});

await client.WaitForState(ConnectionState.Connected);

var channel = GetRandomChannel(client, "RTP16a");
channel.State.Should().Be(ChannelState.Initialized);
await EnterPresenceAndCheckForError();

client.BlockActionFromSending(ProtocolMessage.MessageAction.Attach);
channel.Attach();
await channel.WaitForState(ChannelState.Attaching);
await EnterPresenceAndCheckForError();

// QueueCommand will not retry instantly
client.Workflow.QueueCommand(SetDisconnectedStateCommand.Create(null));
await client.WaitForState(ConnectionState.Disconnected);
await EnterPresenceAndCheckForError();

// clean up
client.Close();

async Task EnterPresenceAndCheckForError()
{
var enterPresenceAwaiter = new TaskCompletionAwaiter();
ErrorInfo err = null;
bool? success = null;
channel.Presence.Enter("dummy data", (b, info) =>
{
if (message.Action == ProtocolMessage.MessageAction.Presence)
{
throw new Exception("RTP16b : error while sending message");
}
success = b;
err = info;
enterPresenceAwaiter.SetCompleted();
});
await client.ProcessCommands();

// No messages sent because queueMessages false
channel.Presence.PendingPresenceQueue.Should().HaveCount(0);
client.State.PendingMessages.Should().HaveCount(0);

if (client.Connection.State != ConnectionState.Disconnected)
{
var presenceMessagesSent = client.GetTestTransport().ProtocolMessagesSent
.FindAll(msg => msg.Action == ProtocolMessage.MessageAction.Presence);
presenceMessagesSent.Should().HaveCount(0);
}
};

await enterPresenceAwaiter.Task;

success.Should().HaveValue();
success.Value.Should().BeFalse();
err.Should().NotBeNull();
err.Message.Should().Be("Unable enqueue message because Options.QueueMessages is set to False.");
}
}

[Theory]
[ProtocolData]
[Trait("spec", "RTN7d")]
public async Task ChannelStateCondition_WhenQueueMessagesIsFalse_ShouldFailAckQueueMessages_WhenSendFails(Protocol protocol)
{
var client = await GetRealtimeClient(protocol, (options, settings) =>
{
options.ClientId = "RTP16b";
options.ClientId = "RTN7d";
options.QueueMessages = false;
options.TransportFactory = transportFactory;
});

await client.WaitForState(ConnectionState.Connected);

var channel = GetRandomChannel(client, "RTP16a");
var channel = GetRandomChannel(client, "RTN7d");
channel.Attach();
await channel.WaitForAttachedState();

var tsc = new TaskCompletionAwaiter();
client.BlockActionFromSending(ProtocolMessage.MessageAction.Presence);

var enterPresenceAwaiter = new TaskCompletionAwaiter();
ErrorInfo err = null;
bool? success = null;
channel.Presence.Enter(client.Connection.State.ToString(), (b, info) =>
channel.Presence.Enter("dummy data", (b, info) =>
{
success = b;
err = info;
tsc.SetCompleted();
});

await WaitFor(done =>
{
// Ack Queue has one presence message
if (channel.RealtimeClient.State.WaitingForAck.Count == 1)
{
done();
}
enterPresenceAwaiter.SetCompleted();
});
await client.ProcessCommands();

// No pending message queue, since QueueMessages is false
channel.RealtimeClient.State.PendingMessages.Should().HaveCount(0);

Presence.QueuedPresenceMessage[] presenceMessages = channel.Presence.PendingPresenceQueue.ToArray();
// All messages sent
channel.Presence.PendingPresenceQueue.Should().HaveCount(0);
client.State.PendingMessages.Should().HaveCount(0);

presenceMessages.Should().HaveCount(0);
// no ack received, so ack queue has one presence message
await new ConditionalAwaiter(() => channel.RealtimeClient.State.WaitingForAck.Count == 1);

await tsc.Task;
// Disconnect using QueueCommand will not retry instantly
client.Workflow.QueueCommand(SetDisconnectedStateCommand.Create(null));
await client.WaitForState(ConnectionState.Disconnected);

// No pending message queue, since QueueMessages=false
channel.RealtimeClient.State.PendingMessages.Should().HaveCount(0);
await enterPresenceAwaiter.Task;

await WaitFor(done =>
{
// Ack cleared after flushing the queue for transport disconnection, because QueueMessages=false
if (channel.RealtimeClient.State.WaitingForAck.Count == 0)
{
done();
}
});
// Fail all ack/nack, because QueueMessages=false
channel.RealtimeClient.State.WaitingForAck.Should().HaveCount(0);

success.Should().HaveValue();
success.Value.Should().BeFalse();
err.Should().NotBeNull();
err.Message.Should().Be("Clearing message AckQueue(created at connected state) because Options.QueueMessages is false");
err.Cause.InnerException.Message.Should().Be("RTP16b : error while sending message");
err.Code.Should().Be(ErrorCodes.Disconnected); // cleared because of disconnection

// clean up
client.Close();
Expand Down

0 comments on commit 9386789

Please sign in to comment.