Back to project page couchbase-lite-android.
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.
package com.couchbase.lite; //from ww w . j a v a 2s .co m import com.couchbase.lite.internal.RevisionInternal; import com.couchbase.lite.util.Log; import junit.framework.Assert; import java.util.ArrayList; import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Observable; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; public class RevisionsTest extends LiteTestCase { public void testParseRevID() { int num; String suffix; num = Database.parseRevIDNumber("1-utiopturoewpt"); Assert.assertEquals(1, num); suffix = Database.parseRevIDSuffix("1-utiopturoewpt"); Assert.assertEquals("utiopturoewpt", suffix); num = Database.parseRevIDNumber("321-fdjfdsj-e"); Assert.assertEquals(321, num); suffix = Database.parseRevIDSuffix("321-fdjfdsj-e"); Assert.assertEquals("fdjfdsj-e", suffix); num = Database.parseRevIDNumber("0-fdjfdsj-e"); suffix = Database.parseRevIDSuffix("0-fdjfdsj-e"); Assert.assertTrue(num == 0 || (suffix.length() == 0)); num = Database.parseRevIDNumber("-4-fdjfdsj-e"); suffix = Database.parseRevIDSuffix("-4-fdjfdsj-e"); Assert.assertTrue(num < 0 || (suffix.length() == 0)); num = Database.parseRevIDNumber("5_fdjfdsj-e"); suffix = Database.parseRevIDSuffix("5_fdjfdsj-e"); Assert.assertTrue(num < 0 || (suffix.length() == 0)); num = Database.parseRevIDNumber(" 5-fdjfdsj-e"); suffix = Database.parseRevIDSuffix(" 5-fdjfdsj-e"); Assert.assertTrue(num < 0 || (suffix.length() == 0)); num = Database.parseRevIDNumber("7 -foo"); suffix = Database.parseRevIDSuffix("7 -foo"); Assert.assertTrue(num < 0 || (suffix.length() == 0)); num = Database.parseRevIDNumber("7-"); suffix = Database.parseRevIDSuffix("7-"); Assert.assertTrue(num < 0 || (suffix.length() == 0)); num = Database.parseRevIDNumber("7"); suffix = Database.parseRevIDSuffix("7"); Assert.assertTrue(num < 0 || (suffix.length() == 0)); num = Database.parseRevIDNumber("eiuwtiu"); suffix = Database.parseRevIDSuffix("eiuwtiu"); Assert.assertTrue(num < 0 || (suffix.length() == 0)); num = Database.parseRevIDNumber(""); suffix = Database.parseRevIDSuffix(""); Assert.assertTrue(num < 0 || (suffix.length() == 0)); } public void testCBLCompareRevIDs() { // Single Digit Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("1-foo", "1-foo") == 0); Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("2-bar", "1-foo") > 0); Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("1-foo", "2-bar") < 0); // Multi-digit: Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("123-bar", "456-foo") < 0); Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("456-foo", "123-bar") > 0); Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("456-foo", "456-foo") == 0); Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("456-foo", "456-foofoo") < 0); // Different numbers of digits: Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("89-foo", "123-bar") < 0); Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("123-bar", "89-foo") > 0); // Edge cases: Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("123-", "89-") > 0); Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("123-a", "123-a") == 0); // Invalid rev IDs: Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("-a", "-b") < 0); Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("-", "-") == 0); Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("", "") == 0); Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("", "-b") < 0); Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("bogus", "yo") < 0); Assert.assertTrue(RevisionInternal.CBLCollateRevIDs("bogus-x", "yo-y") < 0); } public void testMakeRevisionHistoryDict() { List<RevisionInternal> revs = new ArrayList<RevisionInternal>(); revs.add(mkrev("4-jkl")); revs.add(mkrev("3-ghi")); revs.add(mkrev("2-def")); List<String> expectedSuffixes = new ArrayList<String>(); expectedSuffixes.add("jkl"); expectedSuffixes.add("ghi"); expectedSuffixes.add("def"); Map<String,Object> expectedHistoryDict = new HashMap<String,Object>(); expectedHistoryDict.put("start", 4); expectedHistoryDict.put("ids", expectedSuffixes); Map<String,Object> historyDict = Database.makeRevisionHistoryDict(revs); Assert.assertEquals(expectedHistoryDict, historyDict); revs = new ArrayList<RevisionInternal>(); revs.add(mkrev("4-jkl")); revs.add(mkrev("2-def")); expectedSuffixes = new ArrayList<String>(); expectedSuffixes.add("4-jkl"); expectedSuffixes.add("2-def"); expectedHistoryDict = new HashMap<String,Object>(); expectedHistoryDict.put("ids", expectedSuffixes); historyDict = Database.makeRevisionHistoryDict(revs); Assert.assertEquals(expectedHistoryDict, historyDict); revs = new ArrayList<RevisionInternal>(); revs.add(mkrev("12345")); revs.add(mkrev("6789")); expectedSuffixes = new ArrayList<String>(); expectedSuffixes.add("12345"); expectedSuffixes.add("6789"); expectedHistoryDict = new HashMap<String,Object>(); expectedHistoryDict.put("ids", expectedSuffixes); historyDict = Database.makeRevisionHistoryDict(revs); Assert.assertEquals(expectedHistoryDict, historyDict); } /** * https://github.com/couchbase/couchbase-lite-java-core/issues/164 */ public void testRevisionIdDifferentRevisions() throws Exception { // two revisions with different json should have different rev-id's // because their content will have a different hash (even though // they have the same generation number) Map<String, Object> properties = new HashMap<String, Object>(); properties.put("testName", "testCreateRevisions"); properties.put("tag", 1337); Document doc = database.createDocument(); UnsavedRevision newRev = doc.createRevision(); newRev.setUserProperties(properties); SavedRevision rev1 = newRev.save(); SavedRevision rev2a = createRevisionWithRandomProps(rev1, false); SavedRevision rev2b = createRevisionWithRandomProps(rev1, true); assertNotSame(rev2a.getId(), rev2b.getId()); } /** * https://github.com/couchbase/couchbase-lite-java-core/issues/164 */ public void testRevisionIdEquivalentRevisions() throws Exception { // two revisions with the same content and the same json // should have the exact same revision id, because their content // will have an identical hash Map<String, Object> properties = new HashMap<String, Object>(); properties.put("testName", "testCreateRevisions"); properties.put("tag", 1337); Map<String, Object> properties2 = new HashMap<String, Object>(); properties2.put("testName", "testCreateRevisions"); properties2.put("tag", 1338); Document doc = database.createDocument(); UnsavedRevision newRev = doc.createRevision(); newRev.setUserProperties(properties); SavedRevision rev1 = newRev.save(); UnsavedRevision newRev2a = rev1.createRevision(); newRev2a.setUserProperties(properties2); SavedRevision rev2a = newRev2a.save(); UnsavedRevision newRev2b = rev1.createRevision(); newRev2b.setUserProperties(properties2); SavedRevision rev2b = newRev2b.save(true); assertEquals(rev2a.getId(), rev2b.getId()); } /** * https://github.com/couchbase/couchbase-lite-java-core/issues/106 */ public void testResolveConflict() throws Exception { Map<String, Object> properties = new HashMap<String, Object>(); properties.put("testName", "testCreateRevisions"); properties.put("tag", 1337); // Create a conflict on purpose Document doc = database.createDocument(); UnsavedRevision newRev1 = doc.createRevision(); newRev1.setUserProperties(properties); SavedRevision rev1 = newRev1.save(); SavedRevision rev2a = createRevisionWithRandomProps(rev1, false); SavedRevision rev2b = createRevisionWithRandomProps(rev1, true); SavedRevision winningRev = null; SavedRevision losingRev = null; if (doc.getCurrentRevisionId().equals(rev2a.getId())) { winningRev = rev2a; losingRev = rev2b; } else { winningRev = rev2b; losingRev = rev2a; } assertEquals(2,doc.getConflictingRevisions().size()); assertEquals(2, doc.getLeafRevisions().size()); // let's manually choose the losing rev as the winner. First, delete winner, which will // cause losing rev to be the current revision. SavedRevision deleteRevision = winningRev.deleteDocument(); List<SavedRevision> conflictingRevisions = doc.getConflictingRevisions(); assertEquals(1, conflictingRevisions.size()); assertEquals(2, doc.getLeafRevisions().size()); assertEquals(3, deleteRevision.getGeneration()); assertEquals(losingRev.getId(), doc.getCurrentRevision().getId()); // Finally create a new revision rev3 based on losing rev SavedRevision rev3 = createRevisionWithRandomProps(losingRev, true); assertEquals(rev3.getId(), doc.getCurrentRevisionId()); List<SavedRevision> conflictingRevisions1 = doc.getConflictingRevisions(); assertEquals(1, conflictingRevisions1.size()); assertEquals(2, doc.getLeafRevisions().size()); } public void testCorrectWinningRevisionTiebreaker() throws Exception { // Create a conflict on purpose Document doc = database.createDocument(); SavedRevision rev1 = doc.createRevision().save(); SavedRevision rev2a = createRevisionWithRandomProps(rev1, false); SavedRevision rev2b = createRevisionWithRandomProps(rev1, true); // the tiebreaker will happen based on which rev hash has lexicographically higher sort order SavedRevision expectedWinner = null; if (rev2a.getId().compareTo(rev2b.getId()) > 0) { expectedWinner = rev2a; } else if (rev2a.getId().compareTo(rev2b.getId()) < 0) { expectedWinner = rev2b; } RevisionInternal revFound = database.getDocumentWithIDAndRev(doc.getId(), null, EnumSet.noneOf(Database.TDContentOptions.class)); assertEquals(expectedWinner.getId(), revFound.getRevId()); } public void testCorrectWinningRevisionLongerBranch() throws Exception { // Create a conflict on purpose Document doc = database.createDocument(); SavedRevision rev1 = doc.createRevision().save(); SavedRevision rev2a = createRevisionWithRandomProps(rev1, false); SavedRevision rev2b = createRevisionWithRandomProps(rev1, true); SavedRevision rev3b = createRevisionWithRandomProps(rev2b, true); // rev3b should be picked as the winner since it has a longer branch SavedRevision expectedWinner = rev3b; RevisionInternal revFound = database.getDocumentWithIDAndRev(doc.getId(), null, EnumSet.noneOf(Database.TDContentOptions.class)); assertEquals(expectedWinner.getId(), revFound.getRevId()); } /** * https://github.com/couchbase/couchbase-lite-java-core/issues/135 */ public void testCorrectWinningRevisionHighRevisionNumber() throws Exception { // Create a conflict on purpose Document doc = database.createDocument(); SavedRevision rev1 = doc.createRevision().save(); SavedRevision rev2a = createRevisionWithRandomProps(rev1, false); SavedRevision rev2b = createRevisionWithRandomProps(rev1, true); SavedRevision rev3b = createRevisionWithRandomProps(rev2b, true); SavedRevision rev4b = createRevisionWithRandomProps(rev3b, true); SavedRevision rev5b = createRevisionWithRandomProps(rev4b, true); SavedRevision rev6b = createRevisionWithRandomProps(rev5b, true); SavedRevision rev7b = createRevisionWithRandomProps(rev6b, true); SavedRevision rev8b = createRevisionWithRandomProps(rev7b, true); SavedRevision rev9b = createRevisionWithRandomProps(rev8b, true); SavedRevision rev10b = createRevisionWithRandomProps(rev9b, true); RevisionInternal revFound = database.getDocumentWithIDAndRev(doc.getId(), null, EnumSet.noneOf(Database.TDContentOptions.class)); assertEquals(rev10b.getId(), revFound.getRevId()); } public void testDocumentChangeListener() throws Exception { Document doc = database.createDocument(); final CountDownLatch documentChanged = new CountDownLatch(1); doc.addChangeListener(new Document.ChangeListener() { @Override public void changed(Document.ChangeEvent event) { DocumentChange docChange = event.getChange(); String msg = "New revision added: %s. Conflict: %s"; msg = String.format(msg, docChange.getAddedRevision(), docChange.isConflict()); Log.d(TAG, msg); documentChanged.countDown(); } }); doc.createRevision().save(); boolean success = documentChanged.await(30, TimeUnit.SECONDS); assertTrue(success); } private static RevisionInternal mkrev(String revID) { return new RevisionInternal("docid", revID, false, null); } }