/** * Copyright (c) 2016 Couchbase, Inc. All rights reserved. * <p/> * 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 * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * 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.couchbase.lite.replicator; import com.couchbase.lite.Document; import com.couchbase.lite.LiteTestCaseWithDB; import com.couchbase.lite.mockserver.MockChangesFeed; import com.couchbase.lite.mockserver.MockChangesFeedNoResponse; import com.couchbase.lite.mockserver.MockCheckpointPut; import com.couchbase.lite.mockserver.MockDispatcher; import com.couchbase.lite.mockserver.MockDocumentBulkGet; import com.couchbase.lite.mockserver.MockDocumentGet; import com.couchbase.lite.mockserver.MockHelper; import com.couchbase.lite.util.Log; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; /** * Created by hideki on 12/15/15. */ public class ReplicationInternalTest extends LiteTestCaseWithDB { // one shot pull replication with _bulk_get - successful scenario public void testOneShotPullReplBulkGet() throws Exception { String doc1Id = "doc1"; String doc2Id = "doc2"; String doc3Id = "doc3"; final MockDocumentGet.MockDocument mockDocument1 = new MockDocumentGet.MockDocument(doc1Id, "1-0001", 1); mockDocument1.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument2 = new MockDocumentGet.MockDocument(doc2Id, "1-0002", 2); mockDocument2.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument3 = new MockDocumentGet.MockDocument(doc3Id, "1-0003", 3); mockDocument3.setJsonMap(MockHelper.generateRandomJsonMap()); // create mockwebserver and custom dispatcher MockDispatcher dispatcher = new MockDispatcher(); MockWebServer server = MockHelper.getMockWebServer(dispatcher); dispatcher.setServerType(MockDispatcher.ServerType.SYNC_GW); try { //add response to _local request // checkpoint GET response w/ 404 MockResponse fakeCheckpointResponse = new MockResponse(); MockHelper.set404NotFoundJson(fakeCheckpointResponse); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, fakeCheckpointResponse); //add response to _changes request // _changes response MockChangesFeed mockChangesFeed = new MockChangesFeed(); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument1)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument2)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument3)); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHANGES, mockChangesFeed.generateMockResponse()); // _bulk_get response for odd indexed documents MockDocumentBulkGet mockBulkGet = new MockDocumentBulkGet(); mockBulkGet.addDocument(mockDocument1); mockBulkGet.addDocument(mockDocument2); mockBulkGet.addDocument(mockDocument3); mockBulkGet.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_BULK_GET, mockBulkGet); // checkpoint PUT response MockCheckpointPut mockCheckpointPut = new MockCheckpointPut(); mockCheckpointPut.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, mockCheckpointPut); // start mock server server.start(); //create replication Replication pull = database.createPullReplication(server.url("/db").url()); pull.setContinuous(false); //add change listener to notify when the replication is finished CountDownLatch replicationIdleSignal = new CountDownLatch(1); pull.addChangeListener(new ReplicationFinishedObserver(replicationIdleSignal)); //start replication pull.start(); boolean success = replicationIdleSignal.await(30, TimeUnit.SECONDS); assertTrue(success); if (pull.getLastError() != null) Log.d(TAG, "Replication had error: ", pull.getLastError()); assertNull(pull.getLastError()); //assert document 1 was correctly pulled Document doc1 = database.getDocument(doc1Id); assertNotNull(doc1); assertNotNull(doc1.getCurrentRevision()); assertEquals("1-0001", doc1.getCurrentRevision().getId()); //assert it was impossible to pull doc2 Document doc2 = database.getDocument(doc2Id); assertNotNull(doc2); assertEquals("1-0002", doc2.getCurrentRevision().getId()); //assert it was possible to pull doc3 Document doc3 = database.getDocument(doc3Id); assertNotNull(doc3); assertEquals("1-0003", doc3.getCurrentRevision().getId()); // wait until the replicator PUT's checkpoint with mockDocument3's sequence waitForPutCheckpointRequestWithSeq(dispatcher, mockDocument3.getDocSeq()); //last saved seq must be equal to last pulled document seq String doc3Seq = Integer.toString(mockDocument3.getDocSeq()); String lastSequence = database.lastSequenceWithCheckpointId( pull.remoteCheckpointDocID()); assertEquals(doc3Seq, lastSequence); } finally { assertTrue(MockHelper.shutdown(server, dispatcher)); } } // continuous pull replication with _bulk_get - successful scenario public void testContPullReplBulkGet() throws Exception { String doc1Id = "doc1"; String doc2Id = "doc2"; String doc3Id = "doc3"; final MockDocumentGet.MockDocument mockDocument1 = new MockDocumentGet.MockDocument(doc1Id, "1-0001", 1); mockDocument1.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument2 = new MockDocumentGet.MockDocument(doc2Id, "1-0002", 2); mockDocument2.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument3 = new MockDocumentGet.MockDocument(doc3Id, "1-0003", 3); mockDocument3.setJsonMap(MockHelper.generateRandomJsonMap()); // create mockwebserver and custom dispatcher MockDispatcher dispatcher = new MockDispatcher(); MockWebServer server = MockHelper.getMockWebServer(dispatcher); dispatcher.setServerType(MockDispatcher.ServerType.SYNC_GW); try { //add response to _local request // checkpoint GET response w/ 404 MockResponse fakeCheckpointResponse = new MockResponse(); MockHelper.set404NotFoundJson(fakeCheckpointResponse); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, fakeCheckpointResponse); //add response to _changes request // _changes response MockChangesFeed mockChangesFeed = new MockChangesFeed(); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument1)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument2)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument3)); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHANGES, mockChangesFeed.generateMockResponse()); // add sticky _changes response to feed=longpoll that just blocks for 60 seconds // to emulate server that doesn't have any new changes MockChangesFeedNoResponse mockChangesFeedNoResponse = new MockChangesFeedNoResponse(); mockChangesFeedNoResponse.setDelayMs(60 * 1000); mockChangesFeedNoResponse.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHANGES, mockChangesFeedNoResponse); // _bulk_get response for odd indexed documents MockDocumentBulkGet mockBulkGet = new MockDocumentBulkGet(); mockBulkGet.addDocument(mockDocument1); mockBulkGet.addDocument(mockDocument2); mockBulkGet.addDocument(mockDocument3); mockBulkGet.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_BULK_GET, mockBulkGet); // checkpoint PUT response MockCheckpointPut mockCheckpointPut = new MockCheckpointPut(); mockCheckpointPut.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, mockCheckpointPut); // start mock server server.start(); //create replication Replication pull = database.createPullReplication(server.url("/db").url()); pull.setContinuous(true); CountDownLatch replicationIdleSignal = new CountDownLatch(1); pull.addChangeListener(new ReplicationIdleObserver(replicationIdleSignal)); CountDownLatch replicationDoneSignal = new CountDownLatch(1); pull.addChangeListener(new ReplicationFinishedObserver(replicationDoneSignal)); pull.start(); assertTrue(replicationIdleSignal.await(30, TimeUnit.SECONDS)); pull.stop(); assertTrue(replicationDoneSignal.await(30, TimeUnit.SECONDS)); if (pull.getLastError() != null) Log.d(TAG, "Replication had error: ", pull.getLastError()); assertNull(pull.getLastError()); Document doc1 = database.getDocument(doc1Id); assertNotNull(doc1); assertNotNull(doc1.getCurrentRevision()); assertEquals("1-0001", doc1.getCurrentRevision().getId()); Document doc2 = database.getDocument(doc2Id); assertNotNull(doc2); assertNotNull(doc2.getCurrentRevision()); assertEquals("1-0002", doc2.getCurrentRevision().getId()); Document doc3 = database.getDocument(doc3Id); assertNotNull(doc3); assertNotNull(doc3.getCurrentRevision()); assertEquals("1-0003", doc3.getCurrentRevision().getId()); waitForPutCheckpointRequestWithSeq(dispatcher, mockDocument3.getDocSeq()); String doc3Seq = Integer.toString(mockDocument3.getDocSeq()); String lastSequence = database.lastSequenceWithCheckpointId( pull.remoteCheckpointDocID()); assertEquals(doc3Seq, lastSequence); } finally { assertTrue(MockHelper.shutdown(server, dispatcher)); } } // continuous pull replication with _bulk_get with missing revision - erro scenario public void testOneShotPullReplBulkGetWithMissingRev() throws Exception { String doc1Id = "doc1"; String doc2Id = "doc2"; String doc3Id = "doc3"; final MockDocumentGet.MockDocument mockDocument1 = new MockDocumentGet.MockDocument(doc1Id, "1-0001", 1); mockDocument1.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument2 = new MockDocumentGet.MockDocument(doc2Id, "1-0002", 2); mockDocument2.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument3 = new MockDocumentGet.MockDocument(doc3Id, "1-0003", 3); mockDocument3.setJsonMap(MockHelper.generateRandomJsonMap()); // create mockwebserver and custom dispatcher MockDispatcher dispatcher = new MockDispatcher(); MockWebServer server = MockHelper.getMockWebServer(dispatcher); dispatcher.setServerType(MockDispatcher.ServerType.SYNC_GW); try { //add response to _local request // checkpoint GET response w/ 404 MockResponse fakeCheckpointResponse = new MockResponse(); MockHelper.set404NotFoundJson(fakeCheckpointResponse); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, fakeCheckpointResponse); //add response to _changes request // _changes response MockChangesFeed mockChangesFeed = new MockChangesFeed(); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument1)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument2)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument3)); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHANGES, mockChangesFeed.generateMockResponse()); // _bulk_get response for odd indexed documents MockDocumentBulkGet mockBulkGet = new MockDocumentBulkGet(); mockBulkGet.addDocument(mockDocument1); mockDocument2.setMissing(true); mockBulkGet.addDocument(mockDocument2); mockBulkGet.addDocument(mockDocument3); mockBulkGet.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_BULK_GET, mockBulkGet); // checkpoint PUT response MockCheckpointPut mockCheckpointPut = new MockCheckpointPut(); mockCheckpointPut.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, mockCheckpointPut); // start mock server server.start(); //create replication Replication pull = database.createPullReplication(server.url("/db").url()); pull.setContinuous(false); //add change listener to notify when the replication is finished CountDownLatch replicationIdleSignal = new CountDownLatch(1); pull.addChangeListener(new ReplicationFinishedObserver(replicationIdleSignal)); //start replication pull.start(); boolean success = replicationIdleSignal.await(30, TimeUnit.SECONDS); assertTrue(success); if (pull.getLastError() != null) Log.d(TAG, "Replication had error: ", pull.getLastError()); assertNull(pull.getLastError()); assertEquals(2, database.getDocumentCount()); //assert document 1 was correctly pulled Document doc1 = database.getDocument(doc1Id); assertNotNull(doc1); assertNotNull(doc1.getCurrentRevision()); assertEquals("1-0001", doc1.getCurrentRevision().getId()); //assert it was possible to pull doc3 Document doc3 = database.getDocument(doc3Id); assertNotNull(doc3); assertEquals("1-0003", doc3.getCurrentRevision().getId()); } finally { assertTrue(MockHelper.shutdown(server, dispatcher)); } } // continuous pull replication with _bulk_get with missing revision - erro scenario public void testContPullReplBulkGetWithMissingRev() throws Exception { String doc1Id = "doc1"; String doc2Id = "doc2"; String doc3Id = "doc3"; final MockDocumentGet.MockDocument mockDocument1 = new MockDocumentGet.MockDocument(doc1Id, "1-0001", 1); mockDocument1.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument2 = new MockDocumentGet.MockDocument(doc2Id, "1-0002", 2); mockDocument2.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument3 = new MockDocumentGet.MockDocument(doc3Id, "1-0003", 3); mockDocument3.setJsonMap(MockHelper.generateRandomJsonMap()); // create mockwebserver and custom dispatcher MockDispatcher dispatcher = new MockDispatcher(); MockWebServer server = MockHelper.getMockWebServer(dispatcher); dispatcher.setServerType(MockDispatcher.ServerType.SYNC_GW); try { //add response to _local request // checkpoint GET response w/ 404 MockResponse fakeCheckpointResponse = new MockResponse(); MockHelper.set404NotFoundJson(fakeCheckpointResponse); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, fakeCheckpointResponse); //add response to _changes request // _changes response MockChangesFeed mockChangesFeed = new MockChangesFeed(); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument1)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument2)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument3)); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHANGES, mockChangesFeed.generateMockResponse()); // add sticky _changes response to feed=longpoll that just blocks for 60 seconds // to emulate server that doesn't have any new changes MockChangesFeedNoResponse mockChangesFeedNoResponse = new MockChangesFeedNoResponse(); mockChangesFeedNoResponse.setDelayMs(60 * 1000); mockChangesFeedNoResponse.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHANGES, mockChangesFeedNoResponse); // _bulk_get response for odd indexed documents MockDocumentBulkGet mockBulkGet = new MockDocumentBulkGet(); mockBulkGet.addDocument(mockDocument1); mockDocument2.setMissing(true); mockBulkGet.addDocument(mockDocument2); mockBulkGet.addDocument(mockDocument3); mockBulkGet.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_BULK_GET, mockBulkGet); // checkpoint PUT response MockCheckpointPut mockCheckpointPut = new MockCheckpointPut(); mockCheckpointPut.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, mockCheckpointPut); // start mock server server.start(); //create replication Replication pull = database.createPullReplication(server.url("/db").url()); pull.setContinuous(true); CountDownLatch replicationIdleSignal = new CountDownLatch(1); pull.addChangeListener(new ReplicationIdleObserver(replicationIdleSignal)); CountDownLatch replicationDoneSignal = new CountDownLatch(1); pull.addChangeListener(new ReplicationFinishedObserver(replicationDoneSignal)); pull.start(); assertTrue(replicationIdleSignal.await(30, TimeUnit.SECONDS)); pull.stop(); assertTrue(replicationDoneSignal.await(30, TimeUnit.SECONDS)); if (pull.getLastError() != null) Log.d(TAG, "Replication had error: ", pull.getLastError()); assertNull(pull.getLastError()); assertEquals(2, database.getDocumentCount()); Document doc1 = database.getDocument(doc1Id); assertNotNull(doc1); assertNotNull(doc1.getCurrentRevision()); assertEquals("1-0001", doc1.getCurrentRevision().getId()); Document doc3 = database.getDocument(doc3Id); assertNotNull(doc3); assertNotNull(doc3.getCurrentRevision()); assertEquals("1-0003", doc3.getCurrentRevision().getId()); } finally { assertTrue(MockHelper.shutdown(server, dispatcher)); } } // one shot pull replication with _bulk_get - 404 should stop immediately - error scenario public void testOneShotPullReplBulkGetWith404() throws Exception { String doc1Id = "doc1"; String doc2Id = "doc2"; String doc3Id = "doc3"; final MockDocumentGet.MockDocument mockDocument1 = new MockDocumentGet.MockDocument(doc1Id, "1-0001", 1); mockDocument1.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument2 = new MockDocumentGet.MockDocument(doc2Id, "1-0002", 2); mockDocument2.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument3 = new MockDocumentGet.MockDocument(doc3Id, "1-0003", 3); mockDocument3.setJsonMap(MockHelper.generateRandomJsonMap()); // create mockwebserver and custom dispatcher MockDispatcher dispatcher = new MockDispatcher(); MockWebServer server = MockHelper.getMockWebServer(dispatcher); dispatcher.setServerType(MockDispatcher.ServerType.SYNC_GW); try { //add response to _local request // checkpoint GET response w/ 404 MockResponse fakeCheckpointResponse = new MockResponse(); MockHelper.set404NotFoundJson(fakeCheckpointResponse); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, fakeCheckpointResponse); //add response to _changes request // _changes response MockChangesFeed mockChangesFeed = new MockChangesFeed(); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument1)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument2)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument3)); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHANGES, mockChangesFeed.generateMockResponse()); // _bulk_get response for odd indexed documents MockDocumentBulkGet mockBulkGet = new MockDocumentBulkGet(); mockBulkGet.addDocument(mockDocument1); mockBulkGet.addDocument(mockDocument2); mockBulkGet.addDocument(mockDocument3); mockBulkGet.setSticky(true); mockBulkGet.set404(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_BULK_GET, mockBulkGet); // checkpoint PUT response MockCheckpointPut mockCheckpointPut = new MockCheckpointPut(); mockCheckpointPut.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, mockCheckpointPut); // start mock server server.start(); //create replication Replication pull = database.createPullReplication(server.url("/db").url()); pull.setContinuous(false); //add change listener to notify when the replication is finished CountDownLatch replicationIdleSignal = new CountDownLatch(1); pull.addChangeListener(new ReplicationFinishedObserver(replicationIdleSignal)); //start replication pull.start(); boolean success = replicationIdleSignal.await(30, TimeUnit.SECONDS); assertTrue(success); assertNotNull(pull.getLastError()); Log.d(TAG, "Replication had error: ", pull.getLastError()); assertEquals(0, database.getDocumentCount()); } finally { assertTrue(MockHelper.shutdown(server, dispatcher)); } } // continuous pull replication with _bulk_get - 404 should stop immediately - error scenario public void testContPullReplBulkGetWith404() throws Exception { String doc1Id = "doc1"; String doc2Id = "doc2"; String doc3Id = "doc3"; final MockDocumentGet.MockDocument mockDocument1 = new MockDocumentGet.MockDocument(doc1Id, "1-0001", 1); mockDocument1.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument2 = new MockDocumentGet.MockDocument(doc2Id, "1-0002", 2); mockDocument2.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument3 = new MockDocumentGet.MockDocument(doc3Id, "1-0003", 3); mockDocument3.setJsonMap(MockHelper.generateRandomJsonMap()); // create mockwebserver and custom dispatcher MockDispatcher dispatcher = new MockDispatcher(); MockWebServer server = MockHelper.getMockWebServer(dispatcher); dispatcher.setServerType(MockDispatcher.ServerType.SYNC_GW); try { //add response to _local request // checkpoint GET response w/ 404 MockResponse fakeCheckpointResponse = new MockResponse(); MockHelper.set404NotFoundJson(fakeCheckpointResponse); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, fakeCheckpointResponse); //add response to _changes request // _changes response MockChangesFeed mockChangesFeed = new MockChangesFeed(); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument1)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument2)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument3)); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHANGES, mockChangesFeed.generateMockResponse()); // add sticky _changes response to feed=longpoll that just blocks for 60 seconds // to emulate server that doesn't have any new changes MockChangesFeedNoResponse mockChangesFeedNoResponse = new MockChangesFeedNoResponse(); mockChangesFeedNoResponse.setDelayMs(60 * 1000); mockChangesFeedNoResponse.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHANGES, mockChangesFeedNoResponse); // _bulk_get response for odd indexed documents MockDocumentBulkGet mockBulkGet = new MockDocumentBulkGet(); mockBulkGet.addDocument(mockDocument1); mockBulkGet.addDocument(mockDocument2); mockBulkGet.addDocument(mockDocument3); mockBulkGet.setSticky(true); mockBulkGet.set404(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_BULK_GET, mockBulkGet); // checkpoint PUT response MockCheckpointPut mockCheckpointPut = new MockCheckpointPut(); mockCheckpointPut.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, mockCheckpointPut); // start mock server server.start(); //create replication Replication pull = database.createPullReplication(server.url("/db").url()); pull.setContinuous(true); CountDownLatch replicationDoneSignal = new CountDownLatch(1); pull.addChangeListener(new ReplicationFinishedObserver(replicationDoneSignal)); pull.start(); assertTrue(replicationDoneSignal.await(30, TimeUnit.SECONDS)); assertNotNull(pull.getLastError()); Log.d(TAG, "Replication had error: ", pull.getLastError()); assertEquals(0, database.getDocumentCount()); } finally { assertTrue(MockHelper.shutdown(server, dispatcher)); } } public void testServerIsSyncGatewayVersion() { // sync gateway 1.2 assertFalse(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/1.2 branch/fix/server_header commit/5bfcf79+CHANGES", "1.3")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/1.2 branch/fix/server_header commit/5bfcf79+CHANGES", "1.2")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/1.2 branch/fix/server_header commit/5bfcf79+CHANGES", "1.1")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/1.2 branch/fix/server_header commit/5bfcf79+CHANGES", "0.93")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/1.2 branch/fix/server_header commit/5bfcf79+CHANGES", "0.92")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/1.2 branch/fix/server_header commit/5bfcf79+CHANGES", "0.81")); // sync gateway 1.0 or 1.1 assertFalse(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/1.0", "1.3")); assertFalse(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/1.0", "1.2")); assertFalse(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/1.0", "1.1")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/1.0", "0.93")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/1.0", "0.92")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/1.0", "0.81")); // before 1.0 release (beta) assertFalse(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/0.92", "1.3")); assertFalse(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/0.92", "1.2")); assertFalse(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/0.92", "1.1")); assertFalse(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/0.92", "0.93")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/0.92", "0.92")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/0.92", "0.81")); // developer build 1.1 or earlier ('a' > '0') assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/unofficial", "1.3")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/unofficial", "1.2")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/unofficial", "1.1")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/unofficial", "0.93")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/unofficial", "0.92")); assertTrue(ReplicationInternal.serverIsSyncGatewayVersion( "Couchbase Sync Gateway/unofficial", "0.81")); } public void testUserAgent() throws Exception { String doc1Id = "doc1"; String doc2Id = "doc2"; String doc3Id = "doc3"; final MockDocumentGet.MockDocument mockDocument1 = new MockDocumentGet.MockDocument(doc1Id, "1-0001", 1); mockDocument1.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument2 = new MockDocumentGet.MockDocument(doc2Id, "1-0002", 2); mockDocument2.setJsonMap(MockHelper.generateRandomJsonMap()); final MockDocumentGet.MockDocument mockDocument3 = new MockDocumentGet.MockDocument(doc3Id, "1-0003", 3); mockDocument3.setJsonMap(MockHelper.generateRandomJsonMap()); // create mockwebserver and custom dispatcher MockDispatcher dispatcher = new MockDispatcher(); MockWebServer server = MockHelper.getMockWebServer(dispatcher); dispatcher.setServerType(MockDispatcher.ServerType.SYNC_GW); try { //add response to _local request // checkpoint GET response w/ 404 MockResponse fakeCheckpointResponse = new MockResponse(); MockHelper.set404NotFoundJson(fakeCheckpointResponse); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, fakeCheckpointResponse); //add response to _changes request // _changes response MockChangesFeed mockChangesFeed = new MockChangesFeed(); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument1)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument2)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDocument3)); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHANGES, mockChangesFeed.generateMockResponse()); // _bulk_get response for odd indexed documents MockDocumentBulkGet mockBulkGet = new MockDocumentBulkGet(); mockBulkGet.addDocument(mockDocument1); mockBulkGet.addDocument(mockDocument2); mockBulkGet.addDocument(mockDocument3); mockBulkGet.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_BULK_GET, mockBulkGet); // checkpoint PUT response MockCheckpointPut mockCheckpointPut = new MockCheckpointPut(); mockCheckpointPut.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, mockCheckpointPut); // start mock server server.start(); //create replication Replication pull = database.createPullReplication(server.url("/db").url()); pull.setContinuous(false); //add change listener to notify when the replication is finished CountDownLatch replicationIdleSignal = new CountDownLatch(1); pull.addChangeListener(new ReplicationFinishedObserver(replicationIdleSignal)); //start replication pull.start(); boolean success = replicationIdleSignal.await(30, TimeUnit.SECONDS); assertTrue(success); if (pull.getLastError() != null) Log.d(TAG, "Replication had error: ", pull.getLastError()); assertNull(pull.getLastError()); // wait until the replicator PUT's checkpoint with mockDocument3's sequence waitForPutCheckpointRequestWithSeq(dispatcher, mockDocument3.getDocSeq()); // Check User-Agent Header value for /_changes and /_bulk_get // CheckPoint is validated by waitForPutCheckpointRequestWithSeq() method checkUserAgent(dispatcher.takeRequestBlocking(MockHelper.PATH_REGEX_CHANGES)); checkUserAgent(dispatcher.takeRequestBlocking(MockHelper.PATH_REGEX_BULK_GET)); } finally { assertTrue(MockHelper.shutdown(server, dispatcher)); } } public void testStopReplication() throws Exception { MockWebServer server = null; MockDispatcher dispatcher = new MockDispatcher(); try { // Create mock server and play: server = MockHelper.getMockWebServer(dispatcher); dispatcher.setServerType(MockDispatcher.ServerType.SYNC_GW); server.start(); // Mock documents to be pulled: MockDocumentGet.MockDocument mockDoc1 = new MockDocumentGet.MockDocument("doc1", "1-5e38", 1); mockDoc1.setJsonMap(MockHelper.generateRandomJsonMap()); MockDocumentGet.MockDocument mockDoc2 = new MockDocumentGet.MockDocument("doc2", "1-563b", 2); mockDoc2.setJsonMap(MockHelper.generateRandomJsonMap()); // // checkpoint GET response w/ 404: MockResponse fakeCheckpointResponse = new MockResponse(); MockHelper.set404NotFoundJson(fakeCheckpointResponse); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, fakeCheckpointResponse); // _changes response: MockChangesFeed mockChangesFeed = new MockChangesFeed(); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDoc1)); mockChangesFeed.add(new MockChangesFeed.MockChangedDoc(mockDoc2)); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHANGES, mockChangesFeed.generateMockResponse(/*gzip*/true)); // add sticky _changes response to feed=longpoll that just blocks for 60 seconds // to emulate server that doesn't have any new changes MockChangesFeedNoResponse mockChangesFeedNoResponse = new MockChangesFeedNoResponse(); mockChangesFeedNoResponse.setDelayMs(120 * 1000); mockChangesFeedNoResponse.setSticky(true); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHANGES_LONGPOLL, mockChangesFeedNoResponse); // doc1 response: MockDocumentGet mockDocumentGet = new MockDocumentGet(mockDoc1); dispatcher.enqueueResponse(mockDoc1.getDocPathRegex(), mockDocumentGet.generateMockResponse()); // doc2 response: mockDocumentGet = new MockDocumentGet(mockDoc2); dispatcher.enqueueResponse(mockDoc2.getDocPathRegex(), mockDocumentGet.generateMockResponse()); // _bulk_get response: MockDocumentBulkGet mockBulkGet = new MockDocumentBulkGet(); mockBulkGet.addDocument(mockDoc1); mockBulkGet.addDocument(mockDoc2); mockBulkGet.setDelayMs(120 * 1000); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_BULK_GET, mockBulkGet); // Respond to all PUT Checkpoint requests MockCheckpointPut mockCheckpointPut = new MockCheckpointPut(); mockCheckpointPut.setSticky(true); mockCheckpointPut.setDelayMs(500); dispatcher.enqueueResponse(MockHelper.PATH_REGEX_CHECKPOINT, mockCheckpointPut); // Run pull replication: Replication pull = database.createPullReplication(server.url("/db").url()); pull.setContinuous(true); final CountDownLatch doneSignal = new CountDownLatch(1); pull.addChangeListener(new ReplicationFinishedObserver(doneSignal)); final CountDownLatch idleSignal = new CountDownLatch(1); pull.addChangeListener(new ReplicationIdleObserver(idleSignal)); final CountDownLatch changeSignal = new CountDownLatch(1); pull.addChangeListener(new Replication.ChangeListener() { @Override public void changed(Replication.ChangeEvent event) { if (event.getChangeCount() > 0) changeSignal.countDown(); } }); pull.start(); // wait until idle assertTrue(changeSignal.await(30, TimeUnit.SECONDS)); pull.stop(); assertTrue(doneSignal.await(30, TimeUnit.SECONDS)); } finally { assertTrue(MockHelper.shutdown(server, dispatcher)); } } }