Skip to content

Commit a6bbcb2

Browse files
committed
[ECO-5117][RTL5] Fix missing spec implementation for channel detach (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
1 parent 0ffd50c commit a6bbcb2

File tree

2 files changed

+87
-1
lines changed

2 files changed

+87
-1
lines changed

lib/src/main/java/io/ably/lib/realtime/ChannelBase.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,9 @@ private void detachImpl(CompletionListener listener) throws AblyException {
350350
default:
351351
}
352352
ConnectionManager connectionManager = ably.connection.connectionManager;
353-
if(!connectionManager.isActive())
353+
if(!connectionManager.isActive()) { // RTL5g
354354
throw AblyException.fromErrorInfo(connectionManager.getStateErrorInfo());
355+
}
355356

356357
sendDetachMessage(listener);
357358
}
@@ -609,6 +610,7 @@ public void onError(ErrorInfo reason) {
609610
detachImpl(completionListener);
610611
} catch (AblyException e) {
611612
attachTimer = null;
613+
callCompletionListenerError(listener, e.errorInfo); // RTL5g
612614
}
613615

614616
if(attachTimer == null) {

lib/src/test/java/io/ably/lib/test/realtime/RealtimeChannelTest.java

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,9 @@ public void attach_success_callback() {
945945
}
946946
}
947947

948+
/**
949+
* Spec: RTL4g
950+
*/
948951
@Test
949952
public void attach_success_callback_for_channel_in_failed_state() {
950953
AblyRealtime ably = null;
@@ -1037,6 +1040,7 @@ public void attach_fail_callback() {
10371040
/**
10381041
* When client detaches from a channel successfully after initialized state,
10391042
* verify attach {@code CompletionListener#onSuccess()} gets called.
1043+
* Spec: RTL5a
10401044
*/
10411045
@Test
10421046
public void detach_success_callback_initialized() {
@@ -1069,6 +1073,9 @@ public void detach_success_callback_initialized() {
10691073
}
10701074
}
10711075

1076+
/**
1077+
* Spec: RTL5j
1078+
*/
10721079
@Test
10731080
public void detach_success_callback_on_suspended_state() {
10741081
AblyRealtime ably = null;
@@ -1106,6 +1113,9 @@ public void detach_success_callback_on_suspended_state() {
11061113
}
11071114
}
11081115

1116+
/**
1117+
* Spec: RTL5b
1118+
*/
11091119
@Test
11101120
public void detach_failure_callback_on_failed_state() {
11111121
AblyRealtime ably = null;
@@ -1147,6 +1157,79 @@ public void detach_failure_callback_on_failed_state() {
11471157
}
11481158
}
11491159

1160+
/**
1161+
* When connection is in failed or suspended, set error in callback
1162+
* Spec: RTL5g
1163+
*/
1164+
@Test
1165+
public void detach_fail_callback_for_connection_invalid_state() {
1166+
AblyRealtime ably = null;
1167+
try {
1168+
ClientOptions opts = createOptions(testVars.keys[0].keyStr);
1169+
ably = new AblyRealtime(opts);
1170+
ConnectionWaiter connWaiter = new ConnectionWaiter(ably.connection);
1171+
1172+
/* wait until connected */
1173+
connWaiter.waitFor(ConnectionState.connected);
1174+
1175+
/* create a channel and attach */
1176+
final Channel channel = ably.channels.get("detach_failure");
1177+
ChannelWaiter channelWaiter = new ChannelWaiter(channel);
1178+
channel.attach();
1179+
channelWaiter.waitFor(ChannelState.attached);
1180+
1181+
// Simulate connection closing from outside
1182+
ably.connection.connectionManager.requestState(new ConnectionManager.StateIndication(
1183+
ConnectionState.closing,
1184+
new ErrorInfo("Connection is closing", 80001)
1185+
));
1186+
/* wait until connection closing */
1187+
connWaiter.waitFor(ConnectionState.closing);
1188+
1189+
// channel state is ATTACHED despite closing connection state
1190+
assertEquals(ChannelState.attached, channel.state);
1191+
1192+
/* detach */
1193+
Helpers.CompletionWaiter detachWaiter1 = new Helpers.CompletionWaiter();
1194+
channel.detach(detachWaiter1);
1195+
1196+
/* Verify onSuccess callback gets called */
1197+
detachWaiter1.waitFor();
1198+
assertFalse(detachWaiter1.success);
1199+
assertNotNull(detachWaiter1.error);
1200+
assertEquals("Connection is closing", detachWaiter1.error.message);
1201+
assertEquals(80001, detachWaiter1.error.code);
1202+
1203+
// Simulate connection failure
1204+
ably.connection.connectionManager.requestState(ConnectionState.failed);
1205+
/* wait until connection failed */
1206+
connWaiter.waitFor(ConnectionState.failed);
1207+
1208+
// Mock channel state to ATTACHED despite failed connection state
1209+
channelWaiter.waitFor(ChannelState.failed);
1210+
channel.state = ChannelState.attached;
1211+
assertEquals(ChannelState.attached, channel.state);
1212+
1213+
/* detach */
1214+
Helpers.CompletionWaiter detachWaiter2 = new Helpers.CompletionWaiter();
1215+
channel.detach(detachWaiter2);
1216+
1217+
/* Verify onSuccess callback gets called */
1218+
detachWaiter2.waitFor();
1219+
assertFalse(detachWaiter2.success);
1220+
assertNotNull(detachWaiter2.error);
1221+
assertEquals("Connection failed", detachWaiter2.error.message);
1222+
assertEquals(80000, detachWaiter2.error.code);
1223+
1224+
} catch (AblyException e) {
1225+
e.printStackTrace();
1226+
fail("init0: Unexpected exception instantiating library");
1227+
} finally {
1228+
if(ably != null)
1229+
ably.close();
1230+
}
1231+
}
1232+
11501233
/**
11511234
* When client detaches from a channel successfully after attached state,
11521235
* verify attach {@code CompletionListener#onSuccess()} gets called.
@@ -1184,6 +1267,7 @@ public void detach_success_callback_attached() throws AblyException {
11841267
/**
11851268
* When client detaches from a channel successfully after detaching state,
11861269
* verify attach {@code CompletionListener#onSuccess()} gets called.
1270+
* Spec: RTL5i
11871271
*/
11881272
@Test
11891273
public void detach_success_callback_detaching() throws AblyException {

0 commit comments

Comments
 (0)