void deleteMark(MojUInt32 expect = 50ul, int mark = -1, MojDbReqRef req = MojDbReq()) { MojDbQuery query; MojAssertNoErr( query.from(_T("Test:1")) ); MojAssertNoErr( query.where(_T("bar"), MojDbQuery::OpEq, mark) ); MojUInt32 count = 0xbaddcafe; MojAssertNoErr( db.del(query, count, MojDb::FlagNone, req) ); EXPECT_EQ( expect, count ); }
MojErr MojDbPerfCreateTest::testBatchInsertLgArrayObj(MojDb& db, const MojChar* kindId) { // register all the kinds again MojTime time; MojErr err = putKinds(db, time); MojTestErrCheck(err); // time put with large array objects (20 properties + 2 arrays of 5 elements each) MojTime batchLgArrayObjTime = 0; for (int i = 0; i < numRepetitions; i++) { err = putLargeArrayObj(db, kindId, batchLgArrayObjTime); MojTestErrCheck(err); MojDbQuery q; err = q.from(kindId); MojTestErrCheck(err); MojUInt32 count = 0; err = db.del(q, count); MojTestErrCheck(err); } MojUInt64 putTime = batchLgArrayObjTime.microsecs(); err = MojPrintF("\n -------------------- \n"); MojTestErrCheck(err); err = MojPrintF(" time to batch put %llu %s objects %d times: %llu microsecs\n", numInsert, kindId, numRepetitions, putTime); MojTestErrCheck(err); err = MojPrintF(" time per batch: %llu microsecs", (putTime) / (numRepetitions)); MojTestErrCheck(err); err = MojPrintF(" time per object: %llu microsecs", (putTime) / (numInsert * numRepetitions)); MojTestErrCheck(err); err = MojPrintF("\n\n"); MojTestErrCheck(err); MojString buf; err = buf.format("batch put %llu objects %d times,%s,%llu,%llu,%llu,\n", numInsert, numRepetitions, kindId, putTime, putTime/numRepetitions, putTime / (numInsert * numRepetitions)); MojTestErrCheck(err); err = fileWrite(file, buf); MojTestErrCheck(err); return MojErrNone; }
MojErr MojDbPerfCreateTest::testInsertMedArrayObj(MojDb& db, const MojChar* kindId) { // register all the kinds again MojTime time; MojErr err = putKinds(db, time); MojTestErrCheck(err); // time put with med array objects (10 properties + 1 array of 5 elements) MojTime medArrayObjTime; for (int i = 0; i < numRepetitions; i++) { err = putMedArrayObj(db, kindId, medArrayObjTime); MojTestErrCheck(err); MojDbQuery q; err = q.from(kindId); MojTestErrCheck(err); MojUInt32 count = 0; err = db.del(q, count, MojDb::FlagPurge); MojTestErrCheck(err); } MojUInt64 putTime = medArrayObjTime.microsecs(); err = MojPrintF("\n -------------------- \n"); MojTestErrCheck(err); err = MojPrintF(" time to put %llu %s objects %d times: %llu microsecs\n", numInsert, kindId, numRepetitions, putTime); MojTestErrCheck(err); err = MojPrintF(" time per object: %llu microsecs", (putTime) / (numInsert * numRepetitions)); MojTestErrCheck(err); err = MojPrintF("\n\n"); MojTestErrCheck(err); MojString buf; err = buf.format("put %llu objects %d times,%s,%llu,%llu,%llu,\n", numInsert, numRepetitions, kindId, putTime, putTime/numRepetitions, putTime / (numInsert * numRepetitions)); MojTestErrCheck(err); err = fileWrite(file, buf); MojTestErrCheck(err); return MojErrNone; }
MojErr MojDbPerfCreateTest::testInsertLgNestedObj(MojDb& db, const MojChar* kindId) { // register all the kinds again MojUInt64 time = 0; MojErr err = putKinds(db, time); MojTestErrCheck(err); // time put with large nested objects (3 levels of nesting, 20 properties) MojUInt64 largeNestedObjTime = 0; for (int i = 0; i < numRepetitions; i++) { err = putLargeNestedObj(db, kindId, largeNestedObjTime); MojTestErrCheck(err); MojDbQuery q; err = q.from(kindId); MojTestErrCheck(err); MojUInt32 count = 0; err = db.del(q, count, MojDb::FlagPurge); MojTestErrCheck(err); } err = MojPrintF("\n -------------------- \n"); MojTestErrCheck(err); err = MojPrintF(" time to put %llu %s nested objects %d times: %llu nanosecs\n", numInsert, kindId, numRepetitions, largeNestedObjTime); MojTestErrCheck(err); err = MojPrintF(" time per object: %llu nanosecs", (largeNestedObjTime) / (numInsert * numRepetitions)); MojTestErrCheck(err); err = MojPrintF("\n\n"); MojTestErrCheck(err); MojString buf; err = buf.format("put %llu objects %d times,%s,%llu,%llu,%llu,\n", numInsert, numRepetitions, kindId, largeNestedObjTime, largeNestedObjTime/numRepetitions, largeNestedObjTime / (numInsert * numRepetitions)); MojTestErrCheck(err); err = fileWrite(file, buf); MojTestErrCheck(err); return MojErrNone; }
MojErr MojDbWatchTest::eqTest(MojDb& db) { MojDbQuery query; MojErr err = query.from(_T("WatchTest:1")); MojTestErrCheck(err); err = query.where(_T("foo"), MojDbQuery::OpEq, 1); MojTestErrCheck(err); MojRefCountedPtr<TestWatcher> watcher(new TestWatcher); MojTestAssert(watcher.get()); MojDbCursor cursor; err = db.find(query, cursor, watcher->m_slot); MojTestErrCheck(err); err = cursor.close(); MojTestErrCheck(err); MojTestAssert(watcher->m_count == 0); MojRefCountedPtr<TestWatcher> watcher2(new TestWatcher); MojTestAssert(watcher2.get()); bool fired = false; err = db.watch(query, cursor, watcher2->m_slot, fired); MojTestErrCheck(err); err = cursor.close(); MojTestErrCheck(err); MojTestAssert(!fired); // puts MojObject id; err = put(db, 0, 0, id, m_rev); MojTestErrCheck(err); MojTestAssert(watcher->m_count == 0); MojTestAssert(watcher2->m_count == 0); err = put(db, 2, 2, id, m_rev); MojTestErrCheck(err); MojTestAssert(watcher->m_count == 0); MojTestAssert(watcher2->m_count == 0); err = put(db, 1, 1, id, m_rev); MojTestErrCheck(err); MojTestAssert(watcher->m_count == 1); MojTestAssert(watcher2->m_count == 1); err = put(db, 1, 1, id, m_rev); MojTestErrCheck(err); MojTestAssert(watcher->m_count == 1); MojTestAssert(watcher2->m_count == 1); // put, changing property not in index watcher.reset(new TestWatcher); MojTestAssert(watcher.get()); err = db.find(query, cursor, watcher->m_slot); MojTestErrCheck(err); err = cursor.close(); MojTestErrCheck(err); err = put(db, 1, 2, id, m_rev); MojTestErrCheck(err); MojTestAssert(watcher->m_count == 1); // dels watcher.reset(new TestWatcher); MojTestAssert(watcher.get()); err = db.find(query, cursor, watcher->m_slot); MojTestErrCheck(err); err = cursor.close(); MojTestErrCheck(err); watcher2.reset(new TestWatcher); MojTestAssert(watcher2.get()); MojDbQuery queryWithRev; err = queryWithRev.from(_T("WatchTest:1")); MojTestErrCheck(err); err = queryWithRev.where(_T("foo"), MojDbQuery::OpEq, 1); MojTestErrCheck(err); err = queryWithRev.where(_T("_rev"), MojDbQuery::OpGreaterThan, m_rev); MojTestErrCheck(err); err = queryWithRev.includeDeleted(); MojTestErrCheck(err); fired = false; err = db.watch(queryWithRev, cursor, watcher2->m_slot, fired); MojTestErrCheck(err); err = cursor.close(); MojTestErrCheck(err); MojTestAssert(!fired); MojTestAssert(watcher->m_count == 0); MojTestAssert(watcher2->m_count == 0); bool found; err = db.del(id, found); MojTestErrCheck(err); MojTestAssert(found); MojTestAssert(watcher->m_count == 1); MojTestAssert(watcher2->m_count == 1); // ordering watcher.reset(new TestWatcher); MojTestAssert(watcher.get()); err = db.find(query, cursor, watcher->m_slot); MojTestErrCheck(err); err = put(db, 1, 1, id, m_rev); MojTestErrCheck(err); MojTestAssert(watcher->m_count == 0); err = cursor.close(); MojTestErrCheck(err); MojTestAssert(watcher->m_count == 1); return MojErrNone; }
MojErr MojDbWatchTest::pageTest(MojDb& db) { MojObject id; MojObject idFirst; MojObject idFourth; MojObject idLast; MojInt64 rev; for (int i = 100; i < 150; ++i) { MojErr err = put(db, 100, i, id, rev); MojTestErrCheck(err); if (i == 100) { idFirst = id; } else if (i == 103) { idFourth = id; } else if (i == 149) { idLast = id; } } MojDbQuery query; MojErr err = query.from(_T("WatchTest:1")); MojTestErrCheck(err); err = query.where(_T("foo"), MojDbQuery::OpGreaterThanEq, 100); MojTestErrCheck(err); query.limit(3); MojRefCountedPtr<TestWatcher> watcher(new TestWatcher); MojTestAssert(watcher.get()); MojDbCursor cursor; err = db.find(query, cursor, watcher->m_slot); MojTestErrCheck(err); bool found = false; MojUInt32 count = 0; do { MojObject obj; err = cursor.get(obj, found); MojTestErrCheck(err); if (found) ++count; } while (found); MojTestAssert(count == 3); MojDbQuery::Page page; err = cursor.nextPage(page); MojTestErrCheck(err); err = cursor.close(); MojTestErrCheck(err); err = merge(db, idFourth, 53); MojTestErrCheck(err); MojTestAssert(watcher->m_count == 0); query.page(page); MojRefCountedPtr<TestWatcher> watcher2(new TestWatcher); MojTestAssert(watcher2.get()); err = db.find(query, cursor, watcher2->m_slot); MojTestErrCheck(err); found = false; count = 0; do { MojObject obj; err = cursor.get(obj, found); MojTestErrCheck(err); if (found) ++count; } while (found); MojTestAssert(count == 3); err = cursor.close(); MojTestErrCheck(err); err = db.del(idFirst, found); MojTestErrCheck(err); MojTestAssert(found); MojTestAssert(watcher->m_count == 1); MojTestAssert(watcher2->m_count == 0); err = db.del(idFourth, found); MojTestErrCheck(err); MojTestAssert(found); MojTestAssert(watcher->m_count == 1); MojTestAssert(watcher2->m_count == 1); // desc order query.page(MojDbQuery::Page()); query.desc(true); MojRefCountedPtr<TestWatcher> watcher3(new TestWatcher); MojTestAssert(watcher3.get()); err = db.find(query, cursor, watcher3->m_slot); MojTestErrCheck(err); found = false; count = 0; do { MojObject obj; err = cursor.get(obj, found); MojTestErrCheck(err); if (found) ++count; } while (found); MojTestAssert(count == 3); err = cursor.close(); MojTestErrCheck(err); err = merge(db, idLast, 53); MojTestErrCheck(err); MojTestAssert(watcher3->m_count == 1); MojRefCountedPtr<TestWatcher> watcher4(new TestWatcher); MojTestAssert(watcher4.get()); err = db.find(query, cursor, watcher4->m_slot); MojTestErrCheck(err); found = false; count = 0; do { MojObject obj; err = cursor.get(obj, found); MojTestErrCheck(err); if (found) ++count; } while (found); MojTestAssert(count == 3); err = cursor.close(); MojTestErrCheck(err); err = merge(db, idLast, 54); MojTestErrCheck(err); MojTestAssert(watcher4->m_count == 1); return MojErrNone; }
MojErr MojDbPermissionTest::checkPermissions(MojDb& db) { MojDbReq reqOwner(false); MojErr err = reqOwner.domain(_T("com.foo")); MojTestErrCheck(err); MojDbReq reqFooBar(false); err = reqFooBar.domain(_T("com.foo.bar")); MojTestErrCheck(err); MojDbReq reqFooBarBad(false); err = reqFooBarBad.domain(_T("com.foobar")); MojTestErrCheck(err); MojDbReq reqGranted(false); err = reqGranted.domain("com.granted"); MojTestErrCheck(err); MojDbReq reqEmpty(false); MojDbReq reqBad(false); err = reqBad.domain("com.bad"); MojTestErrCheck(err); MojObject objNoId; err = objNoId.putString(MojDb::KindKey, _T("PermissionTest:1")); MojTestErrCheck(err); MojObject obj2NoId; err = obj2NoId.putString(MojDb::KindKey, _T("PermissionTest2:1")); MojTestErrCheck(err); // put new obj MojObject obj1 = objNoId; err = db.put(obj1, MojDb::FlagNone, reqOwner); MojTestErrCheck(err); MojObject obj2 = objNoId; err = db.put(obj2, MojDb::FlagNone, reqGranted); MojTestErrCheck(err); MojObject obj3 = objNoId; err = db.put(obj3, MojDb::FlagNone, reqBad); MojTestErrExpected(err, MojErrDbPermissionDenied); obj3 = objNoId; err = db.put(obj3, MojDb::FlagNone, reqFooBarBad); MojTestErrExpected(err, MojErrDbPermissionDenied); obj3 = objNoId; err = db.put(obj3, MojDb::FlagNone, reqFooBar); MojTestErrCheck(err); err = db.put(obj2NoId, MojDb::FlagNone, reqEmpty); MojTestErrCheck(err); // put existing obj err = obj1.put(_T("foo"), 1); MojTestErrCheck(err); err = db.put(obj1, MojDb::FlagNone, reqOwner); MojTestErrCheck(err); err = obj2.put(_T("foo"), 2); MojTestErrCheck(err); err = db.put(obj2, MojDb::FlagNone, reqGranted); MojTestErrCheck(err); err = obj2.put(_T("foo"), 3); MojTestErrCheck(err); err = db.put(obj2, MojDb::FlagNone, reqBad); MojTestErrExpected(err, MojErrDbPermissionDenied); // find MojDbQuery query; err = query.from(_T("PermissionTest:1")); MojTestErrCheck(err); MojDbCursor cursor; err = db.find(query, cursor, reqOwner); MojTestErrCheck(err); err = cursor.close(); MojTestErrCheck(err); err = db.find(query, cursor, reqGranted); MojTestErrCheck(err); err = cursor.close(); MojTestErrCheck(err); err = db.find(query, cursor, reqBad); MojTestErrExpected(err, MojErrDbPermissionDenied); err = cursor.close(); MojTestErrCheck(err); // get MojObject id1; MojTestAssert(obj1.get(MojDb::IdKey, id1)); bool found = false; MojObject gotten; err = db.get(id1, gotten, found, reqOwner); MojTestErrCheck(err); err = db.get(id1, gotten, found, reqGranted); MojTestErrCheck(err); err = db.get(id1, gotten, found, reqBad); MojTestErrExpected(err, MojErrDbPermissionDenied); // del by id err = db.del(id1, found, MojDb::FlagNone, reqBad); MojTestErrExpected(err, MojErrDbPermissionDenied); MojTestAssert(!found); err = db.del(id1, found, MojDb::FlagNone, reqOwner); MojTestErrCheck(err); MojTestAssert(found); MojObject id2; MojTestAssert(obj2.get(MojDb::IdKey, id2)); err = db.del(id2, found, MojDb::FlagNone, reqGranted); MojTestErrCheck(err); MojTestAssert(found); // del query MojUInt32 count = 0; err = db.del(query, count, MojDb::FlagNone, reqOwner); MojTestErrCheck(err); err = db.del(query, count, MojDb::FlagNone, reqGranted); MojTestErrCheck(err); err = db.del(query, count, MojDb::FlagNone, reqBad); MojTestErrExpected(err, MojErrDbPermissionDenied); return MojErrNone; }
MojErr MojDbPurgeTest::run() { MojDb db; MojErr err = db.open(MojDbTestDir); MojTestErrCheck(err); // put type MojObject obj; err = obj.fromJson(MojKindStr); MojTestErrCheck(err); err = db.putKind(obj); MojTestErrCheck(err); MojObject revNums[10]; MojObject ids[10]; //put 10 objects in the db for(int i = 0; i < 10; i++) { err = obj.fromJson(MojTestObjStr1); MojTestErrCheck(err); err = db.put(obj); MojTestErrCheck(err); // get _rev and id MojObject rev; err = obj.getRequired(MojDb::RevKey, rev); MojTestErrCheck(err); revNums[i] = rev; MojObject id; err = obj.getRequired(MojDb::IdKey, id); MojTestErrCheck(err); ids[i] = id; } //purge now, there are no RevTimestamp entries MojUInt32 count = 0; err = db.purge(count, 30); MojTestErrCheck(err); err = checkObjectsPurged(db, count, 0, 10, 1, -1); MojTestErrCheck(err); //create a RevTimestamp entry - that's not more than PurgeNumDays days ago MojTime time; err = MojGetCurrentTime(time); MojTestErrCheck(err); err = createRevTimestamp(db, revNums[0], time.microsecs()); MojTestErrCheck(err); //purge now, there are no RevTimestamp entries that are more than //PurgeNumDays ago, so nothing should be purged count = 0; err = db.purge(count, 30); MojTestErrCheck(err); err = checkObjectsPurged(db, count, 0, 10, 3, -1); MojTestErrCheck(err); //create a RevTimestamp entry for more than PurgeNumDays days ago err = MojGetCurrentTime(time); MojTestErrCheck(err); err = createRevTimestamp(db, revNums[9], time.microsecs() - (((MojInt64)40) * MojTime::UnitsPerDay)); MojTestErrCheck(err); //purge now, since nothing has been deleted, nothing should be purged, //but the RevTimestamp object should be deleted count = 0; err = db.purge(count, 30); MojTestErrCheck(err); err = checkObjectsPurged(db, count, 0, 10, 4, -1); MojTestErrCheck(err); //delete something - this will set its revision number higher bool found; err = db.del(ids[0], found); MojTestErrCheck(err); MojTestAssert(found == true); //purge now, since nothing has been deleted prior to the revision //number, nothing should be purged count = 0; err = db.purge(count, 30); MojTestErrCheck(err); err = checkObjectsPurged(db, count, 0, 9, 5, -1); MojTestErrCheck(err); //delete another object err = db.del(ids[1], found); MojTestErrCheck(err); MojTestAssert(found == true); //create a RevTimestamp entry for more than PurgeNumDays days ago, //with the rev number of the 1st obj we deleted MojDbQuery query; err = query.from(_T("PurgeTest:1")); MojTestErrCheck(err); err = query.where(MojDb::IdKey, MojDbQuery::OpEq, ids[0]); MojTestErrCheck(err); err = query.includeDeleted(); MojTestErrCheck(err); MojDbCursor cursor; err = db.find(query, cursor); MojTestErrCheck(err); MojObject objFromDb; err = cursor.get(objFromDb, found); MojTestErrCheck(err); err = cursor.close(); MojTestErrCheck(err); MojTestAssert(found == true); MojObject revFromDb; err = objFromDb.getRequired(MojDb::RevKey, revFromDb); MojTestErrCheck(err); err = MojGetCurrentTime(time); MojTestErrCheck(err); err = createRevTimestamp(db, revFromDb, time.microsecs() - (((MojInt64)35) * MojTime::UnitsPerDay)); MojTestErrCheck(err); //now purge, only id[0] should be purged count = 0; err = db.purge(count, 30); MojTestErrCheck(err); err = checkObjectsPurged(db, count, 1, 8, 6, revFromDb); MojTestErrCheck(err); //TODO 2.12.10 - this test does not pass yet, we need to fix calling delKind after a purge //err = delKindTest(db); //MojTestErrCheck(err); err = db.close(); MojTestErrCheck(err); return MojErrNone; }
MojErr MojDbPurgeTest::delKindTest(MojDb& db) { // start from scratch - purge everything MojUInt32 count = 0; MojErr err = db.purge(count, 0); MojTestErrCheck(err); MojTestAssert(count > 0); // purge again, make sure nothing is left err = db.purge(count, 0); MojTestErrCheck(err); MojTestAssert(count == 0); // make sure at least 2 objects exist MojDbQuery q; err = q.from(_T("PurgeTest:1")); MojTestErrCheck(err); MojDbCursor cursor; err = db.find(q, cursor); MojTestErrCheck(err); MojUInt32 objCount; err = cursor.count(objCount); MojTestErrCheck(err); err = cursor.close(); MojTestErrCheck(err); if (objCount <= 1) { for (int i = objCount; i < 2; i++) { MojObject obj; err = obj.fromJson(MojTestObjStr1); MojTestErrCheck(err); err = db.put(obj); MojTestErrCheck(err); objCount++; } } // delete half the objects q.limit(objCount / 2); MojUInt32 delCount; err = db.del(q, delCount); MojTestErrCheck(err); // delete the kind MojString idStr; err = idStr.assign(_T("PurgeTest:1")); MojTestErrCheck(err); MojObject id(idStr); bool found; err = db.delKind(id, found); MojTestErrCheck(err); MojTestAssert(found); /*MojUInt32 deletedObjCount; err = q.where(_T("_del"), MojDbQuery::OpEq, true); MojTestErrCheck(err); q.includeDeleted(true); err = db.find(q, cursor); MojTestErrCheck(err); err = cursor.count(deletedObjCount); MojTestErrCheck(err); err = cursor.close(); MojTestErrCheck(err); // now all the objects should be deleted MojTestAssert(deletedObjCount == objCount);*/ // purge now err = db.purge(count, 0); MojTestErrCheck(err); return MojErrNone; }
MojErr MojDbQuotaTest::testUsage(MojDb& db) { // put quota MojObject obj; MojErr err = obj.fromJson(_T("{\"owner\":\"com.foo.bar\",\"size\":1000}")); MojErrCheck(err); err = db.putQuotas(&obj, &obj + 1); MojErrCheck(err); // empty MojInt64 kindUsage = 0; err = getKindUsage(db, _T("Test:1"), kindUsage); MojTestErrCheck(err); MojTestAssert(kindUsage == 0); MojInt64 quotaUsage = 0; err = getQuotaUsage(db, _T("com.foo.bar"), quotaUsage); MojTestErrCheck(err); MojTestAssert(quotaUsage == 0); // new obj err = put(db, MojTestKind1Objects[0]); MojTestErrCheck(err); MojInt64 kindUsage1 = 0; err = getKindUsage(db, _T("Test:1"), kindUsage1); MojTestErrCheck(err); MojTestAssert(kindUsage1 > 0); MojInt64 quotaUsage1 = 0; err = getQuotaUsage(db, _T("com.foo.bar"), quotaUsage1); MojTestErrCheck(err); MojTestAssert(quotaUsage1 > 0); // add prop to existing obj err = obj.fromJson(MojTestKind1Objects[0]); MojTestErrCheck(err); err = obj.put(_T("bar"), 2); MojTestErrCheck(err); err = db.put(obj, MojDb::FlagForce); MojTestErrCheck(err); MojInt64 kindUsage2 = 0; err = getKindUsage(db, _T("Test:1"), kindUsage2); MojTestErrCheck(err); MojTestAssert(kindUsage2 > kindUsage1); MojInt64 quotaUsage2 = 0; err = getQuotaUsage(db, _T("com.foo.bar"), quotaUsage2); MojTestErrCheck(err); MojTestAssert(quotaUsage2 > quotaUsage1); // add 2nd obj err = put(db, MojTestKind1Objects[1]); MojTestErrCheck(err); MojInt64 kindUsage3 = 0; err = getKindUsage(db, _T("Test:1"), kindUsage3); MojTestErrCheck(err); MojTestAssert(kindUsage3 > kindUsage2); MojInt64 quotaUsage3 = 0; err = getQuotaUsage(db, _T("com.foo.bar"), quotaUsage3); MojTestErrCheck(err); MojTestAssert(quotaUsage3 > quotaUsage2); // del first obj bool found = false; err = db.del(1, found, MojDb::FlagPurge); MojTestErrCheck(err); MojTestAssert(found); MojInt64 kindUsage4 = 0; err = getKindUsage(db, _T("Test:1"), kindUsage4); MojTestErrCheck(err); MojTestAssert(kindUsage4 == kindUsage3 - kindUsage2); MojInt64 quotaUsage4 = 0; err = getQuotaUsage(db, _T("com.foo.bar"), quotaUsage4); MojTestErrCheck(err); MojTestAssert(quotaUsage4 == quotaUsage3 - quotaUsage2); // add index err = obj.fromJson(MojTestKind1Str2); MojTestErrCheck(err); err = db.putKind(obj); MojTestErrCheck(err); MojInt64 kindUsage5 = 0; err = getKindUsage(db, _T("Test:1"), kindUsage5); MojTestErrCheck(err); MojTestAssert(kindUsage5 > kindUsage4); MojInt64 quotaUsage5 = 0; err = getQuotaUsage(db, _T("com.foo.bar"), quotaUsage5); MojTestErrCheck(err); MojTestAssert(quotaUsage5 > quotaUsage4); // update locale err = db.updateLocale(_T("FR_fr")); MojTestErrCheck(err); err = db.updateLocale(_T("EN_us")); MojTestErrCheck(err); MojInt64 kindUsage6 = 0; err = getKindUsage(db, _T("Test:1"), kindUsage6); MojTestErrCheck(err); MojTestAssert(kindUsage6 == kindUsage5); MojInt64 quotaUsage6 = 0; err = getQuotaUsage(db, _T("com.foo.bar"), quotaUsage6); MojTestErrCheck(err); MojTestAssert(quotaUsage6 == quotaUsage5); // drop index err = obj.fromJson(MojTestKind1Str1); MojTestErrCheck(err); err = db.putKind(obj); MojTestErrCheck(err); MojInt64 kindUsage7 = 0; err = getKindUsage(db, _T("Test:1"), kindUsage7); MojTestErrCheck(err); MojTestAssert(kindUsage7 == kindUsage4); MojInt64 quotaUsage7 = 0; err = getQuotaUsage(db, _T("com.foo.bar"), quotaUsage7); MojTestErrCheck(err); MojTestAssert(quotaUsage7 == quotaUsage4); // drop kind MojString kindStr; err = kindStr.assign(_T("Test:1")); MojTestErrCheck(err); err = db.delKind(kindStr, found); MojTestErrCheck(err); MojTestAssert(found); MojInt64 kindUsage8 = 0; err = getKindUsage(db, _T("Test:1"), kindUsage8); MojTestErrCheck(err); MojTestAssert(kindUsage8 == 0); MojInt64 quotaUsage8 = 0; err = getQuotaUsage(db, _T("com.foo.bar"), quotaUsage8); MojTestErrCheck(err); MojTestAssert(quotaUsage8 == 0); err = db.quotaStats(obj); MojErrCheck(err); return MojErrNone; }
MojErr MojDbTxnTest::run() { MojErr err; MojDb db; err = MojDbTestEnv::run(MojDbTestDir); MojTestErrCheck(err); // open err = db.open(MojDbTestDir, env()); MojTestErrCheck(err); // add type MojObject obj; err = obj.fromJson(MojKindStr); MojTestErrCheck(err); err = db.putKind(obj); MojTestErrCheck(err); for (int i = 0; i < 100; ++i) { MojObject obj; MojErr err = obj.putString(MojDb::KindKey, _T("Test:1")); MojTestErrCheck(err); err = obj.put(_T("foo"), (i + 25) % 100); MojTestErrCheck(err); err = obj.put(_T("bar"), i % 3); MojTestErrCheck(err); err = db.put(obj); MojTestErrCheck(err); } // db: x0 = (25, 0), (26, 1), (27, 2), (28, 0) .. x74 = (99,2), x75 = (0,0) .. x99 = (24,0) { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("foo"), MojDbQuery::OpLessThan, 50); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -1); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count); MojTestErrCheck(err); MojTestAssert(count == 50); } // db: x0 = (25, -1) .. x24 = (49,-1), x25 = (50,1)i .. x74 = (99,2), x75 = (0,-1) .. x99 = (24, -1) // test visibility with update { MojDbReq req; // start transaction req.begin(&db, false); MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpEq, -1); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -2); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count, MojDb::FlagNone, req); MojTestErrCheck(err); MojTestAssert(count == 50); // txn: x0 = (25, -2) .. x24 = (49,-2), x25 = (50,1) .. x74 = (99,2), x75 = (0,-2) .. x99 = (24, -2) // visible within transaction { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpEq, -2); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -2); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count, MojDb::FlagNone, req); MojTestErrCheck(err); MojTestAssert(count == 50); } // With BerkeleyDB parallel transaction is locked // invisible outside of transaction if (engineName().compare(_T("leveldb")) == 0) { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpEq, -2); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -2); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count); MojTestErrCheck(err); MojTestAssert(count == 0); } } // invisible after aborted transaction { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpEq, -2); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -2); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count); MojTestErrCheck(err); MojTestAssert(count == 0); } // test visibility with delete { MojDbReq req; // start transaction req.begin(&db, false); MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpEq, -1); MojTestErrCheck(err); MojUInt32 count = 0; err = db.del(query, count, MojDb::FlagNone, req); MojTestErrCheck(err); MojTestAssert(count == 50); // txn: x25 = (50,1) .. x74 = (99,2) // visible within transaction { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpLessThan, 2); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -3); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count, MojDb::FlagNone, req); MojTestErrCheck(err); MojTestAssert(count == 33); } // With BerkeleyDB parallel transaction is locked // invisible outside of transaction if (engineName().compare(_T("leveldb")) == 0) { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpLessThan, 2); MojTestErrCheck(err); MojObject update; err = update.put(_T("bar"), -3); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, update, count); MojTestErrCheck(err); MojTestAssert(count == 83); } } // invisible after aborted transaction { MojDbQuery query; err = query.from(_T("Test:1")); MojTestErrCheck(err); err = query.where(_T("bar"), MojDbQuery::OpLessThan, 2); MojTestErrCheck(err); MojObject update; // Note that if we change bar=1 here we might get double-update when // record we just updated moved into records range ahead of our current // cursor position MojUInt32 count = 0; err = db.merge(query, update, count); MojTestErrCheck(err); MojTestAssert(count == 83); } err = db.close(); MojTestErrCheck(err); return MojErrNone; }
MojErr MojDbRevTest::run() { MojDb db; MojErr err = db.open(MojDbTestDir); MojTestErrCheck(err); // put type MojObject obj; err = obj.fromJson(MojKindStr); MojTestErrCheck(err); // put obj err = db.putKind(obj); MojTestErrCheck(err); err = obj.fromJson(MojTestObjStr1); MojTestErrCheck(err); err = db.put(obj); MojTestErrCheck(err); MojObject id; err = obj.getRequired(MojDb::IdKey, id); MojTestErrCheck(err); // get obj and verify rev eq MojObject rev; err = obj.getRequired(MojDb::RevKey, rev); MojTestErrCheck(err); err = checkRevEq(db, id, rev); MojTestErrCheck(err); // put identical obj and verify rev not changed err = db.put(obj); MojTestErrCheck(err); err = checkRevEq(db, id, rev); MojTestErrCheck(err); // put with changed prop and verify rev gt err = obj.fromJson(MojTestObjStr2); MojTestErrCheck(err); err = obj.put(MojDb::IdKey, id); MojTestErrCheck(err); err = db.put(obj); // this put will fail because we haven't included a rev MojTestErrExpected(err, MojErrDbRevNotSpecified); bool found = false; err = db.del(id, found); // verify that we can put without a rev if the object is deleted MojTestErrCheck(err); MojTestAssert(found); err = db.put(obj); MojTestErrCheck(err); err = obj.getRequired(MojDb::RevKey, rev); MojTestErrCheck(err); err = obj.put(MojDb::RevKey, 1); MojTestErrCheck(err); err = db.put(obj); // this put will fail because the revision num is lower MojTestErrExpected(err, MojErrDbRevisionMismatch); err = obj.put(MojDb::RevKey, rev); MojTestErrCheck(err); err = db.put(obj); // now this should succeed MojTestErrCheck(err); // merge with unchanged prop and verify rev not changed err = obj.fromJson(MojTestObjStr3); MojTestErrCheck(err); err = obj.put(MojDb::IdKey, id); MojTestErrCheck(err); err = db.merge(obj); MojTestErrCheck(err); err = checkRevEq(db, id, rev); MojTestErrCheck(err); // merge with changed prop and verify rev gt err = obj.fromJson(MojTestObjStr4); MojTestErrCheck(err); err = obj.put(MojDb::IdKey, id); MojTestErrCheck(err); err = db.merge(obj); MojTestErrCheck(err); err = checkRevGt(db, id, rev); MojTestErrCheck(err); // query merge with unchanged prop and verify rev not changed MojDbQuery query; err = query.from("RevTest:1"); MojTestErrCheck(err); err = obj.fromJson(MojTestObjStr4); MojTestErrCheck(err); MojUInt32 count = 0; err = db.merge(query, obj, count); MojTestErrCheck(err); MojTestAssert(count == 1); err = checkRevEq(db, id, rev); MojTestErrCheck(err); // query merge with changed prop and verify rev gt err = obj.fromJson(MojTestObjStr3); MojTestErrCheck(err); err = db.merge(query, obj, count); MojTestErrCheck(err); MojTestAssert(count == 1); err = checkRevGt(db, id, rev); MojTestErrCheck(err); // del verify rev gt err = db.del(id, found); MojTestErrCheck(err); MojTestAssert(found); err = checkRevGt(db, id, rev); MojTestErrCheck(err); // del again and verify rev not changed err = db.del(id, found); MojTestErrCheck(err); MojTestAssert(found); err = checkRevEq(db, id, rev); MojTestErrCheck(err); // undel and verify rev gt err = obj.fromJson(MojTestObjStr5); MojTestErrCheck(err); err = obj.put(MojDb::IdKey, id); MojTestErrCheck(err); err = db.merge(obj); MojTestErrCheck(err); err = checkRevGt(db, id, rev); MojTestErrCheck(err); // query del and verify rev gt err = db.del(query, count); MojTestErrCheck(err); MojTestAssert(count == 1); err = checkRevGt(db, id, rev); MojTestErrCheck(err); err = db.close(); MojTestErrCheck(err); return MojErrNone; }