/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
* copy, modify, and distribute this software in source code or binary form for use
* in connection with the web services and APIs provided by Facebook.
*
* As with any software that integrates with the Facebook platform, your use of
* this software is subject to the Facebook Developer Principles and Policies
* [http://developers.facebook.com/policy/]. This copyright notice shall be
* included in all copies or substantial portions of the software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.facebook;
import android.graphics.Bitmap;
import android.test.suitebuilder.annotation.LargeTest;
import com.facebook.share.internal.ShareInternalUtility;
import org.json.JSONObject;
import java.io.IOException;
import java.lang.Override;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class BatchRequestTests extends FacebookTestCase {
protected void setUp() throws Exception {
super.setUp();
// Tests that need this set should explicitly set it.
GraphRequest.setDefaultBatchApplicationId(null);
}
protected String[] getDefaultPermissions()
{
return new String[] { "email", "publish_actions", "read_stream" };
};
@LargeTest
public void testCreateNonemptyRequestBatch() {
GraphRequest meRequest = GraphRequest.newMeRequest(null, null);
GraphRequestBatch batch = new GraphRequestBatch(new GraphRequest[] { meRequest, meRequest });
assertEquals(2, batch.size());
assertEquals(meRequest, batch.get(0));
assertEquals(meRequest, batch.get(1));
}
@LargeTest
public void testBatchWithoutAppIDIsError() {
GraphRequest request1 = new GraphRequest(null, "TourEiffel", null, null, new ExpectFailureCallback());
GraphRequest request2 = new GraphRequest(null, "SpaceNeedle", null, null, new ExpectFailureCallback());
GraphRequest.executeBatchAndWait(request1, request2);
}
@LargeTest
public void testExecuteBatchRequestsPathEncoding() throws IOException {
// ensures that paths passed to batch requests are encoded properly before
// we send it up to the server
final AccessToken accessToken = getAccessTokenForSharedUser();
GraphRequest request1 = new GraphRequest(accessToken, "TourEiffel");
request1.setBatchEntryName("eiffel");
request1.setBatchEntryOmitResultOnSuccess(false);
GraphRequest request2 = new GraphRequest(accessToken, "{result=eiffel:$.id}");
List<GraphResponse> responses = GraphRequest.executeBatchAndWait(request1, request2);
assertEquals(2, responses.size());
assertTrue(responses.get(0).getError() == null);
assertTrue(responses.get(1).getError() == null);
JSONObject eiffelTower1 = responses.get(0).getJSONObject();
JSONObject eiffelTower2 = responses.get(1).getJSONObject();
assertTrue(eiffelTower1 != null);
assertTrue(eiffelTower2 != null);
assertEquals("Paris", eiffelTower1.optJSONObject("location").optString("city"));
assertEquals("Paris", eiffelTower2.optJSONObject("location").optString("city"));
}
@LargeTest
public void testExecuteBatchedGets() throws IOException {
final AccessToken accessToken = getAccessTokenForSharedUser();
GraphRequest request1 = new GraphRequest(accessToken, "TourEiffel");
GraphRequest request2 = new GraphRequest(accessToken, "SpaceNeedle");
List<GraphResponse> responses = GraphRequest.executeBatchAndWait(request1, request2);
assertEquals(2, responses.size());
assertTrue(responses.get(0).getError() == null);
assertTrue(responses.get(1).getError() == null);
JSONObject eiffelTower = responses.get(0).getJSONObject();
JSONObject spaceNeedle = responses.get(1).getJSONObject();
assertTrue(eiffelTower != null);
assertTrue(spaceNeedle != null);
assertEquals("Paris", eiffelTower.optJSONObject("location").optString("city"));
assertEquals("Seattle", spaceNeedle.optJSONObject("location").optString("city"));
}
@LargeTest
public void testFacebookErrorResponsesCreateErrors() {
setBatchApplicationIdForTestApp();
GraphRequest request1 = new GraphRequest(null, "somestringthatshouldneverbeavalidfobjectid");
GraphRequest request2 = new GraphRequest(null, "someotherstringthatshouldneverbeavalidfobjectid");
List<GraphResponse> responses = GraphRequest.executeBatchAndWait(request1, request2);
assertEquals(2, responses.size());
assertTrue(responses.get(0).getError() != null);
assertTrue(responses.get(1).getError() != null);
FacebookRequestError error = responses.get(0).getError();
assertTrue(error.getException() instanceof FacebookServiceException);
assertTrue(error.getErrorType() != null);
assertTrue(error.getErrorCode() != FacebookRequestError.INVALID_ERROR_CODE);
}
@LargeTest
public void testBatchPostStatusUpdate() {
final AccessToken accessToken = getAccessTokenForSharedUser();
JSONObject statusUpdate1 = createStatusUpdate("1");
JSONObject statusUpdate2 = createStatusUpdate("2");
GraphRequest postRequest1 = GraphRequest.newPostRequest(accessToken, "me/feed", statusUpdate1, null);
postRequest1.setBatchEntryName("postRequest1");
postRequest1.setBatchEntryOmitResultOnSuccess(false);
GraphRequest postRequest2 = GraphRequest.newPostRequest(accessToken, "me/feed", statusUpdate2, null);
postRequest2.setBatchEntryName("postRequest2");
postRequest2.setBatchEntryOmitResultOnSuccess(false);
GraphRequest getRequest1 = new GraphRequest(accessToken, "{result=postRequest1:$.id}");
GraphRequest getRequest2 = new GraphRequest(accessToken, "{result=postRequest2:$.id}");
List<GraphResponse> responses = GraphRequest.executeBatchAndWait(postRequest1, postRequest2, getRequest1, getRequest2);
assertNotNull(responses);
assertEquals(4, responses.size());
assertNoErrors(responses);
JSONObject retrievedStatusUpdate1 = responses.get(2).getJSONObject();
JSONObject retrievedStatusUpdate2 = responses.get(3).getJSONObject();
assertNotNull(retrievedStatusUpdate1);
assertNotNull(retrievedStatusUpdate2);
assertEquals(statusUpdate1.optString("message"), retrievedStatusUpdate1.optString("message"));
assertEquals(statusUpdate2.optString("message"), retrievedStatusUpdate2.optString("message"));
}
@LargeTest
public void testTwoDifferentAccessTokens() {
final AccessToken accessToken1 = getAccessTokenForSharedUser();
final AccessToken accessToken2 = getAccessTokenForSharedUser(SECOND_TEST_USER_TAG);
GraphRequest request1 = GraphRequest.newMeRequest(accessToken1, null);
GraphRequest request2 = GraphRequest.newMeRequest(accessToken2, null);
List<GraphResponse> responses = GraphRequest.executeBatchAndWait(request1, request2);
assertNotNull(responses);
assertEquals(2, responses.size());
JSONObject user1 = responses.get(0).getJSONObject();
JSONObject user2 = responses.get(1).getJSONObject();
assertNotNull(user1);
assertNotNull(user2);
assertFalse(user1.optString("id").equals(user2.optString("id")));
assertEquals(accessToken1.getUserId(), user1.optString("id"));
assertEquals(accessToken2.getUserId(), user2.optString("id"));
}
@LargeTest
public void testBatchWithValidSessionAndNoSession() {
final AccessToken accessToken = getAccessTokenForSharedUser();
GraphRequest request1 = new GraphRequest(accessToken, "me");
GraphRequest request2 = new GraphRequest(null, "me");
List<GraphResponse> responses = GraphRequest.executeBatchAndWait(request1, request2);
assertNotNull(responses);
assertEquals(2, responses.size());
JSONObject user1 = responses.get(0).getJSONObject();
JSONObject user2 = responses.get(1).getJSONObject();
assertNotNull(user1);
assertNull(user2);
assertEquals(accessToken.getUserId(), user1.optString("id"));
}
@LargeTest
public void testBatchWithNoSessionAndValidSession() {
final AccessToken accessToken = getAccessTokenForSharedUser();
GraphRequest request1 = new GraphRequest(null, "me");
GraphRequest request2 = new GraphRequest(accessToken, "me");
List<GraphResponse> responses = GraphRequest.executeBatchAndWait(request1, request2);
assertNotNull(responses);
assertEquals(2, responses.size());
JSONObject user1 = responses.get(0).getJSONObject();
JSONObject user2 = responses.get(1).getJSONObject();
assertNull(user1);
assertNotNull(user2);
assertEquals(accessToken.getUserId(), user2.optString("id"));
}
@LargeTest
public void testMixedSuccessAndFailure() {
final AccessToken accessToken = getAccessTokenForSharedUser();
final int NUM_REQUESTS = 8;
GraphRequest[] requests = new GraphRequest[NUM_REQUESTS];
for (int i = 0; i < NUM_REQUESTS; ++i) {
boolean shouldSucceed = (i % 2) == 1;
requests[i] = new GraphRequest(accessToken, shouldSucceed ? "me" : "-1");
}
List<GraphResponse> responses = GraphRequest.executeBatchAndWait(requests);
assertNotNull(responses);
assertEquals(NUM_REQUESTS, responses.size());
for (int i = 0; i < NUM_REQUESTS; ++i) {
boolean shouldSucceed = (i % 2) == 1;
GraphResponse response = responses.get(i);
assertNotNull(response);
if (shouldSucceed) {
assertNull(response.getError());
assertNotNull(response.getJSONObject());
} else {
assertNotNull(response.getError());
assertNull(response.getJSONObject());
}
}
}
@LargeTest
public void testBatchUploadPhoto() {
final AccessToken accessToken = getAccessTokenForSharedUserWithPermissions(null,
"user_photos", "publish_actions");
final int image1Size = 120;
final int image2Size = 150;
Bitmap bitmap1 = createTestBitmap(image1Size);
Bitmap bitmap2 = createTestBitmap(image2Size);
GraphRequest uploadRequest1 = ShareInternalUtility.newUploadPhotoRequest(
accessToken,
bitmap1,
null);
uploadRequest1.setBatchEntryName("uploadRequest1");
GraphRequest uploadRequest2 = ShareInternalUtility.newUploadPhotoRequest(
accessToken,
bitmap2,
null);
uploadRequest2.setBatchEntryName("uploadRequest2");
GraphRequest getRequest1 = new GraphRequest(accessToken, "{result=uploadRequest1:$.id}");
GraphRequest getRequest2 = new GraphRequest(accessToken, "{result=uploadRequest2:$.id}");
List<GraphResponse> responses = GraphRequest.executeBatchAndWait(
uploadRequest1,
uploadRequest2,
getRequest1,
getRequest2);
assertNotNull(responses);
assertEquals(4, responses.size());
assertNoErrors(responses);
JSONObject retrievedPhoto1 = responses.get(2).getJSONObject();
JSONObject retrievedPhoto2 = responses.get(3).getJSONObject();
assertNotNull(retrievedPhoto1);
assertNotNull(retrievedPhoto2);
assertEquals(image1Size, retrievedPhoto1.optInt("width"));
assertEquals(image2Size, retrievedPhoto2.optInt("width"));
}
@LargeTest
public void testCallbacksAreCalled() {
setBatchApplicationIdForTestApp();
ArrayList<GraphRequest> requests = new ArrayList<GraphRequest>();
final ArrayList<Boolean> calledBack = new ArrayList<Boolean>();
final int NUM_REQUESTS = 4;
for (int i = 0; i < NUM_REQUESTS; ++i) {
GraphRequest request = new GraphRequest(null, "4");
request.setCallback(new GraphRequest.Callback() {
@Override
public void onCompleted(GraphResponse response) {
calledBack.add(true);
}
});
requests.add(request);
}
List<GraphResponse> responses = GraphRequest.executeBatchAndWait(requests);
assertNotNull(responses);
assertTrue(calledBack.size() == NUM_REQUESTS);
}
@LargeTest
public void testExplicitDependencyDefaultsToOmitFirstResponse() {
final AccessToken accessToken = getAccessTokenForSharedUser();
GraphRequest requestMe = GraphRequest.newMeRequest(accessToken, null);
requestMe.setBatchEntryName("me_request");
GraphRequest requestMyFriends = GraphRequest.newMyFriendsRequest(accessToken, null);
requestMyFriends.setBatchEntryDependsOn("me_request");
List<GraphResponse> responses = GraphRequest.executeBatchAndWait(requestMe, requestMyFriends);
GraphResponse meResponse = responses.get(0);
GraphResponse myFriendsResponse = responses.get(1);
assertNull(meResponse.getJSONObject());
assertNotNull(myFriendsResponse.getJSONObject());
}
@LargeTest
public void testExplicitDependencyCanIncludeFirstResponse() {
final AccessToken accessToken = getAccessTokenForSharedUser();
GraphRequest requestMe = GraphRequest.newMeRequest(accessToken, null);
requestMe.setBatchEntryName("me_request");
requestMe.setBatchEntryOmitResultOnSuccess(false);
GraphRequest requestMyFriends = GraphRequest.newMyFriendsRequest(accessToken, null);
requestMyFriends.setBatchEntryDependsOn("me_request");
List<GraphResponse> responses = GraphRequest.executeBatchAndWait(requestMe, requestMyFriends);
GraphResponse meResponse = responses.get(0);
GraphResponse myFriendsResponse = responses.get(1);
assertNotNull(meResponse.getJSONObject());
assertNotNull(myFriendsResponse.getJSONObject());
}
@LargeTest
public void testAddAndRemoveBatchCallbacks() {
GraphRequestBatch batch = new GraphRequestBatch();
GraphRequestBatch.Callback callback1 = new GraphRequestBatch.Callback() {
@Override
public void onBatchCompleted(GraphRequestBatch batch) {
}
};
GraphRequestBatch.Callback callback2 = new GraphRequestBatch.Callback() {
@Override
public void onBatchCompleted(GraphRequestBatch batch) {
}
};
batch.addCallback(callback1);
batch.addCallback(callback2);
assertEquals(2, batch.getCallbacks().size());
batch.removeCallback(callback1);
batch.removeCallback(callback2);
assertEquals(0, batch.getCallbacks().size());
}
@LargeTest
public void testBatchCallbackIsCalled() {
final AtomicInteger count = new AtomicInteger();
GraphRequest request1 = GraphRequest.newGraphPathRequest(null, "4", new GraphRequest.Callback() {
@Override
public void onCompleted(GraphResponse response) {
count.incrementAndGet();
}
});
GraphRequest request2 = GraphRequest.newGraphPathRequest(null, "4", new GraphRequest.Callback() {
@Override
public void onCompleted(GraphResponse response) {
count.incrementAndGet();
}
});
GraphRequestBatch batch = new GraphRequestBatch(request1, request2);
batch.addCallback(new GraphRequestBatch.Callback() {
@Override
public void onBatchCompleted(GraphRequestBatch batch) {
count.incrementAndGet();
}
});
batch.executeAndWait();
assertEquals(3, count.get());
}
@LargeTest
public void testBatchOnProgressCallbackIsCalled() {
final AtomicInteger count = new AtomicInteger();
final AccessToken accessToken = getAccessTokenForSharedUser();
String appId = getApplicationId();
GraphRequest.setDefaultBatchApplicationId(appId);
GraphRequest request1 = GraphRequest.newGraphPathRequest(accessToken, "4", null);
assertNotNull(request1);
GraphRequest request2 = GraphRequest.newGraphPathRequest(accessToken, "4", null);
assertNotNull(request2);
GraphRequestBatch batch = new GraphRequestBatch(request1, request2);
batch.addCallback(new GraphRequestBatch.OnProgressCallback() {
@Override
public void onBatchCompleted(GraphRequestBatch batch) {
}
@Override
public void onBatchProgress(GraphRequestBatch batch, long current, long max) {
count.incrementAndGet();
}
});
batch.executeAndWait();
assertEquals(1, count.get());
}
@LargeTest
public void testBatchLastOnProgressCallbackIsCalledOnce() {
final AtomicInteger count = new AtomicInteger();
final AccessToken accessToken = getAccessTokenForSharedUser();
String appId = getApplicationId();
GraphRequest.setDefaultBatchApplicationId(appId);
GraphRequest request1 = GraphRequest.newGraphPathRequest(accessToken, "4", null);
assertNotNull(request1);
GraphRequest request2 = GraphRequest.newGraphPathRequest(accessToken, "4", null);
assertNotNull(request2);
GraphRequestBatch batch = new GraphRequestBatch(request1, request2);
batch.addCallback(new GraphRequestBatch.OnProgressCallback() {
@Override
public void onBatchCompleted(GraphRequestBatch batch) {
}
@Override
public void onBatchProgress(GraphRequestBatch batch, long current, long max) {
if (current == max) {
count.incrementAndGet();
}
else if (current > max) {
count.set(0);
}
}
});
batch.executeAndWait();
assertEquals(1, count.get());
}
@LargeTest
public void testMixedBatchCallbacks() {
final AtomicInteger requestProgressCount = new AtomicInteger();
final AtomicInteger requestCompletedCount = new AtomicInteger();
final AtomicInteger batchProgressCount = new AtomicInteger();
final AtomicInteger batchCompletedCount = new AtomicInteger();
final AccessToken accessToken = getAccessTokenForSharedUser();
String appId = getApplicationId();
GraphRequest.setDefaultBatchApplicationId(appId);
GraphRequest request1 = GraphRequest.newGraphPathRequest(
null, "4", new GraphRequest.OnProgressCallback() {
@Override
public void onCompleted(GraphResponse response) {
requestCompletedCount.incrementAndGet();
}
@Override
public void onProgress(long current, long max) {
if (current == max) {
requestProgressCount.incrementAndGet();
}
else if (current > max) {
requestProgressCount.set(0);
}
}
});
assertNotNull(request1);
GraphRequest request2 = GraphRequest.newGraphPathRequest(null, "4", null);
assertNotNull(request2);
GraphRequestBatch batch = new GraphRequestBatch(request1, request2);
batch.addCallback(new GraphRequestBatch.OnProgressCallback() {
@Override
public void onBatchCompleted(GraphRequestBatch batch) {
batchCompletedCount.incrementAndGet();
}
@Override
public void onBatchProgress(GraphRequestBatch batch, long current, long max) {
if (current == max) {
batchProgressCount.incrementAndGet();
} else if (current > max) {
batchProgressCount.set(0);
}
}
});
batch.executeAndWait();
assertEquals(1, requestProgressCount.get());
assertEquals(1, requestCompletedCount.get());
assertEquals(1, batchProgressCount.get());
assertEquals(1, batchCompletedCount.get());
}
}