Skip to content

Commit

Permalink
[ECO-5117][RTL5] Fix missing spec implementation for channel detach (…
Browse files Browse the repository at this point in the history
…RTL5g)

1. Added missing callCompletionListenerError when detachImpl throws exception
on invalid connection state
2. Added separate test case for the spec RTL5g
3. Annotated channel detach tests with appropriate spec
  • Loading branch information
sacOO7 committed Dec 17, 2024
1 parent 0ffd50c commit a6bbcb2
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 1 deletion.
4 changes: 3 additions & 1 deletion lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,9 @@ private void detachImpl(CompletionListener listener) throws AblyException {
default:
}
ConnectionManager connectionManager = ably.connection.connectionManager;
if(!connectionManager.isActive())
if(!connectionManager.isActive()) { // RTL5g
throw AblyException.fromErrorInfo(connectionManager.getStateErrorInfo());
}

sendDetachMessage(listener);
}
Expand Down Expand Up @@ -609,6 +610,7 @@ public void onError(ErrorInfo reason) {
detachImpl(completionListener);
} catch (AblyException e) {
attachTimer = null;
callCompletionListenerError(listener, e.errorInfo); // RTL5g
}

if(attachTimer == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,9 @@ public void attach_success_callback() {
}
}

/**
* Spec: RTL4g
*/
@Test
public void attach_success_callback_for_channel_in_failed_state() {
AblyRealtime ably = null;
Expand Down Expand Up @@ -1037,6 +1040,7 @@ public void attach_fail_callback() {
/**
* When client detaches from a channel successfully after initialized state,
* verify attach {@code CompletionListener#onSuccess()} gets called.
* Spec: RTL5a
*/
@Test
public void detach_success_callback_initialized() {
Expand Down Expand Up @@ -1069,6 +1073,9 @@ public void detach_success_callback_initialized() {
}
}

/**
* Spec: RTL5j
*/
@Test
public void detach_success_callback_on_suspended_state() {
AblyRealtime ably = null;
Expand Down Expand Up @@ -1106,6 +1113,9 @@ public void detach_success_callback_on_suspended_state() {
}
}

/**
* Spec: RTL5b
*/
@Test
public void detach_failure_callback_on_failed_state() {
AblyRealtime ably = null;
Expand Down Expand Up @@ -1147,6 +1157,79 @@ public void detach_failure_callback_on_failed_state() {
}
}

/**
* When connection is in failed or suspended, set error in callback
* Spec: RTL5g
*/
@Test
public void detach_fail_callback_for_connection_invalid_state() {
AblyRealtime ably = null;
try {
ClientOptions opts = createOptions(testVars.keys[0].keyStr);
ably = new AblyRealtime(opts);
ConnectionWaiter connWaiter = new ConnectionWaiter(ably.connection);

/* wait until connected */
connWaiter.waitFor(ConnectionState.connected);

/* create a channel and attach */
final Channel channel = ably.channels.get("detach_failure");
ChannelWaiter channelWaiter = new ChannelWaiter(channel);
channel.attach();
channelWaiter.waitFor(ChannelState.attached);

// Simulate connection closing from outside
ably.connection.connectionManager.requestState(new ConnectionManager.StateIndication(
ConnectionState.closing,
new ErrorInfo("Connection is closing", 80001)
));
/* wait until connection closing */
connWaiter.waitFor(ConnectionState.closing);

// channel state is ATTACHED despite closing connection state
assertEquals(ChannelState.attached, channel.state);

/* detach */
Helpers.CompletionWaiter detachWaiter1 = new Helpers.CompletionWaiter();
channel.detach(detachWaiter1);

/* Verify onSuccess callback gets called */
detachWaiter1.waitFor();
assertFalse(detachWaiter1.success);
assertNotNull(detachWaiter1.error);
assertEquals("Connection is closing", detachWaiter1.error.message);
assertEquals(80001, detachWaiter1.error.code);

// Simulate connection failure
ably.connection.connectionManager.requestState(ConnectionState.failed);
/* wait until connection failed */
connWaiter.waitFor(ConnectionState.failed);

// Mock channel state to ATTACHED despite failed connection state
channelWaiter.waitFor(ChannelState.failed);
channel.state = ChannelState.attached;
assertEquals(ChannelState.attached, channel.state);

/* detach */
Helpers.CompletionWaiter detachWaiter2 = new Helpers.CompletionWaiter();
channel.detach(detachWaiter2);

/* Verify onSuccess callback gets called */
detachWaiter2.waitFor();
assertFalse(detachWaiter2.success);
assertNotNull(detachWaiter2.error);
assertEquals("Connection failed", detachWaiter2.error.message);
assertEquals(80000, detachWaiter2.error.code);

} catch (AblyException e) {
e.printStackTrace();
fail("init0: Unexpected exception instantiating library");
} finally {
if(ably != null)
ably.close();
}
}

/**
* When client detaches from a channel successfully after attached state,
* verify attach {@code CompletionListener#onSuccess()} gets called.
Expand Down Expand Up @@ -1184,6 +1267,7 @@ public void detach_success_callback_attached() throws AblyException {
/**
* When client detaches from a channel successfully after detaching state,
* verify attach {@code CompletionListener#onSuccess()} gets called.
* Spec: RTL5i
*/
@Test
public void detach_success_callback_detaching() throws AblyException {
Expand Down

0 comments on commit a6bbcb2

Please sign in to comment.