Beispiel #1
0
MojErr MojDbQuotaTest::testEnforce(MojDb& db)
{
	// set quota size to current usage
	MojInt64 quotaUsage1 = 0;
	MojErr err = getQuotaUsage(db, _T("com.foo.bar"), quotaUsage1);
	MojTestErrCheck(err);
	MojObject obj;
	err = obj.putString(_T("owner"), _T("com.foo.bar"));
	MojErrCheck(err);
	err = obj.putInt(_T("size"), quotaUsage1);
	MojErrCheck(err);
	err = db.putQuotas(&obj, &obj + 1);
	MojErrCheck(err);
	err = put(db, MojTestKind1Objects[3]);
	MojTestErrExpected(err, MojErrDbQuotaExceeded);
	// Try to delete the kind
	MojString kindStr;
	err = kindStr.assign(_T("Test:1"));
	MojTestErrCheck(err);
	bool found = false;
	err = db.delKind(kindStr, found);

    //The delete should be failure, because it contain sub kind "Test2:1"
    MojTestErrExpected(err,MojErrDbKindHasSubKinds); 
    MojTestAssert(!found); 

	return MojErrNone;
}
Beispiel #2
0
MojErr MojDbPermissionTest::testKindPermissions(MojDb& db)
{
	MojObject kind;
	MojErr err = kind.fromJson(MojTestKind1);
	MojTestErrCheck(err);

	// new kind, mismatched owner and caller
	MojDbReq req(false);
	err = req.domain(_T("com.bar"));
	MojTestErrCheck(err);
	err = db.putKind(kind, MojDb::FlagNone, req);
	MojTestErrExpected(err, MojErrDbPermissionDenied);
	// new kind, matched owner and caller
	err = req.domain(_T("com.foo"));
	MojTestErrCheck(err);
	err = db.putKind(kind, MojDb::FlagNone, req);
	MojTestErrCheck(err);
	// existing kind, matched owner and caller
	err = db.putKind(kind, MojDb::FlagNone, req);
	MojTestErrCheck(err);
	// existing kind, mismatched owner and caller
	err = req.domain(_T("com.bar"));
	MojTestErrCheck(err);
	err = db.putKind(kind, MojDb::FlagNone, req);
	MojTestErrExpected(err, MojErrDbPermissionDenied);
	// delKind, mismatched owner and caller
	MojString id;
	err = id.assign(_T("PermissionTest:1"));
	MojTestErrCheck(err);
	bool found = false;
	err = db.delKind(id, found, MojDb::FlagNone, req);
	MojTestErrExpected(err, MojErrDbPermissionDenied);

	return MojErrNone;
}
Beispiel #3
0
MojErr MojDbQuotaTest::testErrors()
{
#ifdef MOJ_USE_BDB
	MojRefCountedPtr<MojDbStorageEngine> engine(new MojDbBerkeleyEngine());
#elif MOJ_USE_LDB
	MojRefCountedPtr<MojDbStorageEngine> engine(new MojDbLevelEngine());
#else
    MojRefCountedPtr<MojDbStorageEngine> engine;
#endif
	MojAllocCheck(engine.get());
	MojRefCountedPtr<MojDbTestStorageEngine> testEngine(new MojDbTestStorageEngine(engine.get()));
	MojAllocCheck(testEngine.get());
	MojErr err = testEngine->open(MojDbTestDir);
	MojTestErrCheck(err);

	MojDb db;
	err = db.open(MojDbTestDir, testEngine.get());
	MojTestErrCheck(err);

	// test that failed put does not affect quota
	MojInt64 quotaUsage1 = 0;
	err = getQuotaUsage(db, _T("com.foo.*"), quotaUsage1);
	MojTestErrCheck(err);
	err = testEngine->setNextError(_T("txn.commit"), MojErrDbDeadlock);
	MojTestErrCheck(err);
	err = put(db, MojTestKind3Objects[1]);
	MojTestErrExpected(err, MojErrDbDeadlock);
	MojInt64 quotaUsage2 = 0;
	err = getQuotaUsage(db, _T("com.foo.*"), quotaUsage2);
	MojTestErrCheck(err);
	MojTestAssert(quotaUsage2 == quotaUsage1);
	// test that failed putQuota has no effect
	err = testEngine->setNextError(_T("txn.commit"), MojErrDbDeadlock);
	MojTestErrCheck(err);
	MojObject obj;
	err = obj.fromJson(_T("{\"owner\":\"com.foo.boo\",\"size\":1000}"));
	MojErrCheck(err);
	err = db.putQuotas(&obj, &obj + 1);
	MojTestErrExpected(err, MojErrDbDeadlock);
	MojInt64 quotaUsage3 = 0;
	err = getQuotaUsage(db, _T("com.foo.*"), quotaUsage3);
	MojTestErrCheck(err);
	MojTestAssert(quotaUsage3 == quotaUsage1);
	// test that failed putKind has no effect
	err = testEngine->setNextError(_T("txn.commit"), MojErrDbDeadlock);
	MojTestErrCheck(err);
	err = obj.fromJson(MojTestKind3Str2);
	MojTestErrCheck(err);
	err = db.putKind(obj);
	MojTestErrExpected(err, MojErrDbDeadlock);
	MojInt64 quotaUsage4 = 0;
	err = getQuotaUsage(db, _T("com.foo.*"), quotaUsage4);
	MojTestErrCheck(err);
	MojTestAssert(quotaUsage4 == quotaUsage1);

	err = db.close();
	MojTestErrCheck(err);

	return MojErrNone;
}
Beispiel #4
0
MojErr MojDbQuotaTest::testEnforce(MojDb& db)
{
	// set quota size to current usage
	MojInt64 quotaUsage1 = 0;
	MojErr err = getQuotaUsage(db, _T("com.foo.bar"), quotaUsage1);
	MojTestErrCheck(err);
	MojObject obj;
	err = obj.putString(_T("owner"), _T("com.foo.bar"));
	MojErrCheck(err);
	err = obj.putInt(_T("size"), quotaUsage1);
	MojErrCheck(err);
	err = db.putQuotas(&obj, &obj + 1);
	MojErrCheck(err);
	err = put(db, MojTestKind1Objects[3]);
	MojTestErrExpected(err, MojErrDbQuotaExceeded);
	// make sure we can delete the kind
	MojString kindStr;
	err = kindStr.assign(_T("Test:1"));
	MojTestErrCheck(err);
	bool found = false;
	err = db.delKind(kindStr, found);
	MojTestErrCheck(err);
	MojTestAssert(found);

	return MojErrNone;
}
Beispiel #5
0
MojErr MojDbIndexTest::checkInvalid(MojErr errExpected, const MojChar* json)
{
	MojDbIndex index(NULL, NULL);
	MojErr err = indexFromObject(index, json);
	MojTestErrExpected(err, errExpected);

	return MojErrNone;
}
Beispiel #6
0
MojErr MojDbPermissionTest::checkInvalid(const MojChar* json, MojDb& db)
{
	MojObject permission;
	MojErr err = permission.fromJson(json);
	MojTestErrCheck(err);
	err = db.putPermissions(&permission, &permission+1);
	MojTestErrExpected(err, MojErrDbInvalidCaller);

	return MojErrNone;
}
Beispiel #7
0
MojErr MojThreadTest::errTest()
{
	MojThreadT thread = MojInvalidThread;
	MojErr err = MojThreadCreate(thread, MojThreadTestErrFn, NULL);
	MojTestErrCheck(err);
	MojErr threadErr = MojErrNone;
	err = MojThreadJoin(thread, threadErr);
	MojTestErrCheck(err);
	MojTestErrExpected(threadErr, MojErrNotFound);

	return MojErrNone;
}
Beispiel #8
0
MojErr MojDbPermissionTest::putPermissions(MojDb& db)
{
	MojDbReq reqOwner(false);
	MojErr err = reqOwner.domain(_T("com.foo"));
	MojTestErrCheck(err);
	MojDbReq reqGranted(false);
	err = reqGranted.domain("com.granted 3287");
	MojTestErrCheck(err);
	MojDbReq reqBad(false);
	err = reqBad.domain("com.bad");
	MojTestErrCheck(err);

	MojObject permission;
	err = permission.fromJson(MojTestPermission1);
	MojTestErrCheck(err);
	err = db.putPermissions(&permission, &permission + 1, reqBad);
	MojTestErrExpected(err, MojErrDbPermissionDenied);
	err = reqBad.abort();
	MojTestErrCheck(err);
	err = db.putPermissions(&permission, &permission + 1, reqOwner);
	MojTestErrCheck(err);
	err = db.putPermissions(&permission, &permission + 1, reqGranted);
	MojTestErrExpected(err, MojErrDbPermissionDenied);
	err = reqGranted.abort();
	MojTestErrCheck(err);

	err = permission.fromJson(MojTestPermissionWildcard);
	MojTestErrCheck(err);
	err = db.putPermissions(&permission, &permission + 1, reqOwner);
	MojTestErrCheck(err);
	err = permission.fromJson(MojTestPermissionWildcard2);
	MojTestErrCheck(err);
	err = db.putPermissions(&permission, &permission + 1, reqOwner);
	MojTestErrCheck(err);

	return MojErrNone;
}
Beispiel #9
0
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;
}
Beispiel #10
0
MojErr MojAutoPtrTest::run()
{
	MojErr err = MojErrNone;
	MojAutoPtr<int> intPtr1;
	MojAutoPtr<MojString> strPtr1;
	MojAutoArrayPtr<MojChar> charPtr1;
	MojAutoPtr<int> intPtr2(new int(5));
	MojAutoPtr<MojString> strPtr2(new MojString());
	MojAutoArrayPtr<MojChar> charPtr2(new MojChar[6]);
	MojAutoPtr<int> intPtr3(new int(5));
	MojAutoPtr<MojString> strPtr3(new MojString());
	MojAutoArrayPtr<MojChar> charPtr3(new MojChar[6]);
	MojAutoPtr<int> intPtr4(intPtr3);
	MojAutoPtr<MojString> strPtr4(strPtr3);
	MojAutoArrayPtr<MojChar> charPtr4(charPtr3);
	MojSharedPtr<int> intSp1;
	MojSharedPtr<int> intSp2(intSp1);
	MojSharedPtr<MojString> strSp1;
	MojSharedPtr<MojString> strSp2(strSp1);
	MojSharedArrayPtr<MojChar> charSp1;
	MojSharedArrayPtr<MojChar> charSp2;

	MojTestAssert(!intPtr1.get());
	MojTestAssert(!strPtr1.get());
	MojTestAssert(!charPtr1.get());
	MojTestAssert(!intPtr3.get());
	MojTestAssert(!strPtr3.get());
	MojTestAssert(!charPtr3.get());
	MojTestAssert(intPtr2.get());
	MojTestAssert(strPtr2.get());
	MojTestAssert(charPtr2.get());
	MojTestAssert(intPtr4.get());
	MojTestAssert(strPtr4.get());
	MojTestAssert(charPtr4.get());
	MojTestAssert(!intPtr1.release());

	intPtr1.reset();
	strPtr1.reset();
	charPtr1.reset();
	MojTestAssert(*intPtr2.get() == 5);
	MojTestAssert(*intPtr2 == 5);
	MojTestAssert(strPtr2->empty());
	MojStrCpy(charPtr2.get(), _T("hello"));
	MojTestAssert(*charPtr2 == _T('h'));
	err = strPtr2->assign(charPtr2.get());
	MojTestErrCheck(err);
	MojTestAssert(*strPtr2 == charPtr2.get());
	intPtr1 = intPtr2;
	strPtr1 = strPtr2;
	charPtr1 = charPtr2;
	MojTestAssert(!intPtr2.get());
	MojTestAssert(!strPtr2.get());
	MojTestAssert(!charPtr2.get());
	MojTestAssert(intPtr1.get());
	MojTestAssert(strPtr1.get());
	MojTestAssert(charPtr1.get());
	MojTestAssert(*intPtr1 == 5);
	MojTestAssert(*strPtr1 == _T("hello"));
	MojTestAssert(*charPtr1 == _T('h'));

	delete intPtr1.release();

	// related type
	MojAutoPtr<FooTest> foop;
	MojAutoPtr<BarTest> barp(new BarTest());
	MojAllocCheck(barp.get());
	BarTest* barraw = barp.get();
	foop = barp;
	MojTestAssert(foop.get() == barraw);
	MojTestAssert(barp.get() == NULL);
	MojAutoPtr<FooTest> foop2(barp);

	MojSharedPtr<FooTest> foosp;
	MojSharedPtr<BarTest> barsp;
	foosp = barsp;
	MojSharedPtr<FooTest> foosp2(barsp);

	// shared ptrs
	MojTestAssert(!intSp1.get());
	MojTestAssert(intSp1.refcount() == 0);
	MojTestAssert(!intSp2.get());
	MojTestAssert(intSp2.refcount() == 0);
	MojTestAssert(!strSp1.get());
	MojTestAssert(strSp1.refcount() == 0);
	MojTestAssert(!strSp2.get());
	MojTestAssert(strSp2.refcount() == 0);
	MojTestAssert(!charSp1.get());
	MojTestAssert(charSp1.refcount() == 0);
	MojTestAssert(!charSp2.get());
	MojTestAssert(charSp2.refcount() == 0);

	err = intSp1.reset(new int(10));
	MojTestErrCheck(err);
	MojTestAssert(intSp1.get() && *intSp1 == 10);
	MojTestAssert(!intSp2.get());
	MojTestAssert(intSp1.refcount() == 1);
	intSp2 = intSp1;
	MojTestAssert(intSp1.get() && *intSp1 == 10);
	MojTestAssert(intSp2.get() && *intSp2 == 10);
	MojTestAssert(intSp1.refcount() == 2);
	MojTestAssert(intSp2.refcount() == 2);
	err = intSp1.reset(new int(20));
	MojTestErrCheck(err);
	MojTestAssert(intSp1.get() && *intSp1 == 20);
	MojTestAssert(intSp2.get() && *intSp2 == 10);
	MojTestAssert(intSp1.refcount() == 1);
	MojTestAssert(intSp2.refcount() == 1);
	intSp2 = intSp1;
	MojTestAssert(intSp1.get() && *intSp1 == 20);
	MojTestAssert(intSp2.get() && *intSp2 == 20);
	MojTestAssert(intSp1.refcount() == 2);
	MojTestAssert(intSp2.refcount() == 2);
	err = intSp1.reset(NULL);
	MojTestErrCheck(err);
	MojTestAssert(!intSp1.get());
	MojTestAssert(intSp1.refcount() == 0);
	MojTestAssert(intSp2.get() && *intSp2 == 20);
	MojTestAssert(intSp2.refcount() == 1);
	err = strSp1.reset(new MojString);
	MojTestErrCheck(err);
	MojTestAssert(strSp1.get());
	MojTestAssert(strSp1->empty());
	MojTestAssert(*strSp1 == _T(""));
	strSp2 = strSp1;
	MojTestAssert(*strSp2 == _T(""));
	err = charSp1.reset(new MojChar[100]);
	MojErrCheck(err);
	MojTestAssert(charSp1.get());
	charSp2 = charSp1;
	MojTestAssert(charSp1.get() == charSp2.get());
	err = charSp1.resetChecked(new MojChar[100]);
	MojErrCheck(err);
	err = charSp1.resetChecked(NULL);
	MojTestErrExpected(err, MojErrNoMem);

	// refs
	MojAutoPtr<FooTest> foop3 = makeFooAuto();
	takeFooAuto(foop3);
	takeFooAuto(makeFooAuto());
	MojSharedPtr<FooTest> foosp3 = makeFooShared();
	takeFooShared(foosp3);
	takeFooShared(makeFooShared());

	return MojErrNone;
}
MojErr MojDataSerializationTest::run()
{
	MojBuffer buf;
	MojDataWriter writer(buf);
	MojErr err = writer.writeUInt8(0);
	MojTestErrCheck(err);
	err = writer.writeUInt8(5);
	MojTestErrCheck(err);
	err = writer.writeUInt8(0xFF);
	MojTestErrCheck(err);
	err = writer.writeUInt16(0);
	MojTestErrCheck(err);
	err = writer.writeUInt16(256);
	MojTestErrCheck(err);
	err = writer.writeUInt16(0xFFFF);
	MojTestErrCheck(err);
	err = writer.writeUInt32(0);
	MojTestErrCheck(err);
	err = writer.writeUInt32(0x10000);
	MojTestErrCheck(err);
	err = writer.writeUInt32(0xFFFFFFFF);
	MojTestErrCheck(err);
	err = writer.writeInt64(0);
	MojTestErrCheck(err);
	err = writer.writeInt64(-56);
	MojTestErrCheck(err);
	err = writer.writeInt64(9223372036854775807LL);
	MojTestErrCheck(err);
	err = writer.writeInt64(-9223372036854775807LL);
	MojTestErrCheck(err);
	err = writer.writeDecimal(MojDecimal(3, 14159));
	MojTestErrCheck(err);
	err = writer.writeDecimal(MojDecimal(-9999, 888888));
	MojTestErrCheck(err);

	const MojByte* data = NULL;
	MojSize size;
	err = writer.buf().data(data, size);
	MojTestErrCheck(err);
	MojDataReader reader(data, size);
	MojUInt8 ui8val = 98;
	err = reader.readUInt8(ui8val);
	MojTestErrCheck(err);
	MojTestAssert(ui8val == 0);
	err = reader.readUInt8(ui8val);
	MojTestErrCheck(err);
	MojTestAssert(ui8val == 5);
	err = reader.readUInt8(ui8val);
	MojTestErrCheck(err);
	MojTestAssert(ui8val == 0xFF);
	MojUInt16 ui16val = 9999;
	err = reader.readUInt16(ui16val);
	MojTestErrCheck(err);
	MojTestAssert(ui16val == 0);
	err = reader.readUInt16(ui16val);
	MojTestErrCheck(err);
	MojTestAssert(ui16val == 256);
	err = reader.readUInt16(ui16val);
	MojTestErrCheck(err);
	MojTestAssert(ui16val == 0xFFFF);
	MojUInt32 ui32val = 89765;
	err = reader.readUInt32(ui32val);
	MojTestErrCheck(err);
	MojTestAssert(ui32val == 0);
	err = reader.readUInt32(ui32val);
	MojTestErrCheck(err);
	MojTestAssert(ui32val == 0x10000);
	err = reader.readUInt32(ui32val);
	MojTestErrCheck(err);
	MojTestAssert(ui32val == 0xFFFFFFFF);
	MojInt64 i64val = -98765432;
	err = reader.readInt64(i64val);
	MojTestErrCheck(err);
	MojTestAssert(i64val == 0);
	err = reader.readInt64(i64val);
	MojTestErrCheck(err);
	MojTestAssert(i64val == -56);
	err = reader.readInt64(i64val);
	MojTestErrCheck(err);
	MojTestAssert(i64val == 9223372036854775807LL);
	err = reader.readInt64(i64val);
	MojTestErrCheck(err);
	MojTestAssert(i64val == -9223372036854775807LL);
	MojDecimal decVal;
	err = reader.readDecimal(decVal);
	MojTestErrCheck(err);
	MojTestAssert(decVal == MojDecimal(3, 14159));
	err = reader.readDecimal(decVal);
	MojTestErrCheck(err);
	MojTestAssert(decVal == MojDecimal(-9999, 888888));


	MojDataReader reader2(NULL, 0);
	err = reader.readUInt8(ui8val);
	MojTestErrExpected(err, MojErrUnexpectedEof);
	err = reader.readUInt16(ui16val);
	MojTestErrExpected(err, MojErrUnexpectedEof);
	err = reader.readUInt32(ui32val);
	MojTestErrExpected(err, MojErrUnexpectedEof);
	err = reader.readInt64(i64val);
	MojTestErrExpected(err, MojErrUnexpectedEof);
	err = reader.readDecimal(decVal);
	MojTestErrExpected(err, MojErrUnexpectedEof);

	return MojErrNone;
}
Beispiel #12
0
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;
}