Android Open Source - couchbase-lite-android Rev Tree Test






From Project

Back to project page couchbase-lite-android.

License

The source code is released under:

Apache License

If you think the Android project couchbase-lite-android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * Original iOS version by  Jens Alfke/*from  ww w. ja v  a  2  s  .c om*/
 * Ported to Android by Marty Schoch
 *
 * Copyright (c) 2012 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;

import com.couchbase.lite.internal.RevisionInternal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RevTreeTest extends LiteTestCase {

    public static final String TAG = "RevTree";

    public void testForceInsertEmptyHistory() throws CouchbaseLiteException {

        List<String> revHistory = null;
        RevisionInternal rev = new RevisionInternal("FakeDocId", "1-tango", false, database);

        Map<String, Object> revProperties = new HashMap<String, Object>();
        revProperties.put("_id", rev.getDocId());
        revProperties.put("_rev", rev.getRevId());
        revProperties.put("message", "hi");
        rev.setProperties(revProperties);

        database.forceInsert(rev, revHistory, null);

    }

    public void testRevTree() throws CouchbaseLiteException {

        RevisionInternal rev = new RevisionInternal("MyDocId", "4-foxy", false, database);

        Map<String, Object> revProperties = new HashMap<String, Object>();
        revProperties.put("_id", rev.getDocId());
        revProperties.put("_rev", rev.getRevId());
        revProperties.put("message", "hi");
        rev.setProperties(revProperties);

        List<String> revHistory = new ArrayList<String>();
        revHistory.add(rev.getRevId());
        revHistory.add("3-thrice");
        revHistory.add("2-too");
        revHistory.add("1-won");

        database.forceInsert(rev, revHistory, null);
        assertEquals(1, database.getDocumentCount());
        verifyHistory(database, rev, revHistory);

        RevisionInternal conflict = new RevisionInternal("MyDocId", "5-epsilon", false, database);

        Map<String, Object> conflictProperties = new HashMap<String, Object>();
        conflictProperties.put("_id", conflict.getDocId());
        conflictProperties.put("_rev", conflict.getRevId());
        conflictProperties.put("message", "yo");
        conflict.setProperties(conflictProperties);

        List<String> conflictHistory = new ArrayList<String>();
        conflictHistory.add(conflict.getRevId());
        conflictHistory.add("4-delta");
        conflictHistory.add("3-gamma");
        conflictHistory.add("2-too");
        conflictHistory.add("1-won");

        final List wasInConflict = new ArrayList();
        final Database.ChangeListener listener = new Database.ChangeListener() {
            @Override
            public void changed(Database.ChangeEvent event) {
                if (event.getChanges().get(0).isConflict()) {
                    wasInConflict.add(new Object());
                }
            }
        };
        database.addChangeListener(listener);
        database.forceInsert(conflict, conflictHistory, null);
        assertTrue(wasInConflict.size() > 0);
        database.removeChangeListener(listener);
        assertEquals(1, database.getDocumentCount());
        verifyHistory(database, conflict, conflictHistory);

        // Add an unrelated document:
        RevisionInternal other = new RevisionInternal("AnotherDocID", "1-ichi", false, database);
        Map<String,Object> otherProperties = new HashMap<String,Object>();
        otherProperties.put("language", "jp");
        other.setProperties(otherProperties);
        List<String> otherHistory = new ArrayList<String>();
        otherHistory.add(other.getRevId());
        database.forceInsert(other, otherHistory, null);

        // Fetch one of those phantom revisions with no body:
        RevisionInternal rev2 = database.getDocumentWithIDAndRev(rev.getDocId(), "2-too", EnumSet.noneOf(Database.TDContentOptions.class));
        assertEquals(rev.getDocId(), rev2.getDocId());
        assertEquals("2-too", rev2.getRevId());
        //Assert.assertNull(rev2.getContent());

        // Make sure no duplicate rows were inserted for the common revisions:
        assertEquals(8, database.getLastSequenceNumber());

        // Make sure the revision with the higher revID wins the conflict:
        RevisionInternal current = database.getDocumentWithIDAndRev(rev.getDocId(), null, EnumSet.noneOf(Database.TDContentOptions.class));
        assertEquals(conflict, current);

        // Get the _changes feed and verify only the winner is in it:
        ChangesOptions options = new ChangesOptions();
        RevisionList changes = database.changesSince(0, options, null);
        RevisionList expectedChanges = new RevisionList();
        expectedChanges.add(conflict);
        expectedChanges.add(other);
        assertEquals(changes, expectedChanges);
        options.setIncludeConflicts(true);
        changes = database.changesSince(0, options, null);
        expectedChanges = new RevisionList();
        expectedChanges.add(rev);
        expectedChanges.add(conflict);
        expectedChanges.add(other);
        assertEquals(changes, expectedChanges);
    }

    /**
     * Test that the public API works as expected in change notifications after a rev tree
     * insertion.  See https://github.com/couchbase/couchbase-lite-android-core/pull/27
     */
    public void testRevTreeChangeNotifications() throws CouchbaseLiteException {
        final String DOCUMENT_ID = "MyDocId";

        // add a document with a single (first) revision
        final RevisionInternal rev = new RevisionInternal(DOCUMENT_ID, "1-one", false, database);
        Map<String, Object> revProperties = new HashMap<String, Object>();
        revProperties.put("_id", rev.getDocId());
        revProperties.put("_rev", rev.getRevId());
        revProperties.put("message", "hi");
        rev.setProperties(revProperties);

        List<String> revHistory = Arrays.asList(rev.getRevId());

        Database.ChangeListener listener = new Database.ChangeListener() {
            @Override
            public void changed(Database.ChangeEvent event) {
                assertEquals(1, event.getChanges().size());
                DocumentChange change = event.getChanges().get(0);
                assertEquals(DOCUMENT_ID, change.getDocumentId());
                assertEquals(rev.getRevId(), change.getRevisionId());
                assertTrue(change.isCurrentRevision());
                assertFalse(change.isConflict());

                SavedRevision current = database.getDocument(change.getDocumentId()).getCurrentRevision();
                assertEquals(rev.getRevId(), current.getId());
            }
        };
        database.addChangeListener(listener);
        database.forceInsert(rev, revHistory, null);
        database.removeChangeListener(listener);

        // add two more revisions to the document
        final RevisionInternal rev3 = new RevisionInternal(DOCUMENT_ID, "3-three", false, database);
        Map<String, Object> rev3Properties = new HashMap<String, Object>();
        rev3Properties.put("_id", rev3.getDocId());
        rev3Properties.put("_rev", rev3.getRevId());
        rev3Properties.put("message", "hi again");
        rev3.setProperties(rev3Properties);

        List<String> rev3History = Arrays.asList(rev3.getRevId(), "2-two", rev.getRevId());

        listener = new Database.ChangeListener() {
            @Override
            public void changed(Database.ChangeEvent event) {
                assertEquals(1, event.getChanges().size());
                DocumentChange change = event.getChanges().get(0);
                assertEquals(DOCUMENT_ID, change.getDocumentId());
                assertEquals(rev3.getRevId(), change.getRevisionId());
                assertTrue(change.isCurrentRevision());
                assertFalse(change.isConflict());

                Document doc = database.getDocument(change.getDocumentId());
                assertEquals(rev3.getRevId(), doc.getCurrentRevisionId());
                try {
                    assertEquals(3, doc.getRevisionHistory().size());
                } catch (CouchbaseLiteException ex) {
                    fail("CouchbaseLiteException in change listener: " + ex.toString());
                }
            }
        };
        database.addChangeListener(listener);
        database.forceInsert(rev3, rev3History, null);
        database.removeChangeListener(listener);

        // add a conflicting revision, with the same history length as the last revision we
        // inserted. Since this new revision's revID has a higher ASCII sort, it should become the
        // new winning revision.
        final RevisionInternal conflictRev = new RevisionInternal(DOCUMENT_ID, "3-winner", false, database);
        Map<String, Object> conflictProperties = new HashMap<String, Object>();
        conflictProperties.put("_id", conflictRev.getDocId());
        conflictProperties.put("_rev", conflictRev.getRevId());
        conflictProperties.put("message", "winner");
        conflictRev.setProperties(conflictProperties);

        List<String> conflictRevHistory = Arrays.asList(conflictRev.getRevId(), "2-two", rev.getRevId());

        listener = new Database.ChangeListener() {
            @Override
            public void changed(Database.ChangeEvent event) {
                assertEquals(1, event.getChanges().size());
                DocumentChange change = event.getChanges().get(0);
                assertEquals(DOCUMENT_ID, change.getDocumentId());
                assertEquals(conflictRev.getRevId(), change.getRevisionId());
                assertTrue(change.isCurrentRevision());
                assertTrue(change.isConflict());

                Document doc = database.getDocument(change.getDocumentId());
                assertEquals(conflictRev.getRevId(), doc.getCurrentRevisionId());
                try {
                    assertEquals(2, doc.getConflictingRevisions().size());
                    assertEquals(3, doc.getRevisionHistory().size());
                } catch (CouchbaseLiteException ex) {
                    fail("CouchbaseLiteException in change listener: " + ex.toString());
                }
            }
        };
        database.addChangeListener(listener);
        database.forceInsert(conflictRev, conflictRevHistory, null);
        database.removeChangeListener(listener);
    }

    private static void verifyHistory(Database db, RevisionInternal rev, List<String> history) {
        RevisionInternal gotRev = db.getDocumentWithIDAndRev(rev.getDocId(), null, EnumSet.noneOf(Database.TDContentOptions.class));
        assertEquals(rev, gotRev);
        assertEquals(rev.getProperties(), gotRev.getProperties());

        List<RevisionInternal> revHistory = db.getRevisionHistory(gotRev);
        assertEquals(history.size(), revHistory.size());
        for(int i=0; i<history.size(); i++) {
            RevisionInternal hrev = revHistory.get(i);
            assertEquals(rev.getDocId(), hrev.getDocId());
            assertEquals(history.get(i), hrev.getRevId());
            assertFalse(rev.isDeleted());
        }
    }

}




Java Source Code List

com.couchbase.lite.ApiTest.java
com.couchbase.lite.AttachmentsTest.java
com.couchbase.lite.AuthTest.java
com.couchbase.lite.Base64Test.java
com.couchbase.lite.BlobStoreWriterTest.java
com.couchbase.lite.CRUDOperationsTest.java
com.couchbase.lite.CacheTest.java
com.couchbase.lite.ChangesTest.java
com.couchbase.lite.CollationTest.java
com.couchbase.lite.DatabaseTest.java
com.couchbase.lite.DocumentTest.java
com.couchbase.lite.LitePerfTestCase.java
com.couchbase.lite.LiteTestCase.java
com.couchbase.lite.LiteTestContext.java
com.couchbase.lite.LocalDocsTest.java
com.couchbase.lite.ManagerTest.java
com.couchbase.lite.MiscTest.java
com.couchbase.lite.MultipartReaderTest.java
com.couchbase.lite.RevTreeTest.java
com.couchbase.lite.RevisionsTest.java
com.couchbase.lite.RouterTest.java
com.couchbase.lite.SequenceMapTest.java
com.couchbase.lite.ValidationsTest.java
com.couchbase.lite.ViewsTest.java
com.couchbase.lite.android.AndroidContext.java
com.couchbase.lite.android.AndroidLogger.java
com.couchbase.lite.android.AndroidNetworkReachabilityManager.java
com.couchbase.lite.android.AndroidSQLiteStorageEngineFactory.java
com.couchbase.lite.android.AndroidSQLiteStorageEngine.java
com.couchbase.lite.mockserver.MockBulkDocs.java
com.couchbase.lite.mockserver.MockChangesFeedNoResponse.java
com.couchbase.lite.mockserver.MockChangesFeed.java
com.couchbase.lite.mockserver.MockCheckpointGet.java
com.couchbase.lite.mockserver.MockCheckpointPut.java
com.couchbase.lite.mockserver.MockDispatcher.java
com.couchbase.lite.mockserver.MockDocumentBulkGet.java
com.couchbase.lite.mockserver.MockDocumentGet.java
com.couchbase.lite.mockserver.MockDocumentPut.java
com.couchbase.lite.mockserver.MockFacebookAuthPost.java
com.couchbase.lite.mockserver.MockHelper.java
com.couchbase.lite.mockserver.MockPreloadedPullTarget.java
com.couchbase.lite.mockserver.MockRevsDiff.java
com.couchbase.lite.mockserver.MockSessionGet.java
com.couchbase.lite.mockserver.SmartMockResponse.java
com.couchbase.lite.mockserver.WrappedSmartMockResponse.java
com.couchbase.lite.performance2.Test01_CreateDocs.java
com.couchbase.lite.performance2.Test02_CreateDocsUnoptimizedWay.java
com.couchbase.lite.performance2.Test03_CreateDocsWithAttachments.java
com.couchbase.lite.performance2.Test06_PullReplication.java
com.couchbase.lite.performance2.Test07_PushReplication.java
com.couchbase.lite.performance2.Test08_DocRevisions.java
com.couchbase.lite.performance2.Test09_LoadDB.java
com.couchbase.lite.performance2.Test10_DeleteDB.java
com.couchbase.lite.performance2.Test11_DeleteDocs.java
com.couchbase.lite.performance2.Test12_IndexView.java
com.couchbase.lite.performance2.Test13_QueryView.java
com.couchbase.lite.performance2.Test14_ReduceView.java
com.couchbase.lite.performance2.Test28_KeySizes.java
com.couchbase.lite.performance2.Test29_AllDocQuery.java
com.couchbase.lite.performance2.Test30_LiveQuery.java
com.couchbase.lite.performance2.Test31_CompactDB.java
com.couchbase.lite.performance.Test10_DeleteDB.java
com.couchbase.lite.performance.Test11_DeleteDocs.java
com.couchbase.lite.performance.Test12_IndexView.java
com.couchbase.lite.performance.Test13_QueryView.java
com.couchbase.lite.performance.Test14_ReduceView.java
com.couchbase.lite.performance.Test16_ParallelPushReplication.java
com.couchbase.lite.performance.Test1_CreateDocs.java
com.couchbase.lite.performance.Test2_CreateDocsUnoptimizedWay.java
com.couchbase.lite.performance.Test3_CreateDocsWithAttachments.java
com.couchbase.lite.performance.Test6_PushReplication.java
com.couchbase.lite.performance.Test7_PullReplication.java
com.couchbase.lite.performance.Test8_DocRevisions.java
com.couchbase.lite.performance.Test9_LoadDB.java
com.couchbase.lite.replicator.BulkDownloaderTest.java
com.couchbase.lite.replicator.ChangeTrackerTest.java
com.couchbase.lite.replicator.CustomizableMockHttpClient.java
com.couchbase.lite.replicator.ReplicationTest.java
com.couchbase.lite.replicator.ResponderChain.java
com.couchbase.lite.support.BatcherTest.java
com.couchbase.lite.support.JsonDocumentTest.java
com.couchbase.lite.support.PersistentCookieStoreTest.java
com.couchbase.lite.support.RemoteRequestTest.java
com.couchbase.touchdb.RevCollator.java
com.couchbase.touchdb.TDCollateJSON.java