Skip to content

Commit 1f2d830

Browse files
authored
Merge branch 'tasks/initial-project' into unswallow-subscribe-errors
2 parents bbf1d9e + d055f35 commit 1f2d830

File tree

3 files changed

+120
-31
lines changed

3 files changed

+120
-31
lines changed

ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientImpl.java

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.parse;
22

3-
43
import android.util.Log;
54
import android.util.SparseArray;
65

@@ -179,7 +178,6 @@ private void parseMessage(String message) throws LiveQueryException {
179178
} catch (JSONException e) {
180179
throw new LiveQueryException.InvalidResponseException(message);
181180
}
182-
183181
}
184182

185183
private void handleSubscribedEvent(JSONObject jsonObject) throws JSONException {
@@ -224,17 +222,25 @@ private Subscription<T> subscriptionForRequestId(int requestId) {
224222
}
225223

226224
private void sendSubscription(final Subscription<T> subscription) {
227-
SubscribeClientOperation<T> op = new SubscribeClientOperation<>(subscription.getRequestId(), subscription.getQueryState());
228-
// dispatch errors
229-
sendOperationAsync(op).continueWith(new Continuation<Void, Void>() {
230-
public Void then(Task<Void> task) {
231-
Exception error = task.getError();
232-
if (error != null) {
233-
if (error instanceof RuntimeException) {
234-
subscription.didEncounter(new LiveQueryException.UnknownException(
235-
"Error when subscribing", (RuntimeException) error), subscription.getQuery());
225+
ParseUser.getCurrentSessionTokenAsync().onSuccess(new Continuation<String, Void>() {
226+
@Override
227+
public Void then(Task<String> task) throws Exception {
228+
String sessionToken = task.getResult();
229+
SubscribeClientOperation<T> op = new SubscribeClientOperation<>(subscription.getRequestId(), subscription.getQueryState(), sessionToken);
230+
231+
// dispatch errors
232+
sendOperationAsync(op).continueWith(new Continuation<Void, Void>() {
233+
public Void then(Task<Void> task) {
234+
Exception error = task.getError();
235+
if (error != null) {
236+
if (error instanceof RuntimeException) {
237+
subscription.didEncounter(new LiveQueryException.UnknownException(
238+
"Error when subscribing", (RuntimeException) error), subscription.getQuery());
239+
}
240+
}
241+
return null;
236242
}
237-
}
243+
});
238244
return null;
239245
}
240246
});
@@ -249,7 +255,13 @@ private WebSocketClient.WebSocketClientCallback getWebSocketClientCallback() {
249255
@Override
250256
public void onOpen() {
251257
Log.v(LOG_TAG, "Socket opened");
252-
sendOperationAsync(new ConnectClientOperation(applicationId, "")).continueWith(new Continuation<Void, Void>() {
258+
ParseUser.getCurrentSessionTokenAsync().onSuccessTask(new Continuation<String, Task<Void>>() {
259+
@Override
260+
public Task<Void> then(Task<String> task) throws Exception {
261+
String sessionToken = task.getResult();
262+
return sendOperationAsync(new ConnectClientOperation(applicationId, sessionToken));
263+
}
264+
}).continueWith(new Continuation<Void, Void>() {
253265
public Void then(Task<Void> task) {
254266
Exception error = task.getError();
255267
if (error != null) {
@@ -290,5 +302,4 @@ public void stateChanged() {
290302
}
291303
};
292304
}
293-
294305
}

ParseLiveQuery/src/main/java/com/parse/SubscribeClientOperation.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,22 @@
77

88
private final int requestId;
99
private final ParseQuery.State<T> state;
10+
private final String sessionToken;
1011

11-
/* package */ SubscribeClientOperation(int requestId, final ParseQuery.State<T> state) {
12+
/* package */ SubscribeClientOperation(int requestId, ParseQuery.State<T> state, String sessionToken) {
1213
this.requestId = requestId;
1314
this.state = state;
15+
this.sessionToken = sessionToken;
1416
}
1517

1618
@Override
1719
/* package */ JSONObject getJSONObjectRepresentation() throws JSONException {
1820
JSONObject jsonObject = new JSONObject();
1921
jsonObject.put("op", "subscribe");
2022
jsonObject.put("requestId", requestId);
23+
jsonObject.put("sessionToken", sessionToken);
2124

22-
JSONObject queryJsonObject = state.toJSON(NoObjectsEncoder.get());
25+
JSONObject queryJsonObject = state.toJSON(PointerEncoder.get());
2326

2427
jsonObject.put("query", queryJsonObject);
2528

ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java

Lines changed: 90 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,25 @@
77
import org.junit.Test;
88
import org.junit.runner.RunWith;
99
import org.mockito.ArgumentCaptor;
10+
import org.mockito.invocation.InvocationOnMock;
11+
import org.mockito.stubbing.Answer;
1012
import org.robolectric.RobolectricGradleTestRunner;
1113
import org.robolectric.annotation.Config;
1214

1315
import java.net.URI;
1416
import java.util.concurrent.Executor;
1517

18+
import bolts.Task;
19+
1620
import static junit.framework.Assert.assertEquals;
1721
import static junit.framework.Assert.assertNotNull;
1822
import static junit.framework.Assert.assertTrue;
23+
import static org.mockito.AdditionalMatchers.and;
24+
import static org.mockito.AdditionalMatchers.not;
1925
import static org.mockito.Matchers.any;
2026
import static org.mockito.Matchers.anyString;
27+
import static org.mockito.Matchers.anyBoolean;
28+
import static org.mockito.Matchers.contains;
2129
import static org.mockito.Matchers.eq;
2230
import static org.mockito.Mockito.mock;
2331
import static org.mockito.Mockito.never;
@@ -33,9 +41,29 @@ public class TestParseLiveQueryClient {
3341
private WebSocketClient.WebSocketClientCallback webSocketClientCallback;
3442
private ParseLiveQueryClient<ParseObject> parseLiveQueryClient;
3543

44+
private ParseUser mockUser;
45+
3646
@Before
3747
public void setUp() throws Exception {
3848
ParsePlugins.initialize("1234", "1234");
49+
50+
// Register a mock currentUserController to make getCurrentUser work
51+
mockUser = mock(ParseUser.class);
52+
ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class);
53+
when(currentUserController.getAsync(anyBoolean())).thenAnswer(new Answer<Task<ParseUser>>() {
54+
@Override
55+
public Task<ParseUser> answer(InvocationOnMock invocation) throws Throwable {
56+
return Task.forResult(mockUser);
57+
}
58+
});
59+
when(currentUserController.getCurrentSessionTokenAsync()).thenAnswer(new Answer<Task<String>>() {
60+
@Override
61+
public Task<String> answer(InvocationOnMock invocation) throws Throwable {
62+
return Task.forResult(mockUser.getSessionToken());
63+
}
64+
});
65+
ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController);
66+
3967
parseLiveQueryClient = ParseLiveQueryClient.Factory.getClient(new URI(""), new WebSocketClientFactory() {
4068
@Override
4169
public WebSocketClient createInstance(WebSocketClient.WebSocketClientCallback webSocketClientCallback, URI hostUrl) {
@@ -71,12 +99,14 @@ public void testSubscribeWhenSubscribedToCallback() throws Exception {
7199
@Test
72100
public void testUnsubscribeWhenSubscribedToCallback() throws Exception {
73101
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
74-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
102+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
103+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
75104

76105
parseLiveQueryClient.unsubscribe(parseQuery);
77106
verify(webSocketClient, times(1)).send(any(String.class));
78107

79-
SubscriptionHandling.HandleUnsubscribeCallback<ParseObject> unsubscribeMockCallback = mock(SubscriptionHandling.HandleUnsubscribeCallback.class);
108+
SubscriptionHandling.HandleUnsubscribeCallback<ParseObject> unsubscribeMockCallback = mock(
109+
SubscriptionHandling.HandleUnsubscribeCallback.class);
80110
subscriptionHandling.handleUnsubscribe(unsubscribeMockCallback);
81111
webSocketClientCallback.onMessage(createUnsubscribedMessage(subscriptionHandling.getRequestId()).toString());
82112

@@ -114,7 +144,8 @@ public void testErrorWhileSubscribing() throws Exception {
114144
@Test
115145
public void testErrorWhenSubscribedToCallback() throws Exception {
116146
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
117-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
147+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
148+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
118149

119150
SubscriptionHandling.HandleErrorCallback<ParseObject> errorMockCallback = mock(SubscriptionHandling.HandleErrorCallback.class);
120151
subscriptionHandling.handleError(errorMockCallback);
@@ -135,7 +166,8 @@ public void testErrorWhenSubscribedToCallback() throws Exception {
135166
@Test
136167
public void testCreateEventWhenSubscribedToCallback() throws Exception {
137168
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
138-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
169+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
170+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
139171

140172
SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback = mock(SubscriptionHandling.HandleEventCallback.class);
141173
subscriptionHandling.handleEvent(SubscriptionHandling.Event.CREATE, eventMockCallback);
@@ -151,7 +183,8 @@ public void testCreateEventWhenSubscribedToCallback() throws Exception {
151183
@Test
152184
public void testEnterEventWhenSubscribedToCallback() throws Exception {
153185
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
154-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
186+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
187+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
155188

156189
SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback = mock(SubscriptionHandling.HandleEventCallback.class);
157190
subscriptionHandling.handleEvent(SubscriptionHandling.Event.ENTER, eventMockCallback);
@@ -167,7 +200,8 @@ public void testEnterEventWhenSubscribedToCallback() throws Exception {
167200
@Test
168201
public void testUpdateEventWhenSubscribedToCallback() throws Exception {
169202
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
170-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
203+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
204+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
171205

172206
SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback = mock(SubscriptionHandling.HandleEventCallback.class);
173207
subscriptionHandling.handleEvent(SubscriptionHandling.Event.UPDATE, eventMockCallback);
@@ -183,7 +217,8 @@ public void testUpdateEventWhenSubscribedToCallback() throws Exception {
183217
@Test
184218
public void testLeaveEventWhenSubscribedToCallback() throws Exception {
185219
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
186-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
220+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
221+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
187222

188223
SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback = mock(SubscriptionHandling.HandleEventCallback.class);
189224
subscriptionHandling.handleEvent(SubscriptionHandling.Event.LEAVE, eventMockCallback);
@@ -196,11 +231,11 @@ public void testLeaveEventWhenSubscribedToCallback() throws Exception {
196231
validateSameObject(eventMockCallback, parseQuery, parseObject);
197232
}
198233

199-
200234
@Test
201235
public void testDeleteEventWhenSubscribedToCallback() throws Exception {
202236
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
203-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
237+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
238+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
204239

205240
SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback = mock(SubscriptionHandling.HandleEventCallback.class);
206241
subscriptionHandling.handleEvent(SubscriptionHandling.Event.DELETE, eventMockCallback);
@@ -216,7 +251,8 @@ public void testDeleteEventWhenSubscribedToCallback() throws Exception {
216251
@Test
217252
public void testCreateEventWhenSubscribedToAnyCallback() throws Exception {
218253
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
219-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
254+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
255+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
220256

221257
SubscriptionHandling.HandleEventsCallback<ParseObject> eventsMockCallback = mock(SubscriptionHandling.HandleEventsCallback.class);
222258
subscriptionHandling.handleEvents(eventsMockCallback);
@@ -237,12 +273,14 @@ public void testCreateEventWhenSubscribedToAnyCallback() throws Exception {
237273
@Test
238274
public void testSubscriptionStoppedAfterUnsubscribe() throws Exception {
239275
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
240-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
276+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
277+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
241278

242279
SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback = mock(SubscriptionHandling.HandleEventCallback.class);
243280
subscriptionHandling.handleEvent(SubscriptionHandling.Event.CREATE, eventMockCallback);
244281

245-
SubscriptionHandling.HandleUnsubscribeCallback<ParseObject> unsubscribeMockCallback = mock(SubscriptionHandling.HandleUnsubscribeCallback.class);
282+
SubscriptionHandling.HandleUnsubscribeCallback<ParseObject> unsubscribeMockCallback = mock(
283+
SubscriptionHandling.HandleUnsubscribeCallback.class);
246284
subscriptionHandling.handleUnsubscribe(unsubscribeMockCallback);
247285

248286
parseLiveQueryClient.unsubscribe(parseQuery);
@@ -271,14 +309,52 @@ public void testSubscriptionReplayedAfterReconnect() throws Exception {
271309
verify(webSocketClient, times(2)).send(any(String.class));
272310
}
273311

312+
@Test
313+
public void testSessionTokenSentOnConnect() {
314+
when(mockUser.getSessionToken()).thenReturn("the token");
315+
parseLiveQueryClient.reconnect();
316+
webSocketClientCallback.onOpen();
317+
verify(webSocketClient, times(1)).send(contains("\"sessionToken\":\"the token\""));
318+
}
274319

275-
private SubscriptionHandling<ParseObject> createSubscription(ParseQuery<ParseObject> parseQuery, SubscriptionHandling.HandleSubscribeCallback<ParseObject> subscribeMockCallback) throws Exception {
320+
@Test
321+
public void testEmptySessionTokenOnConnect() {
322+
parseLiveQueryClient.reconnect();
323+
webSocketClientCallback.onOpen();
324+
verify(webSocketClient, times(1)).send(not(contains("\"sessionToken\":")));
325+
}
326+
327+
@Test
328+
public void testSessionTokenSentOnSubscribe() {
329+
when(mockUser.getSessionToken()).thenReturn("the token");
330+
when(webSocketClient.getState()).thenReturn(WebSocketClient.State.CONNECTED);
331+
parseLiveQueryClient.subscribe(ParseQuery.getQuery("Test"));
332+
verify(webSocketClient, times(1)).send(and(
333+
contains("\"op\":\"subscribe\""),
334+
contains("\"sessionToken\":\"the token\"")));
335+
}
336+
337+
@Test
338+
public void testEmptySessionTokenOnSubscribe() {
339+
when(mockUser.getSessionToken()).thenReturn("the token");
340+
when(webSocketClient.getState()).thenReturn(WebSocketClient.State.CONNECTED);
341+
parseLiveQueryClient.subscribe(ParseQuery.getQuery("Test"));
342+
verify(webSocketClient, times(1)).send(contains("\"op\":\"connect\""));
343+
verify(webSocketClient, times(1)).send(and(
344+
contains("\"op\":\"subscribe\""),
345+
contains("\"sessionToken\":\"the token\"")));
346+
}
347+
348+
private SubscriptionHandling<ParseObject> createSubscription(ParseQuery<ParseObject> parseQuery,
349+
SubscriptionHandling.HandleSubscribeCallback<ParseObject> subscribeMockCallback) throws Exception {
276350
SubscriptionHandling<ParseObject> subscriptionHandling = parseLiveQueryClient.subscribe(parseQuery).handleSubscribe(subscribeMockCallback);
277351
webSocketClientCallback.onMessage(createSubscribedMessage(subscriptionHandling.getRequestId()).toString());
278352
return subscriptionHandling;
279353
}
280354

281-
private void validateSameObject(SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback, ParseQuery<ParseObject> parseQuery, ParseObject originalParseObject) {
355+
private void validateSameObject(SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback,
356+
ParseQuery<ParseObject> parseQuery,
357+
ParseObject originalParseObject) {
282358
ArgumentCaptor<ParseObject> objectCaptor = ArgumentCaptor.forClass(ParseObject.class);
283359
verify(eventMockCallback, times(1)).onEvent(eq(parseQuery), objectCaptor.capture());
284360

@@ -367,5 +443,4 @@ private static JSONObject createObjectDeleteMessage(int requestId, ParseObject p
367443
jsonObject.put("object", PointerEncoder.get().encodeRelatedObject(parseObject));
368444
return jsonObject;
369445
}
370-
371446
}

0 commit comments

Comments
 (0)