// // Copyright (c) 2016 Couchbase, Inc. All rights reserved. // // 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.couchbase.lite.replicator; import com.couchbase.lite.CouchbaseLiteException; import com.couchbase.lite.Database; import com.couchbase.lite.LiteTestCaseWithDB; import com.couchbase.lite.auth.FacebookAuthorizer; import com.couchbase.lite.util.Log; import junit.framework.Assert; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Tests for the new state machine based replicator */ public class ReplicationTest extends LiteTestCaseWithDB { /** * TestCase(CreateReplicators) in ReplicationAPITests.m */ public void testCreateReplicators() throws Exception { URL fakeRemoteURL = new URL("http://fake.fake/fakedb"); // Create a replication: assertEquals(0, database.getAllReplications().size()); Replication r1 = database.createPushReplication(fakeRemoteURL); assertNotNull(r1); // Check the replication's properties: assertEquals(database, r1.getLocalDatabase()); assertEquals(fakeRemoteURL, r1.getRemoteUrl()); assertFalse(r1.isPull()); assertFalse(r1.isContinuous()); assertFalse(r1.shouldCreateTarget()); assertNull(r1.getFilter()); assertNull(r1.getFilterParams()); assertNull(r1.getDocIds()); assertEquals(0, r1.getHeaders().size()); // Check that the replication hasn't started running: assertFalse(r1.isRunning()); assertEquals(Replication.ReplicationStatus.REPLICATION_STOPPED, r1.getStatus()); assertEquals(0, r1.getChangesCount()); assertEquals(0, r1.getCompletedChangesCount()); assertNull(r1.getLastError()); // Create another replication: Replication r2 = database.createPullReplication(fakeRemoteURL); assertNotNull(r2); assertTrue(r1 != r2); // Check the replication's properties: assertEquals(database, r2.getLocalDatabase()); assertEquals(fakeRemoteURL, r2.getRemoteUrl()); assertTrue(r2.isPull()); Replication r3 = database.createPullReplication(fakeRemoteURL); assertNotNull(r3); assertTrue(r3 != r2); r3.setDocIds(Arrays.asList("doc1", "doc2")); Replication repl = database.getManager().getReplicator(r3.getProperties()); assertEquals(r3.getDocIds(), repl.getDocIds()); } /** * Start continuous replication with a closed db. * <p/> * Expected behavior: * - Receive replication finished callback * - Replication lastError will contain an exception */ public void testStartReplicationClosedDb() throws Exception { Database db = this.manager.getDatabase("closed"); final CountDownLatch countDownLatch = new CountDownLatch(1); final Replication replication = db.createPullReplication(new URL("http://fake.com/foo")); replication.setContinuous(true); replication.addChangeListener(new Replication.ChangeListener() { @Override public void changed(Replication.ChangeEvent event) { Log.d(TAG, "changed event: %s", event); if (replication.isRunning() == false) { countDownLatch.countDown(); } } }); db.close(); replication.start(); boolean success = countDownLatch.await(60, TimeUnit.SECONDS); assertTrue(success); assertTrue(replication.getLastError() != null); } public void testServerIsSyncGatewayVersion() throws Exception { Replication pusher = database.createPushReplication(getReplicationURL()); assertFalse(pusher.serverIsSyncGatewayVersion("0.01")); pusher.setServerType("Couchbase Sync Gateway/0.93"); assertTrue(pusher.serverIsSyncGatewayVersion("0.92")); assertFalse(pusher.serverIsSyncGatewayVersion("0.94")); } /** * https://github.com/couchbase/couchbase-lite-android/issues/243 */ public void testDifferentCheckpointsFilteredReplication() throws Exception { Replication pullerNoFilter = database.createPullReplication(getReplicationURL()); String noFilterCheckpointDocId = pullerNoFilter.remoteCheckpointDocID(); Replication pullerWithFilter1 = database.createPullReplication(getReplicationURL()); pullerWithFilter1.setFilter("foo/bar"); Map<String, Object> filterParams = new HashMap<String, Object>(); filterParams.put("a", "aval"); filterParams.put("b", "bval"); List<String> docIds = Arrays.asList("doc3", "doc1", "doc2"); pullerWithFilter1.setDocIds(docIds); assertEquals(docIds, pullerWithFilter1.getDocIds()); pullerWithFilter1.setFilterParams(filterParams); String withFilterCheckpointDocId = pullerWithFilter1.remoteCheckpointDocID(); assertFalse(withFilterCheckpointDocId.equals(noFilterCheckpointDocId)); Replication pullerWithFilter2 = database.createPullReplication(getReplicationURL()); pullerWithFilter2.setFilter("foo/bar"); filterParams = new HashMap<String, Object>(); filterParams.put("b", "bval"); filterParams.put("a", "aval"); pullerWithFilter2.setDocIds(Arrays.asList("doc2", "doc3", "doc1")); pullerWithFilter2.setFilterParams(filterParams); String withFilterCheckpointDocId2 = pullerWithFilter2.remoteCheckpointDocID(); assertTrue(withFilterCheckpointDocId.equals(withFilterCheckpointDocId2)); } public void testBuildRelativeURLString() throws Exception { String dbUrlString = "http://10.0.0.3:4984/todos/"; Replication replication = database.createPullReplication(new URL(dbUrlString)); String relativeUrlString = replication.buildRelativeURLString("foo"); String expected = "http://10.0.0.3:4984/todos/foo"; Assert.assertEquals(expected, relativeUrlString); } public void testBuildRelativeURLStringWithLeadingSlash() throws Exception { String dbUrlString = "http://10.0.0.3:4984/todos/"; Replication replication = database.createPullReplication(new URL(dbUrlString)); String relativeUrlString = replication.buildRelativeURLString("/foo"); String expected = "http://10.0.0.3:4984/foo"; Assert.assertEquals(expected, relativeUrlString); relativeUrlString = replication.buildRelativeURLString("foo"); expected = "http://10.0.0.3:4984/todos/foo"; Assert.assertEquals(expected, relativeUrlString); } public void testChannels() throws Exception { URL remote = getReplicationURL(); Replication replicator = database.createPullReplication(remote); List<String> channels = new ArrayList<String>(); channels.add("chan1"); channels.add("chan2"); replicator.setChannels(channels); Assert.assertEquals(channels, replicator.getChannels()); replicator.setChannels(null); Assert.assertTrue(replicator.getChannels().isEmpty()); } public void testChannelsMore() throws MalformedURLException, CouchbaseLiteException { Database db = startDatabase(); URL fakeRemoteURL = new URL("http://couchbase.com/no_such_db"); Replication r1 = db.createPullReplication(fakeRemoteURL); assertTrue(r1.getChannels().isEmpty()); r1.setFilter("foo/bar"); assertTrue(r1.getChannels().isEmpty()); Map<String, Object> filterParams = new HashMap<String, Object>(); filterParams.put("a", "b"); r1.setFilterParams(filterParams); assertTrue(r1.getChannels().isEmpty()); r1.setChannels(null); assertEquals("foo/bar", r1.getFilter()); assertEquals(filterParams, r1.getFilterParams()); List<String> channels = new ArrayList<String>(); channels.add("NBC"); channels.add("MTV"); r1.setChannels(channels); assertEquals(channels, r1.getChannels()); assertEquals("sync_gateway/bychannel", r1.getFilter()); filterParams = new HashMap<String, Object>(); filterParams.put("channels", "NBC,MTV"); assertEquals(filterParams, r1.getFilterParams()); r1.setChannels(null); assertEquals(r1.getFilter(), null); assertEquals(null, r1.getFilterParams()); } public void testGetReplicatorWithAuth() throws Throwable { Map<String, Object> authProperties = getReplicationAuthParsedJson(); Map<String, Object> targetProperties = new HashMap<String, Object>(); targetProperties.put("url", getReplicationURL().toExternalForm()); targetProperties.put("auth", authProperties); Map<String, Object> properties = new HashMap<String, Object>(); properties.put("source", DEFAULT_TEST_DB); properties.put("target", targetProperties); Replication replicator = manager.getReplicator(properties); assertNotNull(replicator); assertNotNull(replicator.getAuthenticator()); assertTrue(replicator.getAuthenticator() instanceof FacebookAuthorizer); } // ReplicatorInternal.m: test_UseRemoteUUID public void testUseRemoteUUID() throws Exception { URL remoteURL1 = new URL("http://alice.local:55555/db"); Replication r1 = database.createPullReplication(remoteURL1); r1.setRemoteUUID("cafebabe"); String check1 = r1.replicationInternal.remoteCheckpointDocID(); // Different URL, but same remoteUUID: URL remoteURL2 = new URL("http://alice17.local:44444/db"); Replication r2 = database.createPullReplication(remoteURL2); r2.setRemoteUUID("cafebabe"); String check2 = r2.replicationInternal.remoteCheckpointDocID(); assertEquals(check1, check2); // Same UUID but different filter settings: Replication r3 = database.createPullReplication(remoteURL2); r3.setRemoteUUID("cafebabe"); r3.setFilter("Melitta"); String check3 = r3.replicationInternal.remoteCheckpointDocID(); assertNotSame(check2, check3); } }