--- a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/sync/repositories/uploaders/PayloadUploadDelegateTest.java
+++ b/mobile/android/tests/background/junit4/src/org/mozilla/gecko/sync/repositories/uploaders/PayloadUploadDelegateTest.java
@@ -3,16 +3,17 @@
package org.mozilla.gecko.sync.repositories.uploaders;
import android.net.Uri;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
import org.mozilla.gecko.background.testhelpers.TestRunner;
import org.mozilla.gecko.sync.CollectionConcurrentModificationException;
import org.mozilla.gecko.sync.HTTPFailureException;
import org.mozilla.gecko.sync.InfoConfiguration;
import org.mozilla.gecko.sync.NonObjectJSONException;
import org.mozilla.gecko.sync.net.AuthHeaderProvider;
import org.mozilla.gecko.sync.net.SyncResponse;
import org.mozilla.gecko.sync.net.SyncStorageResponse;
@@ -29,27 +30,31 @@ import java.util.concurrent.ExecutorServ
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.ProtocolVersion;
import ch.boye.httpclientandroidlib.entity.BasicHttpEntity;
import ch.boye.httpclientandroidlib.message.BasicHttpResponse;
import ch.boye.httpclientandroidlib.message.BasicStatusLine;
import static org.junit.Assert.*;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
@RunWith(TestRunner.class)
public class PayloadUploadDelegateTest {
+ private RepositorySession repositorySession;
private PayloadDispatcher payloadDispatcher;
private AuthHeaderProvider authHeaderProvider;
private RepositorySessionStoreDelegate sessionStoreDelegate;
class MockPayloadDispatcher extends PayloadDispatcher {
public final HashMap<String, Exception> failedRecords = new HashMap<>();
- public boolean didLastPayloadFail = false;
+ public boolean didPayloadFail = false;
public ArrayList<SyncStorageResponse> successResponses = new ArrayList<>();
public int commitPayloadsSucceeded = 0;
public int lastPayloadsSucceeded = 0;
public int committedGuids = 0;
public MockPayloadDispatcher(final Executor workQueue, final BatchingUploader uploader) {
@@ -79,18 +84,19 @@ public class PayloadUploadDelegateTest {
@Override
public void recordFailed(final Exception e, final String recordGuid) {
recordUploadFailed = true;
failedRecords.put(recordGuid, e);
}
@Override
- public void lastPayloadFailed(Exception e) {
- didLastPayloadFail = true;
+ public void payloadFailed(Exception e) {
+ didPayloadFail = true;
+ super.payloadFailed(e);
}
}
class MockRepositorySessionStoreDelegate implements RepositorySessionStoreDelegate {
Exception storeFailedException;
ArrayList<String> succeededGuids = new ArrayList<>();
HashMap<String, Exception> failedGuids = new HashMap<>();
@@ -119,38 +125,48 @@ public class PayloadUploadDelegateTest {
@Override
public RepositorySessionStoreDelegate deferredStoreDelegate(ExecutorService executor) {
return this;
}
}
@Before
public void setUp() throws Exception {
- sessionStoreDelegate = new MockRepositorySessionStoreDelegate();
+ sessionStoreDelegate = spy(new MockRepositorySessionStoreDelegate());
+
+ repositorySession = mock(RepositorySession.class);
payloadDispatcher = new MockPayloadDispatcher(
null,
- new BatchingUploader(mock(RepositorySession.class), null, sessionStoreDelegate, Uri.parse("https://example.com"), 0L, mock(InfoConfiguration.class), mock(AuthHeaderProvider.class))
+ new BatchingUploader(
+ repositorySession,
+ null,
+ sessionStoreDelegate,
+ Uri.parse("https://example.com"),
+ 0L,
+ mock(InfoConfiguration.class),
+ mock(AuthHeaderProvider.class)
+ )
);
authHeaderProvider = mock(AuthHeaderProvider.class);
}
@Test
public void testHandleRequestSuccessNonSuccess() {
ArrayList<String> postedGuids = new ArrayList<>(2);
postedGuids.add("testGuid1");
postedGuids.add("testGuid2");
PayloadUploadDelegate payloadUploadDelegate = new PayloadUploadDelegate(
authHeaderProvider, payloadDispatcher, postedGuids, false, false);
// Test that non-2* responses aren't processed
payloadUploadDelegate.handleRequestSuccess(makeSyncStorageResponse(404, null, null));
assertEquals(2, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.size());
- assertFalse(((MockPayloadDispatcher) payloadDispatcher).didLastPayloadFail);
+ assertTrue(((MockPayloadDispatcher) payloadDispatcher).didPayloadFail);
assertEquals(IllegalStateException.class,
((MockPayloadDispatcher) payloadDispatcher).failedRecords.get("testGuid1").getClass());
assertEquals(IllegalStateException.class,
((MockPayloadDispatcher) payloadDispatcher).failedRecords.get("testGuid2").getClass());
}
@Test
public void testHandleRequestSuccessNoHeaders() {
@@ -158,17 +174,17 @@ public class PayloadUploadDelegateTest {
postedGuids.add("testGuid1");
postedGuids.add("testGuid2");
PayloadUploadDelegate payloadUploadDelegate = new PayloadUploadDelegate(
authHeaderProvider, payloadDispatcher, postedGuids, false, false);
// Test that responses without X-Last-Modified header aren't processed
payloadUploadDelegate.handleRequestSuccess(makeSyncStorageResponse(200, null, null));
assertEquals(2, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.size());
- assertFalse(((MockPayloadDispatcher) payloadDispatcher).didLastPayloadFail);
+ assertTrue(((MockPayloadDispatcher) payloadDispatcher).didPayloadFail);
assertEquals(IllegalStateException.class,
((MockPayloadDispatcher) payloadDispatcher).failedRecords.get("testGuid1").getClass());
assertEquals(IllegalStateException.class,
((MockPayloadDispatcher) payloadDispatcher).failedRecords.get("testGuid2").getClass());
}
@Test
public void testHandleRequestSuccessBadBody() {
@@ -176,17 +192,17 @@ public class PayloadUploadDelegateTest {
postedGuids.add("testGuid1");
postedGuids.add("testGuid2");
PayloadUploadDelegate payloadUploadDelegate = new PayloadUploadDelegate(
authHeaderProvider, payloadDispatcher, postedGuids, false, true);
// Test that we catch json processing errors
payloadUploadDelegate.handleRequestSuccess(makeSyncStorageResponse(200, "non json body", "123"));
assertEquals(2, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.size());
- assertTrue(((MockPayloadDispatcher) payloadDispatcher).didLastPayloadFail);
+ assertTrue(((MockPayloadDispatcher) payloadDispatcher).didPayloadFail);
assertEquals(NonObjectJSONException.class,
((MockPayloadDispatcher) payloadDispatcher).failedRecords.get("testGuid1").getClass());
assertEquals(NonObjectJSONException.class,
((MockPayloadDispatcher) payloadDispatcher).failedRecords.get("testGuid2").getClass());
}
@Test
public void testHandleRequestSuccess202NoToken() {
@@ -230,30 +246,30 @@ public class PayloadUploadDelegateTest {
postedGuids.add("guid2");
postedGuids.add("guid3");
PayloadUploadDelegate payloadUploadDelegate = new PayloadUploadDelegate(
authHeaderProvider, payloadDispatcher, postedGuids, false, false);
payloadUploadDelegate.handleRequestSuccess(
makeSyncStorageResponse(200, "{\"success\": [\"guid1\", \"guid2\", \"guid3\"]}", "123"));
assertEquals(0, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.size());
- assertFalse(((MockPayloadDispatcher) payloadDispatcher).didLastPayloadFail);
+ assertFalse(((MockPayloadDispatcher) payloadDispatcher).didPayloadFail);
assertEquals(1, ((MockPayloadDispatcher) payloadDispatcher).successResponses.size());
assertEquals(0, ((MockPayloadDispatcher) payloadDispatcher).commitPayloadsSucceeded);
assertEquals(0, ((MockPayloadDispatcher) payloadDispatcher).lastPayloadsSucceeded);
// These should fail, because we're returning a non-changed L-M in a non-batching mode
postedGuids.add("guid4");
postedGuids.add("guid6");
payloadUploadDelegate = new PayloadUploadDelegate(
authHeaderProvider, payloadDispatcher, postedGuids, false, false);
payloadUploadDelegate.handleRequestSuccess(
makeSyncStorageResponse(200, "{\"success\": [\"guid4\", 5, \"guid6\"]}", "123"));
assertEquals(5, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.size());
- assertFalse(((MockPayloadDispatcher) payloadDispatcher).didLastPayloadFail);
+ assertTrue(((MockPayloadDispatcher) payloadDispatcher).didPayloadFail);
assertEquals(1, ((MockPayloadDispatcher) payloadDispatcher).successResponses.size());
assertEquals(0, ((MockPayloadDispatcher) payloadDispatcher).commitPayloadsSucceeded);
assertEquals(0, ((MockPayloadDispatcher) payloadDispatcher).lastPayloadsSucceeded);
assertEquals(BatchingUploader.LastModifiedDidNotChange.class,
((MockPayloadDispatcher) payloadDispatcher).failedRecords.get("guid4").getClass());
}
@Test
@@ -283,33 +299,33 @@ public class PayloadUploadDelegateTest {
postedGuids.add("guid6");
payloadUploadDelegate = new PayloadUploadDelegate(
authHeaderProvider, payloadDispatcher, postedGuids, false, true);
payloadUploadDelegate.handleRequestSuccess(
makeSyncStorageResponse(200, "{\"success\": [\"guid6\"], \"failed\": {}}", "444"));
assertEquals(0, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.size());
assertEquals(6, ((MockPayloadDispatcher) payloadDispatcher).committedGuids);
- assertFalse(((MockPayloadDispatcher) payloadDispatcher).didLastPayloadFail);
+ assertFalse(((MockPayloadDispatcher) payloadDispatcher).didPayloadFail);
assertEquals(3, ((MockPayloadDispatcher) payloadDispatcher).successResponses.size());
assertEquals(0, ((MockPayloadDispatcher) payloadDispatcher).commitPayloadsSucceeded);
assertEquals(1, ((MockPayloadDispatcher) payloadDispatcher).lastPayloadsSucceeded);
assertFalse(payloadDispatcher.batchWhiteboard.getInBatchingMode());
postedGuids = new ArrayList<>();
postedGuids.add("guid7");
postedGuids.add("guid8");
payloadUploadDelegate = new PayloadUploadDelegate(
authHeaderProvider, payloadDispatcher, postedGuids, false, true);
payloadUploadDelegate.handleRequestSuccess(
makeSyncStorageResponse(200, "{\"success\": [\"guid8\"], \"failed\": {\"guid7\": \"reason\"}}", "555"));
assertEquals(7, ((MockPayloadDispatcher) payloadDispatcher).committedGuids);
assertEquals(1, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.size());
assertTrue(((MockPayloadDispatcher) payloadDispatcher).failedRecords.containsKey("guid7"));
- assertFalse(((MockPayloadDispatcher) payloadDispatcher).didLastPayloadFail);
+ assertFalse(((MockPayloadDispatcher) payloadDispatcher).didPayloadFail);
assertEquals(4, ((MockPayloadDispatcher) payloadDispatcher).successResponses.size());
assertEquals(0, ((MockPayloadDispatcher) payloadDispatcher).commitPayloadsSucceeded);
assertEquals(2, ((MockPayloadDispatcher) payloadDispatcher).lastPayloadsSucceeded);
assertFalse(payloadDispatcher.batchWhiteboard.getInBatchingMode());
}
@Test
public void testHandleRequestSuccessBatching() {
@@ -357,17 +373,17 @@ public class PayloadUploadDelegateTest {
postedGuids.add("guid8");
payloadUploadDelegate = new PayloadUploadDelegate(
authHeaderProvider, payloadDispatcher, postedGuids, true, true);
payloadUploadDelegate.handleRequestSuccess(
makeSyncStorageResponse(200, "{\"success\": [\"guid7\"], \"failed\": {}}", "333"));
assertEquals(0, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.size());
assertEquals(8, ((MockPayloadDispatcher) payloadDispatcher).committedGuids);
- assertFalse(((MockPayloadDispatcher) payloadDispatcher).didLastPayloadFail);
+ assertFalse(((MockPayloadDispatcher) payloadDispatcher).didPayloadFail);
assertEquals(4, ((MockPayloadDispatcher) payloadDispatcher).successResponses.size());
assertEquals(2, ((MockPayloadDispatcher) payloadDispatcher).commitPayloadsSucceeded);
assertEquals(1, ((MockPayloadDispatcher) payloadDispatcher).lastPayloadsSucceeded);
assertTrue(payloadDispatcher.batchWhiteboard.getInBatchingMode());
}
@Test
public void testHandleRequestError() {
@@ -380,23 +396,23 @@ public class PayloadUploadDelegateTest {
IllegalStateException e = new IllegalStateException();
payloadUploadDelegate.handleRequestError(e);
assertEquals(3, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.size());
assertEquals(e, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.get("testGuid1"));
assertEquals(e, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.get("testGuid2"));
assertEquals(e, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.get("testGuid3"));
- assertFalse(((MockPayloadDispatcher) payloadDispatcher).didLastPayloadFail);
+ assertTrue(((MockPayloadDispatcher) payloadDispatcher).didPayloadFail);
payloadUploadDelegate = new PayloadUploadDelegate(
authHeaderProvider, payloadDispatcher, postedGuids, false, true);
payloadUploadDelegate.handleRequestError(e);
assertEquals(3, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.size());
- assertTrue(((MockPayloadDispatcher) payloadDispatcher).didLastPayloadFail);
+ assertTrue(((MockPayloadDispatcher) payloadDispatcher).didPayloadFail);
}
@Test
public void testHandleRequestFailure() {
ArrayList<String> postedGuids = new ArrayList<>(3);
postedGuids.add("testGuid1");
postedGuids.add("testGuid2");
postedGuids.add("testGuid3");
@@ -408,42 +424,50 @@ public class PayloadUploadDelegateTest {
payloadUploadDelegate.handleRequestFailure(new SyncStorageResponse(response));
assertEquals(3, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.size());
assertEquals(HTTPFailureException.class,
((MockPayloadDispatcher) payloadDispatcher).failedRecords.get("testGuid1").getClass());
assertEquals(HTTPFailureException.class,
((MockPayloadDispatcher) payloadDispatcher).failedRecords.get("testGuid2").getClass());
assertEquals(HTTPFailureException.class,
((MockPayloadDispatcher) payloadDispatcher).failedRecords.get("testGuid3").getClass());
+ verify(repositorySession, times(1)).abort();
+ verify(sessionStoreDelegate, times(1)).onStoreFailed((Exception) Mockito.any());
payloadUploadDelegate = new PayloadUploadDelegate(
authHeaderProvider, payloadDispatcher, postedGuids, false, true);
payloadUploadDelegate.handleRequestFailure(new SyncStorageResponse(response));
assertEquals(3, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.size());
- assertTrue(((MockPayloadDispatcher) payloadDispatcher).didLastPayloadFail);
+ assertTrue(((MockPayloadDispatcher) payloadDispatcher).didPayloadFail);
assertTrue(payloadDispatcher.recordUploadFailed);
+
+ // Ensure we'd only ever call .abort and .onStoreFailed once.
+ verify(repositorySession, times(1)).abort();
+ verify(sessionStoreDelegate, times(1)).onStoreFailed((Exception) Mockito.any());
}
@Test
public void testHandleRequestFailure412() {
ArrayList<String> postedGuids = new ArrayList<>(3);
postedGuids.add("testGuid1");
postedGuids.add("testGuid2");
postedGuids.add("testGuid3");
PayloadUploadDelegate payloadUploadDelegate = new PayloadUploadDelegate(authHeaderProvider, payloadDispatcher, postedGuids, false, false);
final HttpResponse response = new BasicHttpResponse(
new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 412, "Precondition failed"));
payloadUploadDelegate.handleRequestFailure(new SyncStorageResponse(response));
assertEquals(0, ((MockPayloadDispatcher) payloadDispatcher).failedRecords.size());
assertTrue(payloadDispatcher.recordUploadFailed);
- assertTrue(payloadDispatcher.storeFailed);
+ assertTrue(payloadDispatcher.storeFailed.get());
assertTrue(((MockRepositorySessionStoreDelegate) sessionStoreDelegate).storeFailedException instanceof CollectionConcurrentModificationException);
+ verify(repositorySession, times(1)).abort();
+ verify(sessionStoreDelegate, times(1)).onStoreFailed((Exception) Mockito.any());
}
@Test
public void testIfUnmodifiedSinceNoLM() {
PayloadUploadDelegate payloadUploadDelegate = new PayloadUploadDelegate(
authHeaderProvider, payloadDispatcher, new ArrayList<String>(), false, false);
assertNull(payloadUploadDelegate.ifUnmodifiedSince());