/**
* Copyright 2012 Facebook
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.facebook;
import android.graphics.Bitmap;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import com.facebook.model.GraphObject;
import com.facebook.model.GraphPlace;
import com.facebook.model.GraphUser;
import com.facebook.internal.CacheableRequestBatch;
import java.io.IOException;
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.
Request.setDefaultBatchApplicationId(null);
}
@SmallTest
@MediumTest
@LargeTest
public void testCreateEmptyRequestBatch() {
CacheableRequestBatch batch = new CacheableRequestBatch();
Request meRequest = Request.newMeRequest(null, null);
assertEquals(0, batch.size());
batch.add(meRequest);
assertEquals(1, batch.size());
assertEquals(meRequest, batch.get(0));
String key = "The Key";
assertNull(batch.getCacheKeyOverride());
batch.setCacheKeyOverride(key);
assertEquals(key, batch.getCacheKeyOverride());
assertTrue(!batch.getForceRoundTrip());
batch.setForceRoundTrip(true);
assertTrue(batch.getForceRoundTrip());
}
@SmallTest
@MediumTest
@LargeTest
public void testCreateNonemptyRequestBatch() {
Request meRequest = Request.newMeRequest(null, null);
RequestBatch batch = new RequestBatch(new Request[] { meRequest, meRequest });
assertEquals(2, batch.size());
assertEquals(meRequest, batch.get(0));
assertEquals(meRequest, batch.get(1));
}
@SmallTest
@MediumTest
@LargeTest
public void testBatchWithoutAppIDIsError() {
Request request1 = new Request(null, "TourEiffel", null, null, new ExpectFailureCallback());
Request request2 = new Request(null, "SpaceNeedle", null, null, new ExpectFailureCallback());
Request.executeBatchAndWait(request1, request2);
}
@MediumTest
@LargeTest
public void testExecuteBatchedGets() throws IOException {
setBatchApplicationIdForTestApp();
Request request1 = new Request(null, "TourEiffel");
Request request2 = new Request(null, "SpaceNeedle");
List<Response> responses = Request.executeBatchAndWait(request1, request2);
assertEquals(2, responses.size());
assertTrue(responses.get(0).getError() == null);
assertTrue(responses.get(1).getError() == null);
GraphPlace eiffelTower = responses.get(0).getGraphObjectAs(GraphPlace.class);
GraphPlace spaceNeedle = responses.get(1).getGraphObjectAs(GraphPlace.class);
assertTrue(eiffelTower != null);
assertTrue(spaceNeedle != null);
assertEquals("Paris", eiffelTower.getLocation().getCity());
assertEquals("Seattle", spaceNeedle.getLocation().getCity());
}
@MediumTest
@LargeTest
public void testFacebookErrorResponsesCreateErrors() {
setBatchApplicationIdForTestApp();
Request request1 = new Request(null, "somestringthatshouldneverbeavalidfobjectid");
Request request2 = new Request(null, "someotherstringthatshouldneverbeavalidfobjectid");
List<Response> responses = Request.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() {
TestSession session = openTestSessionWithSharedUser();
GraphObject statusUpdate1 = createStatusUpdate();
GraphObject statusUpdate2 = createStatusUpdate();
Request postRequest1 = Request.newPostRequest(session, "me/feed", statusUpdate1, null);
postRequest1.setBatchEntryName("postRequest1");
Request postRequest2 = Request.newPostRequest(session, "me/feed", statusUpdate2, null);
postRequest2.setBatchEntryName("postRequest2");
Request getRequest1 = new Request(session, "{result=postRequest1:$.id}");
Request getRequest2 = new Request(session, "{result=postRequest2:$.id}");
List<Response> responses = Request.executeBatchAndWait(postRequest1, postRequest2, getRequest1, getRequest2);
assertNotNull(responses);
assertEquals(4, responses.size());
assertNoErrors(responses);
GraphObject retrievedStatusUpdate1 = responses.get(2).getGraphObject();
GraphObject retrievedStatusUpdate2 = responses.get(3).getGraphObject();
assertNotNull(retrievedStatusUpdate1);
assertNotNull(retrievedStatusUpdate2);
assertEquals(statusUpdate1.getProperty("message"), retrievedStatusUpdate1.getProperty("message"));
assertEquals(statusUpdate2.getProperty("message"), retrievedStatusUpdate2.getProperty("message"));
}
@LargeTest
public void testTwoDifferentAccessTokens() {
TestSession session1 = openTestSessionWithSharedUser();
TestSession session2 = openTestSessionWithSharedUser(SECOND_TEST_USER_TAG);
Request request1 = Request.newMeRequest(session1, null);
Request request2 = Request.newMeRequest(session2, null);
List<Response> responses = Request.executeBatchAndWait(request1, request2);
assertNotNull(responses);
assertEquals(2, responses.size());
GraphUser user1 = responses.get(0).getGraphObjectAs(GraphUser.class);
GraphUser user2 = responses.get(1).getGraphObjectAs(GraphUser.class);
assertNotNull(user1);
assertNotNull(user2);
assertFalse(user1.getId().equals(user2.getId()));
assertEquals(session1.getTestUserId(), user1.getId());
assertEquals(session2.getTestUserId(), user2.getId());
}
@LargeTest
public void testBatchWithValidSessionAndNoSession() {
TestSession session = openTestSessionWithSharedUser();
Request request1 = new Request(session, "me");
Request request2 = new Request(null, "zuck");
List<Response> responses = Request.executeBatchAndWait(request1, request2);
assertNotNull(responses);
assertEquals(2, responses.size());
GraphUser user1 = responses.get(0).getGraphObjectAs(GraphUser.class);
GraphUser user2 = responses.get(1).getGraphObjectAs(GraphUser.class);
assertNotNull(user1);
assertNotNull(user2);
assertFalse(user1.getId().equals(user2.getId()));
assertEquals(session.getTestUserId(), user1.getId());
assertEquals("4", user2.getId());
}
@LargeTest
public void testBatchWithNoSessionAndValidSession() {
TestSession session = openTestSessionWithSharedUser();
Request request1 = new Request(null, "zuck");
Request request2 = new Request(session, "me");
List<Response> responses = Request.executeBatchAndWait(request1, request2);
assertNotNull(responses);
assertEquals(2, responses.size());
GraphUser user1 = responses.get(0).getGraphObjectAs(GraphUser.class);
GraphUser user2 = responses.get(1).getGraphObjectAs(GraphUser.class);
assertNotNull(user1);
assertNotNull(user2);
assertFalse(user1.getId().equals(user2.getId()));
assertEquals("4", user1.getId());
assertEquals(session.getTestUserId(), user2.getId());
}
@LargeTest
public void testBatchWithTwoSessionlessRequestsAndDefaultAppID() {
TestSession session = getTestSessionWithSharedUser(null);
String appId = session.getApplicationId();
Request.setDefaultBatchApplicationId(appId);
Request request1 = new Request(null, "zuck");
Request request2 = new Request(null, "zuck");
List<Response> responses = Request.executeBatchAndWait(request1, request2);
assertNotNull(responses);
assertEquals(2, responses.size());
GraphUser user1 = responses.get(0).getGraphObjectAs(GraphUser.class);
GraphUser user2 = responses.get(1).getGraphObjectAs(GraphUser.class);
assertNotNull(user1);
assertNotNull(user2);
assertEquals("4", user1.getId());
assertEquals("4", user2.getId());
}
@LargeTest
public void testMixedSuccessAndFailure() {
TestSession session = openTestSessionWithSharedUser();
final int NUM_REQUESTS = 8;
Request[] requests = new Request[NUM_REQUESTS];
for (int i = 0; i < NUM_REQUESTS; ++i) {
boolean shouldSucceed = (i % 2) == 1;
requests[i] = new Request(session, shouldSucceed ? "me" : "-1");
}
List<Response> responses = Request.executeBatchAndWait(requests);
assertNotNull(responses);
assertEquals(NUM_REQUESTS, responses.size());
for (int i = 0; i < NUM_REQUESTS; ++i) {
boolean shouldSucceed = (i % 2) == 1;
Response response = responses.get(i);
assertNotNull(response);
if (shouldSucceed) {
assertNull(response.getError());
assertNotNull(response.getGraphObject());
} else {
assertNotNull(response.getError());
assertNull(response.getGraphObject());
}
}
}
@MediumTest
@LargeTest
public void testClosedSessionDoesntAppendAccessToken() {
TestSession session = openTestSessionWithSharedUser();
session.close();
Request request1 = new Request(session, "me", null, null, new ExpectFailureCallback());
Request request2 = new Request(session, "me", null, null, new ExpectFailureCallback());
TestRequestAsyncTask task = new TestRequestAsyncTask(request1, request2);
task.executeOnBlockerThread();
waitAndAssertSuccess(2);
}
@LargeTest
public void testBatchUploadPhoto() {
TestSession session = openTestSessionWithSharedUserAndPermissions(null, "user_photos");
final int image1Size = 120;
final int image2Size = 150;
Bitmap bitmap1 = createTestBitmap(image1Size);
Bitmap bitmap2 = createTestBitmap(image2Size);
Request uploadRequest1 = Request.newUploadPhotoRequest(session, bitmap1, null);
uploadRequest1.setBatchEntryName("uploadRequest1");
Request uploadRequest2 = Request.newUploadPhotoRequest(session, bitmap2, null);
uploadRequest2.setBatchEntryName("uploadRequest2");
Request getRequest1 = new Request(session, "{result=uploadRequest1:$.id}");
Request getRequest2 = new Request(session, "{result=uploadRequest2:$.id}");
List<Response> responses = Request.executeBatchAndWait(uploadRequest1, uploadRequest2, getRequest1, getRequest2);
assertNotNull(responses);
assertEquals(4, responses.size());
assertNoErrors(responses);
GraphObject retrievedPhoto1 = responses.get(2).getGraphObject();
GraphObject retrievedPhoto2 = responses.get(3).getGraphObject();
assertNotNull(retrievedPhoto1);
assertNotNull(retrievedPhoto2);
assertEquals(image1Size, retrievedPhoto1.getProperty("width"));
assertEquals(image2Size, retrievedPhoto2.getProperty("width"));
}
@MediumTest
@LargeTest
public void testCallbacksAreCalled() {
setBatchApplicationIdForTestApp();
ArrayList<Request> requests = new ArrayList<Request>();
final ArrayList<Boolean> calledBack = new ArrayList<Boolean>();
final int NUM_REQUESTS = 4;
for (int i = 0; i < NUM_REQUESTS; ++i) {
Request request = new Request(null, "4");
request.setCallback(new Request.Callback() {
@Override
public void onCompleted(Response response) {
calledBack.add(true);
}
});
requests.add(request);
}
List<Response> responses = Request.executeBatchAndWait(requests);
assertNotNull(responses);
assertTrue(calledBack.size() == NUM_REQUESTS);
}
@MediumTest
@LargeTest
public void testCacheMyFriendsRequest() throws IOException {
Response.getResponseCache().clearForTest();
TestSession session = openTestSessionWithSharedUser();
Request request = Request.newMyFriendsRequest(session, null);
CacheableRequestBatch batch = new CacheableRequestBatch(request);
batch.setCacheKeyOverride("MyFriends");
// Running the request with empty cache should hit the server.
List<Response> responses = Request.executeBatchAndWait(batch);
assertNotNull(responses);
assertEquals(1, responses.size());
Response response = responses.get(0);
assertNotNull(response);
assertNull(response.getError());
assertTrue(!response.getIsFromCache());
// Running again should hit the cache.
responses = Request.executeBatchAndWait(batch);
assertNotNull(responses);
assertEquals(1, responses.size());
response = responses.get(0);
assertNotNull(response);
assertNull(response.getError());
assertTrue(response.getIsFromCache());
// Forcing roundtrip should hit the server again.
batch.setForceRoundTrip(true);
responses = Request.executeBatchAndWait(batch);
assertNotNull(responses);
assertEquals(1, responses.size());
response = responses.get(0);
assertNotNull(response);
assertNull(response.getError());
assertTrue(!response.getIsFromCache());
Response.getResponseCache().clearForTest();
}
@MediumTest
@LargeTest
public void testCacheMeAndMyFriendsRequest() throws IOException {
Response.getResponseCache().clearForTest();
TestSession session = openTestSessionWithSharedUser();
Request requestMe = Request.newMeRequest(session, null);
Request requestMyFriends = Request.newMyFriendsRequest(session, null);
CacheableRequestBatch batch = new CacheableRequestBatch(new Request[] { requestMyFriends, requestMe });
batch.setCacheKeyOverride("MyFriends");
// Running the request with empty cache should hit the server.
List<Response> responses = Request.executeBatchAndWait(batch);
assertNotNull(responses);
assertEquals(2, responses.size());
for (Response response : responses) {
assertNotNull(response);
assertNull(response.getError());
assertTrue(!response.getIsFromCache());
}
// Running again should hit the cache.
responses = Request.executeBatchAndWait(batch);
assertNotNull(responses);
assertEquals(2, responses.size());
for (Response response : responses) {
assertNotNull(response);
assertNull(response.getError());
assertTrue(response.getIsFromCache());
}
// Forcing roundtrip should hit the server again.
batch.setForceRoundTrip(true);
responses = Request.executeBatchAndWait(batch);
assertNotNull(responses);
assertEquals(2, responses.size());
for (Response response : responses) {
assertNotNull(response);
assertNull(response.getError());
assertTrue(!response.getIsFromCache());
}
Response.getResponseCache().clearForTest();
}
@MediumTest
@LargeTest
public void testExplicitDependencyDefaultsToOmitFirstResponse() {
TestSession session = openTestSessionWithSharedUser();
Request requestMe = Request.newMeRequest(session, null);
requestMe.setBatchEntryName("me_request");
Request requestMyFriends = Request.newMyFriendsRequest(session, null);
requestMyFriends.setBatchEntryDependsOn("me_request");
List<Response> responses = Request.executeBatchAndWait(requestMe, requestMyFriends);
Response meResponse = responses.get(0);
Response myFriendsResponse = responses.get(1);
assertNull(meResponse.getGraphObject());
assertNotNull(myFriendsResponse.getGraphObject());
}
@MediumTest
@LargeTest
public void testExplicitDependencyCanIncludeFirstResponse() {
TestSession session = openTestSessionWithSharedUser();
Request requestMe = Request.newMeRequest(session, null);
requestMe.setBatchEntryName("me_request");
requestMe.setBatchEntryOmitResultOnSuccess(false);
Request requestMyFriends = Request.newMyFriendsRequest(session, null);
requestMyFriends.setBatchEntryDependsOn("me_request");
List<Response> responses = Request.executeBatchAndWait(requestMe, requestMyFriends);
Response meResponse = responses.get(0);
Response myFriendsResponse = responses.get(1);
assertNotNull(meResponse.getGraphObject());
assertNotNull(myFriendsResponse.getGraphObject());
}
@SmallTest
@MediumTest
@LargeTest
public void testAddAndRemoveBatchCallbacks() {
RequestBatch batch = new RequestBatch();
RequestBatch.Callback callback1 = new RequestBatch.Callback() {
@Override
public void onBatchCompleted(RequestBatch batch) {
}
};
RequestBatch.Callback callback2 = new RequestBatch.Callback() {
@Override
public void onBatchCompleted(RequestBatch batch) {
}
};
batch.addCallback(callback1);
batch.addCallback(callback2);
assertEquals(2, batch.getCallbacks().size());
batch.removeCallback(callback1);
batch.removeCallback(callback2);
assertEquals(0, batch.getCallbacks().size());
}
@MediumTest
@LargeTest
public void testBatchCallbackIsCalled() {
final AtomicInteger count = new AtomicInteger();
Request request1 = Request.newGraphPathRequest(null, "4", new Request.Callback() {
@Override
public void onCompleted(Response response) {
count.incrementAndGet();
}
});
Request request2 = Request.newGraphPathRequest(null, "4", new Request.Callback() {
@Override
public void onCompleted(Response response) {
count.incrementAndGet();
}
});
RequestBatch batch = new RequestBatch(request1, request2);
batch.addCallback(new RequestBatch.Callback() {
@Override
public void onBatchCompleted(RequestBatch batch) {
count.incrementAndGet();
}
});
batch.executeAndWait();
assertEquals(3, count.get());
}
}