/*
* 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.JSONObject;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import bolts.Task;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
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;
public class ParseCloudCodeControllerTest {
@Before
public void setUp() throws MalformedURLException {
ParseRESTCommand.server = new URL("https://api.parse.com/1");
}
@After
public void tearDown() {
ParseRESTCommand.server = null;
}
//region testConstructor
@Test
public void testConstructor() throws Exception {
ParseHttpClient restClient = mock(ParseHttpClient.class);
ParseCloudCodeController controller = new ParseCloudCodeController(restClient);
assertSame(restClient, controller.restClient);
}
//endregion
//region testConvertCloudResponse
@Test
public void testConvertCloudResponseNullResponse() throws Exception {
ParseHttpClient restClient = mock(ParseHttpClient.class);
ParseCloudCodeController controller = new ParseCloudCodeController(restClient);
Object result = controller.convertCloudResponse(null);
assertNull(result);
}
@Test
public void testConvertCloudResponseJsonResponseWithResultField() throws Exception {
ParseHttpClient restClient = mock(ParseHttpClient.class);
ParseCloudCodeController controller = new ParseCloudCodeController(restClient);
JSONObject response = new JSONObject();
response.put("result", "test");
Object result = controller.convertCloudResponse(response);
assertThat(result, instanceOf(String.class));
assertEquals("test", result);
}
@Test
public void testConvertCloudResponseJsonArrayResponse() throws Exception {
ParseHttpClient restClient = mock(ParseHttpClient.class);
ParseCloudCodeController controller = new ParseCloudCodeController(restClient);
JSONArray response = new JSONArray();
response.put(0, "test");
response.put(1, true);
response.put(2, 2);
Object result = controller.convertCloudResponse(response);
assertThat(result, instanceOf(List.class));
List listResult = (List)result;
assertEquals(3, listResult.size());
assertEquals("test", listResult.get(0));
assertEquals(true, listResult.get(1));
assertEquals(2, listResult.get(2));
}
//endregion
//region testCallFunctionInBackground
@Test
public void testCallFunctionInBackgroundCommand() throws Exception {
// TODO(mengyan): Verify proper command is constructed
}
@Test
public void testCallFunctionInBackgroundSuccessWithResult() throws Exception {
JSONObject json = new JSONObject();
json.put("result", "test");
String content = json.toString();
ParseHttpResponse mockResponse = new ParseHttpResponse.Builder()
.setStatusCode(200)
.setTotalSize((long) content.length())
.setContent(new ByteArrayInputStream(content.getBytes()))
.build();
ParseHttpClient restClient = mockParseHttpClientWithReponse(mockResponse);
ParseCloudCodeController controller = new ParseCloudCodeController(restClient);
Task<String> cloudCodeTask = controller.callFunctionInBackground(
"test", new HashMap<String, Object>(), "sessionToken");
ParseTaskUtils.wait(cloudCodeTask);
verify(restClient, times(1)).execute(any(ParseHttpRequest.class));
assertEquals("test", cloudCodeTask.getResult());
}
@Test
public void testCallFunctionInBackgroundSuccessWithoutResult() throws Exception {
JSONObject json = new JSONObject();
String content = json.toString();
ParseHttpResponse mockResponse = new ParseHttpResponse.Builder()
.setStatusCode(200)
.setTotalSize((long) content.length())
.setContent(new ByteArrayInputStream(content.getBytes()))
.build();
ParseHttpClient restClient = mockParseHttpClientWithReponse(mockResponse);
ParseCloudCodeController controller = new ParseCloudCodeController(restClient);
Task<String> cloudCodeTask = controller.callFunctionInBackground(
"test", new HashMap<String, Object>(), "sessionToken");
ParseTaskUtils.wait(cloudCodeTask);
verify(restClient, times(1)).execute(any(ParseHttpRequest.class));
assertNull(cloudCodeTask.getResult());
}
@Test
public void testCallFunctionInBackgroundFailure() 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());
ParseCloudCodeController controller = new ParseCloudCodeController(restClient);
Task<String> cloudCodeTask =
controller.callFunctionInBackground("test", new HashMap<String, Object>(), "sessionToken");
// Do not use ParseTaskUtils.wait() since we do not want to throw the exception
cloudCodeTask.waitForCompletion();
// TODO(mengyan): Abstract out command runner so we don't have to account for retries.
verify(restClient, times(5)).execute(any(ParseHttpRequest.class));
assertTrue(cloudCodeTask.isFaulted());
Exception error = cloudCodeTask.getError();
assertThat(error, instanceOf(ParseException.class));
assertEquals(ParseException.CONNECTION_FAILED, ((ParseException) error).getCode());
}
//endregion
private ParseHttpClient mockParseHttpClientWithReponse(ParseHttpResponse response)
throws IOException {
ParseHttpClient client = mock(ParseHttpClient.class);
when(client.execute(any(ParseHttpRequest.class))).thenReturn(response);
return client;
}
}