private void CreateDocs(uint n, bool verbose = false) { _R = new Random(42); using (var t = new TransactionHelper(_db)) { for (int i = 0; i < n; i++) { var docID = "doc-" + i.ToString(); double lat0 = RandomLatitude(); double lon0 = RandomLongitude(); double lat1 = Math.Min(lat0 + 0.5, 90.0); double lon1 = Math.Min(lon0 + 0.5, 180.0); var body = String.Format("({0}, {1}, {2}, {3})", lon0, lat0, lon1, lat1); var rq = new C4DocPutRequest(); rq.docID = docID; rq.body = body; rq.save = true; C4Error error; var doc = Native.c4doc_put(_db, rq, null, &error); Assert.IsTrue(doc != null); if (verbose) { Console.WriteLine("Added {0} -> {1}", docID, body); } } } }
protected void CreateRev(string docID, string revID, string body, bool isNew = true) { using (var t = new TransactionHelper(_db)) { C4Error error; var doc = Native.c4doc_get(_db, docID, false, &error); Assert.IsTrue(doc != null); var deleted = body == null; Assert.AreEqual(isNew ? 1 : 0, Native.c4doc_insertRevision(doc, revID, body, deleted, false, false, &error)); Assert.IsTrue(Native.c4doc_save(doc, 20, &error)); Native.c4doc_free(doc); } }
public void TestCreateVersionedDoc() { // Try reading doc with mustExist=true, which should fail: C4Error error; var doc = Native.c4doc_get(_db, DOC_ID, true, &error); Assert.IsTrue(doc == null); Assert.AreEqual(C4ErrorDomain.ForestDB, error.domain); Assert.AreEqual(ForestDBStatus.KeyNotFound, (ForestDBStatus)error.code); // Now get the doc with mustExist=false, which returns an empty doc: doc = Native.c4doc_get(_db, DOC_ID, false, &error); Assert.IsTrue(doc != null); Assert.AreEqual((C4DocumentFlags)0, doc->flags); Assert.IsTrue(doc->docID.Equals(DOC_ID)); Assert.IsTrue(doc->revID.buf == null); Assert.IsTrue(doc->selectedRev.revID.buf == null); using (var t = new TransactionHelper(_db)) { Assert.AreEqual(1, Native.c4doc_insertRevision(doc, REV_ID, BODY, false, false, false, &error)); Assert.IsTrue(doc->revID.Equals(REV_ID)); Assert.IsTrue(doc->selectedRev.revID.Equals(REV_ID)); Assert.AreEqual(C4RevisionFlags.RevNew | C4RevisionFlags.RevLeaf, doc->selectedRev.flags); Assert.IsTrue(doc->selectedRev.body.Equals(BODY)); Assert.IsTrue(Native.c4doc_save(doc, 20, &error)); Native.c4doc_free(doc); } // Reload the doc: doc = Native.c4doc_get(_db, DOC_ID, true, &error); Assert.IsTrue(doc != null); Assert.AreEqual(C4DocumentFlags.Exists, doc->flags); Assert.IsTrue(doc->docID.Equals(DOC_ID)); Assert.IsTrue(doc->revID.Equals(REV_ID)); Assert.IsTrue(doc->selectedRev.revID.Equals(REV_ID)); Assert.AreEqual(1UL, doc->selectedRev.sequence); Assert.IsTrue(doc->selectedRev.body.Equals(BODY)); // Get the doc by its sequence: doc = Native.c4doc_getBySequence(_db, 1, &error); Assert.IsTrue(doc != null); Assert.AreEqual(C4DocumentFlags.Exists, doc->flags); Assert.IsTrue(doc->docID.Equals(DOC_ID)); Assert.IsTrue(doc->revID.Equals(REV_ID)); Assert.IsTrue(doc->selectedRev.revID.Equals(REV_ID)); Assert.AreEqual(1UL, doc->selectedRev.sequence); Assert.IsTrue(doc->selectedRev.body.Equals(BODY)); }
public void TestCreateMultipleRevisions() { const string BODY_2 = "{\"ok\":\"go\"}"; CreateRev(DOC_ID, REV_ID, BODY); CreateRev(DOC_ID, REV_2_ID, BODY_2); CreateRev(DOC_ID, REV_2_ID, BODY_2, false); // test redundant insert // Reload the doc: C4Error error; var doc = Native.c4doc_get(_db, DOC_ID, true, &error); Assert.IsTrue(doc != null); Assert.AreEqual(C4DocumentFlags.Exists, doc->flags); Assert.IsTrue(doc->docID.Equals(DOC_ID)); Assert.IsTrue(doc->revID.Equals(REV_2_ID)); Assert.IsTrue(doc->selectedRev.revID.Equals(REV_2_ID)); Assert.AreEqual(2UL, doc->selectedRev.sequence); Assert.IsTrue(doc->selectedRev.body.Equals(BODY_2)); // Select 1st revision: Assert.IsTrue(Native.c4doc_selectParentRevision(doc)); Assert.IsTrue(doc->selectedRev.revID.Equals(REV_ID)); Assert.AreEqual(1UL, doc->selectedRev.sequence); Assert.AreEqual(C4Slice.NULL, doc->selectedRev.body); Assert.IsTrue(Native.c4doc_hasRevisionBody(doc)); Assert.IsTrue(Native.c4doc_loadRevisionBody(doc, &error)); // have to explicitly load the body Assert.IsTrue(doc->selectedRev.body.Equals(BODY)); Assert.IsFalse(Native.c4doc_selectParentRevision(doc)); // Compact database: Assert.IsTrue(Native.c4db_compact(_db, &error)); doc = Native.c4doc_get(_db, DOC_ID, true, &error); Assert.IsTrue(doc != null); Assert.IsTrue(Native.c4doc_selectParentRevision(doc)); Assert.IsTrue(doc->selectedRev.revID.Equals(REV_ID)); Assert.AreEqual(1L, doc->selectedRev.sequence); Assert.IsTrue(doc->selectedRev.body.Equals(C4Slice.NULL)); Assert.IsFalse(Native.c4doc_hasRevisionBody(doc)); Assert.IsFalse(Native.c4doc_loadRevisionBody(doc, &error)); using (var t = new TransactionHelper(_db)) { int nPurged = Native.c4doc_purgeRevision(doc, REV_2_ID, &error); Assert.AreEqual(2, nPurged); Assert.IsTrue(Native.c4doc_save(doc, 20, &error)); } }
public void TestPut() { C4Error error; using (var t = new TransactionHelper(_db)) { C4DocPutRequest rq = new C4DocPutRequest(); rq.docID = DOC_ID; rq.body = BODY; rq.save = true; var doc = Native.c4doc_put(_db, rq, null, &error); Assert.IsTrue(doc != null); Assert.IsTrue(doc->docID.Equals(DOC_ID)); const string expectedRevID = "1-c10c25442d9fe14fa3ca0db4322d7f1e43140fab"; Assert.IsTrue(doc->revID.Equals(expectedRevID)); Assert.AreEqual(C4DocumentFlags.Exists, doc->flags); Assert.IsTrue(doc->selectedRev.revID.Equals(expectedRevID)); Native.c4doc_free(doc); // Update doc: rq.body = "{\"ok\":\"go\"}"; rq.history = new[] { expectedRevID }; ulong commonAncestorIndex; doc = Native.c4doc_put(_db, rq, &commonAncestorIndex, &error); Assert.IsTrue(doc != null); Assert.AreEqual(1UL, commonAncestorIndex); const string expectedRev2ID = "2-32c711b29ea3297e27f3c28c8b066a68e1bb3f7b"; Assert.IsTrue(doc->revID.Equals(expectedRev2ID)); Assert.AreEqual(C4DocumentFlags.Exists, doc->flags); Assert.IsTrue(doc->selectedRev.revID.Equals(expectedRev2ID)); Native.c4doc_free(doc); // Insert existing rev: rq.body = "{\"from\":\"elsewhere\"}"; rq.existingRevision = true; rq.history = new[] { REV_2_ID, expectedRevID }; doc = Native.c4doc_put(_db, rq, &commonAncestorIndex, &error); Assert.IsTrue(doc != null); Assert.AreEqual(1UL, commonAncestorIndex); Assert.IsTrue(doc->revID.Equals(REV_2_ID)); Assert.AreEqual(C4DocumentFlags.Exists | C4DocumentFlags.Conflicted, doc->flags); Assert.IsTrue(doc->selectedRev.revID.Equals(REV_2_ID)); Native.c4doc_free(doc); } }
public void TestInsertRevisionWithHistory() { const string BODY_2 = @"{""ok"":""go""}"; CreateRev(DOC_ID, REV_ID, BODY); CreateRev(DOC_ID, REV_2_ID, BODY_2); // Reload the doc: C4Error error; var doc = Native.c4doc_get(_db, DOC_ID, true, &error); // Add 18 revisions; the last two entries in the history repeat the two existing revs: const int historyCount = 20; var revIDs = new List <string>(historyCount); var rand = new Random(); for (uint i = historyCount - 1; i >= 2; i--) { revIDs.Add(String.Format("{0}-{1:x8}", i + 1, rand.Next())); } revIDs.Add(REV_2_ID); revIDs.Add(REV_ID); int n; using (var t = new TransactionHelper(_db)) { n = Native.c4doc_insertRevisionWithHistory(doc, @"{""foo"":true}", false, false, revIDs.ToArray(), &error); } if (n < 0) { Console.Error.WriteLine(String.Format("Error({0})", error)); } Assert.AreEqual(historyCount - 2, n); }
public void TestCreateVersionedDoc() { // Try reading doc with mustExist=true, which should fail: C4Error error; var doc = Native.c4doc_get(_db, DOC_ID, true, &error); Assert.IsTrue(doc == null); Assert.AreEqual(C4ErrorDomain.ForestDB, error.domain); Assert.AreEqual(ForestDBStatus.KeyNotFound, (ForestDBStatus)error.code); // Now get the doc with mustExist=false, which returns an empty doc: doc = Native.c4doc_get(_db, DOC_ID, false, &error); Assert.IsTrue(doc != null); Assert.AreEqual((C4DocumentFlags)0, doc->flags); Assert.IsTrue(doc->docID.Equals(DOC_ID)); Assert.IsTrue(doc->revID.buf == null); Assert.IsTrue(doc->selectedRev.revID.buf == null); using(var t = new TransactionHelper(_db)) { Assert.AreEqual(1, Native.c4doc_insertRevision(doc, REV_ID, BODY, false, false, false, &error)); Assert.IsTrue(doc->revID.Equals(REV_ID)); Assert.IsTrue(doc->selectedRev.revID.Equals(REV_ID)); Assert.AreEqual(C4RevisionFlags.RevNew | C4RevisionFlags.RevLeaf, doc->selectedRev.flags); Assert.IsTrue(doc->selectedRev.body.Equals(BODY)); Assert.IsTrue(Native.c4doc_save(doc, 20, &error)); Native.c4doc_free(doc); } // Reload the doc: doc = Native.c4doc_get(_db, DOC_ID, true, &error); Assert.IsTrue(doc != null); Assert.AreEqual(C4DocumentFlags.Exists, doc->flags); Assert.IsTrue(doc->docID.Equals(DOC_ID)); Assert.IsTrue(doc->revID.Equals(REV_ID)); Assert.IsTrue(doc->selectedRev.revID.Equals(REV_ID)); Assert.AreEqual(1UL, doc->selectedRev.sequence); Assert.IsTrue(doc->selectedRev.body.Equals(BODY)); // Get the doc by its sequence: doc = Native.c4doc_getBySequence(_db, 1, &error); Assert.IsTrue(doc != null); Assert.AreEqual(C4DocumentFlags.Exists, doc->flags); Assert.IsTrue(doc->docID.Equals(DOC_ID)); Assert.IsTrue(doc->revID.Equals(REV_ID)); Assert.IsTrue(doc->selectedRev.revID.Equals(REV_ID)); Assert.AreEqual(1UL, doc->selectedRev.sequence); Assert.IsTrue(doc->selectedRev.body.Equals(BODY)); }
public void TestInsertRevisionWithHistory() { const string BODY_2 = @"{""ok"":""go""}"; CreateRev(DOC_ID, REV_ID, BODY); CreateRev(DOC_ID, REV_2_ID, BODY_2); // Reload the doc: C4Error error; var doc = Native.c4doc_get(_db, DOC_ID, true, &error); // Add 18 revisions; the last two entries in the history repeat the two existing revs: const int historyCount = 20; var revIDs = new List<string>(historyCount); var rand = new Random(); for(uint i = historyCount - 1; i >= 2; i--) { revIDs.Add(String.Format("{0}-{1:x8}", i+1, rand.Next())); } revIDs.Add(REV_2_ID); revIDs.Add(REV_ID); int n; using(var t = new TransactionHelper(_db)) { n = Native.c4doc_insertRevisionWithHistory(doc, @"{""foo"":true}", false, false, revIDs.ToArray(), &error); } if(n < 0) { Console.Error.WriteLine(String.Format("Error({0})", error)); } Assert.AreEqual(historyCount - 2, n); }
public void TestCreateMultipleRevisions() { const string BODY_2 = "{\"ok\":\"go\"}"; CreateRev(DOC_ID, REV_ID, BODY); CreateRev(DOC_ID, REV_2_ID, BODY_2); CreateRev(DOC_ID, REV_2_ID, BODY_2, false); // test redundant insert // Reload the doc: C4Error error; var doc = Native.c4doc_get(_db, DOC_ID, true, &error); Assert.IsTrue(doc != null); Assert.AreEqual(C4DocumentFlags.Exists, doc->flags); Assert.IsTrue(doc->docID.Equals(DOC_ID)); Assert.IsTrue(doc->revID.Equals(REV_2_ID)); Assert.IsTrue(doc->selectedRev.revID.Equals(REV_2_ID)); Assert.AreEqual(2UL, doc->selectedRev.sequence); Assert.IsTrue(doc->selectedRev.body.Equals(BODY_2)); // Select 1st revision: Assert.IsTrue(Native.c4doc_selectParentRevision(doc)); Assert.IsTrue(doc->selectedRev.revID.Equals(REV_ID)); Assert.AreEqual(1UL, doc->selectedRev.sequence); Assert.AreEqual(C4Slice.NULL, doc->selectedRev.body); Assert.IsTrue(Native.c4doc_hasRevisionBody(doc)); Assert.IsTrue(Native.c4doc_loadRevisionBody(doc, &error)); // have to explicitly load the body Assert.IsTrue(doc->selectedRev.body.Equals(BODY)); Assert.IsFalse(Native.c4doc_selectParentRevision(doc)); // Compact database: Assert.IsTrue(Native.c4db_compact(_db, &error)); doc = Native.c4doc_get(_db, DOC_ID, true, &error); Assert.IsTrue(doc != null); Assert.IsTrue(Native.c4doc_selectParentRevision(doc)); Assert.IsTrue(doc->selectedRev.revID.Equals(REV_ID)); Assert.AreEqual(1L, doc->selectedRev.sequence); Assert.IsTrue(doc->selectedRev.body.Equals(C4Slice.NULL)); Assert.IsFalse(Native.c4doc_hasRevisionBody(doc)); Assert.IsFalse(Native.c4doc_loadRevisionBody(doc, &error)); using(var t = new TransactionHelper(_db)) { int nPurged = Native.c4doc_purgeRevision(doc, REV_2_ID, &error); Assert.AreEqual(2, nPurged); Assert.IsTrue(Native.c4doc_save(doc, 20, &error)); } }
protected void CreateRev(string docID, string revID, string body, bool isNew = true) { using(var t = new TransactionHelper(_db)) { C4Error error; var doc = Native.c4doc_get(_db, docID, false, &error); Assert.IsTrue(doc != null); var deleted = body == null; Assert.AreEqual(isNew ? 1 : 0, Native.c4doc_insertRevision(doc, revID, body, deleted, false, false, &error)); Assert.IsTrue(Native.c4doc_save(doc, 20, &error)); Native.c4doc_free(doc); } }