Java tutorial
/* * Copyright (c) 2015-present, Parse, LLC. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.parse; import com.parse.http.ParseHttpRequest; import com.parse.http.ParseHttpResponse; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricGradleTestRunner; import org.robolectric.annotation.Config; import org.skyscreamer.jsonassert.JSONCompareMode; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import bolts.Task; import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.skyscreamer.jsonassert.JSONAssert.assertEquals; // For SSLSessionCache @RunWith(RobolectricGradleTestRunner.class) @Config(constants = BuildConfig.class, sdk = 21) public class ParsePushControllerTest { //region testBuildRESTSendPushCommand @Test public void testBuildRESTSendPushCommandWithChannelSet() throws Exception { ParseHttpClient restClient = mock(ParseHttpClient.class); ParsePushController controller = new ParsePushController(restClient); // Build PushState JSONObject data = new JSONObject(); data.put(ParsePush.KEY_DATA_MESSAGE, "hello world"); List<String> expectedChannelSet = new ArrayList<String>() { { add("foo"); add("bar"); add("yarr"); } }; ParsePush.State state = new ParsePush.State.Builder().data(data).channelSet(expectedChannelSet).build(); // Build command ParseRESTCommand pushCommand = controller.buildRESTSendPushCommand(state, "sessionToken"); // Verify command JSONObject jsonParameters = pushCommand.jsonParameters; assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_EXPIRATION_TIME)); assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_EXPIRATION_INTERVAL)); // Verify device type and query assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_WHERE)); assertEquals("hello world", jsonParameters.getJSONObject(ParseRESTPushCommand.KEY_DATA).getString(ParsePush.KEY_DATA_MESSAGE)); JSONArray pushChannels = jsonParameters.getJSONArray(ParseRESTPushCommand.KEY_CHANNELS); assertEquals(new JSONArray(expectedChannelSet), pushChannels, JSONCompareMode.NON_EXTENSIBLE); } @Test public void testBuildRESTSendPushCommandWithExpirationTime() throws Exception { ParseHttpClient restClient = mock(ParseHttpClient.class); ParsePushController controller = new ParsePushController(restClient); // Build PushState JSONObject data = new JSONObject(); data.put(ParsePush.KEY_DATA_MESSAGE, "hello world"); ParsePush.State state = new ParsePush.State.Builder().data(data).expirationTime((long) 1400000000).build(); // Build command ParseRESTCommand pushCommand = controller.buildRESTSendPushCommand(state, "sessionToken"); // Verify command JSONObject jsonParameters = pushCommand.jsonParameters; assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_EXPIRATION_INTERVAL)); assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_CHANNELS)); // Verify device type and query assertEquals("{}", jsonParameters.get(ParseRESTPushCommand.KEY_WHERE).toString()); assertEquals("hello world", jsonParameters.getJSONObject(ParseRESTPushCommand.KEY_DATA).getString(ParsePush.KEY_DATA_MESSAGE)); assertEquals(1400000000, jsonParameters.getLong(ParseRESTPushCommand.KEY_EXPIRATION_TIME)); } @Test public void testBuildRESTSendPushCommandWithExpirationTimeInterval() throws Exception { ParseHttpClient restClient = mock(ParseHttpClient.class); ParsePushController controller = new ParsePushController(restClient); // Build PushState JSONObject data = new JSONObject(); data.put(ParsePush.KEY_DATA_MESSAGE, "hello world"); ParsePush.State state = new ParsePush.State.Builder().data(data).expirationTimeInterval((long) 86400) .build(); // Build command ParseRESTCommand pushCommand = controller.buildRESTSendPushCommand(state, "sessionToken"); // Verify command JSONObject jsonParameters = pushCommand.jsonParameters; assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_EXPIRATION_TIME)); assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_CHANNELS)); // Verify device type and query assertEquals("{}", jsonParameters.get(ParseRESTPushCommand.KEY_WHERE).toString()); assertEquals("hello world", jsonParameters.getJSONObject(ParseRESTPushCommand.KEY_DATA).getString(ParsePush.KEY_DATA_MESSAGE)); assertEquals(86400, jsonParameters.getLong(ParseRESTPushCommand.KEY_EXPIRATION_INTERVAL)); } @Test public void testBuildRESTSendPushCommandWithQuery() throws Exception { ParseHttpClient restClient = mock(ParseHttpClient.class); ParsePushController controller = new ParsePushController(restClient); // Build PushState JSONObject data = new JSONObject(); data.put(ParsePush.KEY_DATA_MESSAGE, "hello world"); ParseQuery<ParseInstallation> query = ParseInstallation.getQuery(); query.whereEqualTo("language", "en/US"); query.whereLessThan("version", "1.2"); ParsePush.State state = new ParsePush.State.Builder().data(data).query(query).build(); // Build command ParseRESTCommand pushCommand = controller.buildRESTSendPushCommand(state, "sessionToken"); // Verify command JSONObject jsonParameters = pushCommand.jsonParameters; assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_EXPIRATION_TIME)); assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_EXPIRATION_INTERVAL)); assertFalse(jsonParameters.getJSONObject(ParseRESTPushCommand.KEY_WHERE) .has(ParseRESTPushCommand.KEY_DEVICE_TYPE)); assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_CHANNELS)); assertEquals("hello world", jsonParameters.getJSONObject(ParseRESTPushCommand.KEY_DATA).getString(ParsePush.KEY_DATA_MESSAGE)); JSONObject pushQuery = jsonParameters.getJSONObject(ParseRESTPushCommand.KEY_WHERE); assertEquals("en/US", pushQuery.getString("language")); JSONObject inequality = pushQuery.getJSONObject("version"); assertEquals("1.2", inequality.getString("$lt")); } @Test public void testBuildRESTSendPushCommandWithPushToAndroid() throws Exception { ParseHttpClient restClient = mock(ParseHttpClient.class); ParsePushController controller = new ParsePushController(restClient); // Build PushState JSONObject data = new JSONObject(); data.put(ParsePush.KEY_DATA_MESSAGE, "hello world"); ParsePush.State state = new ParsePush.State.Builder().pushToAndroid(true).data(data).build(); // Build command ParseRESTCommand pushCommand = controller.buildRESTSendPushCommand(state, "sessionToken"); // Verify command JSONObject jsonParameters = pushCommand.jsonParameters; assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_EXPIRATION_TIME)); assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_EXPIRATION_INTERVAL)); assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_CHANNELS)); assertEquals("hello world", jsonParameters.getJSONObject(ParseRESTPushCommand.KEY_DATA).getString(ParsePush.KEY_DATA_MESSAGE)); assertEquals(ParsePushController.DEVICE_TYPE_ANDROID, jsonParameters.getJSONObject(ParseRESTPushCommand.KEY_WHERE) .optString(ParseRESTPushCommand.KEY_DEVICE_TYPE, null)); } @Test public void testBuildRESTSendPushCommandWithPushToIOS() throws Exception { ParseHttpClient restClient = mock(ParseHttpClient.class); ParsePushController controller = new ParsePushController(restClient); // Build PushState JSONObject data = new JSONObject(); data.put(ParsePush.KEY_DATA_MESSAGE, "hello world"); ParsePush.State state = new ParsePush.State.Builder().pushToIOS(true).data(data).build(); // Build command ParseRESTCommand pushCommand = controller.buildRESTSendPushCommand(state, "sessionToken"); // Verify command JSONObject jsonParameters = pushCommand.jsonParameters; assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_EXPIRATION_TIME)); assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_EXPIRATION_INTERVAL)); assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_CHANNELS)); assertEquals("hello world", jsonParameters.getJSONObject(ParseRESTPushCommand.KEY_DATA).getString(ParsePush.KEY_DATA_MESSAGE)); assertEquals(ParsePushController.DEVICE_TYPE_IOS, jsonParameters.getJSONObject(ParseRESTPushCommand.KEY_WHERE) .optString(ParseRESTPushCommand.KEY_DEVICE_TYPE, null)); } @Test public void testBuildRESTSendPushCommandWithPushToIOSAndAndroid() throws Exception { ParseHttpClient restClient = mock(ParseHttpClient.class); ParsePushController controller = new ParsePushController(restClient); // Build PushState JSONObject data = new JSONObject(); data.put(ParsePush.KEY_DATA_MESSAGE, "hello world"); ParsePush.State state = new ParsePush.State.Builder().pushToAndroid(true).pushToIOS(true).data(data) .build(); // Build command ParseRESTCommand pushCommand = controller.buildRESTSendPushCommand(state, "sessionToken"); // Verify command JSONObject jsonParameters = pushCommand.jsonParameters; assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_EXPIRATION_TIME)); assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_EXPIRATION_INTERVAL)); assertFalse(jsonParameters.has(ParseRESTPushCommand.KEY_CHANNELS)); assertEquals("hello world", jsonParameters.getJSONObject(ParseRESTPushCommand.KEY_DATA).getString(ParsePush.KEY_DATA_MESSAGE)); assertFalse(jsonParameters.getJSONObject(ParseRESTPushCommand.KEY_WHERE) .has(ParseRESTPushCommand.KEY_DEVICE_TYPE)); } //endregion //region testSendInBackground @Test public void testSendInBackgroundSuccess() throws Exception { JSONObject mockResponse = new JSONObject(); mockResponse.put("result", "OK"); ParseHttpClient restClient = mockParseHttpClientWithResponse(mockResponse, 200, "OK"); ParsePushController controller = new ParsePushController(restClient); JSONObject data = new JSONObject(); data.put(ParsePush.KEY_DATA_MESSAGE, "hello world"); ParsePush.State state = new ParsePush.State.Builder().data(data).build(); Task<Void> pushTask = controller.sendInBackground(state, "sessionToken"); // Verify task complete ParseTaskUtils.wait(pushTask); // Verify httpclient execute encough times verify(restClient, times(1)).execute(any(ParseHttpRequest.class)); } @Test public void testSendInBackgroundFailWithIOException() throws Exception { // TODO(mengyan): Remove once we no longer rely on retry logic. ParseRequest.setDefaultInitialRetryDelay(1L); ParseHttpClient restClient = mock(ParseHttpClient.class); when(restClient.execute(any(ParseHttpRequest.class))).thenThrow(new IOException()); ParsePushController controller = new ParsePushController(restClient); JSONObject data = new JSONObject(); data.put(ParsePush.KEY_DATA_MESSAGE, "hello world"); ParsePush.State state = new ParsePush.State.Builder().data(data).build(); Task<Void> pushTask = controller.sendInBackground(state, "sessionToken"); // Do not use ParseTaskUtils.wait() since we do not want to throw the exception pushTask.waitForCompletion(); // Verify httpClient is tried enough times // TODO(mengyan): Abstract out command runner so we don't have to account for retries. verify(restClient, times(5)).execute(any(ParseHttpRequest.class)); assertTrue(pushTask.isFaulted()); Exception error = pushTask.getError(); assertThat(error, instanceOf(ParseException.class)); assertEquals(ParseException.CONNECTION_FAILED, ((ParseException) error).getCode()); } //endregion private ParseHttpClient mockParseHttpClientWithResponse(JSONObject content, int statusCode, String reasonPhrase) throws IOException { byte[] contentBytes = content.toString().getBytes(); ParseHttpResponse response = new ParseHttpResponse.Builder() .setContent(new ByteArrayInputStream(contentBytes)).setStatusCode(statusCode) .setTotalSize(contentBytes.length).setContentType("application/json").build(); ParseHttpClient client = mock(ParseHttpClient.class); when(client.execute(any(ParseHttpRequest.class))).thenReturn(response); return client; } private static boolean containsString(JSONArray array, String value) throws JSONException { for (int i = 0; i < array.length(); i++) { Object element = array.get(i); if (element instanceof String && element.equals(value)) { return true; } } return false; } }