void TearDown() { MojDbCoreTest::TearDown(); MojExpectNoErr( MojUnlink(MojLoadTestFileName) ); MojExpectNoErr( MojUnlink(MojDumpTestFileName) ); }
TEST_F(QuotaTest, enforce) { MojObject obj; // put quota MojAssertNoErr( obj.fromJson(_T("{\"owner\":\"com.foo.bar\",\"size\":1000}")) ); MojAssertNoErr( db.putQuotas(&obj, &obj + 1) ); // make kind2 inherit from kind1 MojAssertNoErr( obj.fromJson(MojTestKind2Str3) ); MojExpectNoErr( db.putKind(obj) ); //// end of prerequisites form prev tests // set quota size to current usage MojInt64 quotaUsage1 = 0; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage1) ); MojAssertNoErr( obj.putString(_T("owner"), _T("com.foo.bar")) ); MojAssertNoErr( obj.putInt(_T("size"), quotaUsage1) ); MojExpectNoErr( db.putQuotas(&obj, &obj + 1) ); MojAssertNoErr( obj.fromJson(MojTestKind1Objects[3]) ); EXPECT_EQ( MojErrDbQuotaExceeded, db.put(obj) ); // Try to delete the kind MojString kindStr; MojAssertNoErr( kindStr.assign(_T("Test:1")) ); bool found = false; EXPECT_EQ( MojErrDbKindHasSubKinds, db.delKind(kindStr, found) ) << "The delete should be failure, because it contain sub kind \"Test2:1\""; EXPECT_FALSE( found ); }
TEST(SignalTest, easy_peasy) { int signaled = -1; MojEasySignal<int> signal; decltype(signal)::EasySlot slot([&](int x) { signaled = x; return MojErrNone; }); signal.connect(slot.slot()); MojExpectNoErr( signal.call(42) ); EXPECT_EQ(42, signaled); MojExpectNoErr( signal.fire(45) ); EXPECT_EQ(45, signaled); MojExpectNoErr( signal.fire(41) ); EXPECT_EQ(45, signaled); MojEasySlot<int> badSlot([&](int x) { signaled = x; MojErrThrowMsg(MojErrUnknown, "intentional"); }); signal.connect(badSlot.slot()); EXPECT_EQ( MojErrUnknown, signal.call(41) ); EXPECT_EQ(41, signaled); EXPECT_EQ( MojErrUnknown, signal.call(41) ); EXPECT_EQ(41, signaled); }
/** * @test Situation when mantissa digits are close to boundary */ TEST(NumberTest, parse_mantissa_bound) { MojNumber::Parser parser; // MojNumber::Parser allows mantissa nearly as big // as: (2^64-1 - 9) `div` 10 * 10 + 9 = 18446744073709551609 MojExpectNoErr( MojNumber::Lexer::parse(parser, "18446744073709551609") ); }
/** * @test number very close to boundary of maximum MojDecimal but still * parsable. * I.e. ((2^63 - 1) / 10^6) / 10^12 = 9.223372036854775 * But double have issue to represent that number exactly, so we found * some other that is close enough. */ TEST(NumberTest, parse_decimal_exponent_bound) { MojNumber::Parser parser; MojDecimal d; MojAssertNoErr( MojNumber::Lexer::parse(parser, "9.22337203685477376e12") ); MojExpectNoErr( parser.toDecimal(d) ); EXPECT_EQ( MojDecimal(9.223372036854774376e12), d ); }
void buildSample() { for (int i = 0; i < 100; ++i) { MojObject obj; MojAssertNoErr( obj.putString(MojDb::KindKey, _T("Test:1")) ); MojAssertNoErr( obj.put(_T("foo"), (i + 25) % 100) ); MojAssertNoErr( obj.put(_T("bar"), i % 3) ); MojExpectNoErr( db.put(obj) ) << "Failed to put record #" << i; } // db: x0 = (25, 0), (26, 1), (27, 2), (28, 0) .. x74 = (99,2), x75 = (0,0) .. x99 = (24,0) }
/** * Basic test for lexer */ TEST(NumberTest, lexer_basic) { lexer_test_visitor tv{{ tok_neg, tok_mag(3), tok_frac(1), tok_frac(4), tok_exp(0) }}; // all valid representations of same number (from Lexer point of view) for (std::string sample : { "-3.14e0", "-3.14e+0", "-3.14E0", "-3.14E+0" }) { SCOPED_TRACE(sample); tv.reset(); MojExpectNoErr( MojNumber::Lexer::parse(tv, sample) ); } }
/** * Basic test for numbers with optional plus sign */ TEST(NumberTest, lexer_extra_plus) { lexer_test_visitor tv{{ tok_mag(3), tok_frac(1), tok_frac(4), tok_exp(0) }}; // all valid representations of same number (from Lexer point of view) for (std::string sample : { "3.14e0", "3.14e+0", "+3.14e0", "+3.14e+0", "3.14E0", "3.14E+0", "+3.14E0", "+3.14E+0" }) { tv.reset(); MojExpectNoErr( MojNumber::Lexer::parse(tv, sample) ) << "Lexer should report events for '" << sample << "' in a same way as for '3.14e0'"; } }
TEST_F(DatabaseSuite, dump_and_load) { // load MojAssertNoErr( MojFileFromString(MojLoadTestFileName, MojTestStr) ); MojUInt32 count = 0; MojAssertNoErr( db.load(MojLoadTestFileName, count) ); EXPECT_EQ( 11LL, count ); checkCount(); // dump count = 0; MojAssertNoErr( db.dump(MojDumpTestFileName, count) ); EXPECT_EQ( 11LL, count ); EXPECT_TRUE( db.kindEngine() ); // verify that we can get this kind MojDbKind *pk = 0; MojExpectNoErr( db.kindEngine()->getKind(kindId.data(), pk) ); EXPECT_TRUE( pk ); // del bool found = false; MojAssertNoErr( db.delKind(kindId, found) ); EXPECT_TRUE( found ); // verify that we can NOT get this kind pk = 0; EXPECT_EQ( MojErrDbKindNotRegistered, db.kindEngine()->getKind(kindId.data(), pk) ); EXPECT_FALSE( pk ); // purge deleted kinds MojAssertNoErr( db.purge(count, 0) ); EXPECT_EQ( 1LL, count ) << "Purged kinds marked for delete"; // load again. why 12? MojAssertNoErr( db.load(MojDumpTestFileName, count) ); EXPECT_EQ( 12LL, count ); checkCount(); // analyze MojObject analysis; MojAssertNoErr( db.stats(analysis) ); }
TEST_F(QuotaTest, error) { MojErr err; MojObject obj; // put quota (from testUsage) err = obj.fromJson(_T("{\"owner\":\"com.foo.bar\",\"size\":1000}")); MojAssertNoErr(err); err = db.putQuotas(&obj, &obj + 1); MojAssertNoErr(err); // quota for com.foo.baz (from multipleQuotas) err = obj.fromJson(_T("{\"owner\":\"com.foo.baz\",\"size\":1000}")); MojAssertNoErr(err); err = db.putQuotas(&obj, &obj + 1); MojAssertNoErr(err); // make kind2 inherit from kind1 (from multipleQuotas) err = obj.fromJson(MojTestKind2Str3); MojAssertNoErr(err); err = db.putKind(obj); MojExpectNoErr(err); // kind3 (from multipleQuotas) err = obj.fromJson(MojTestKind3Str1); MojAssertNoErr(err); err = db.putKind(obj); MojExpectNoErr(err); // wildcard (from multipleQuotas) err = obj.fromJson(_T("{\"owner\":\"com.foo.*\",\"size\":1000}")); MojAssertNoErr(err); err = db.putQuotas(&obj, &obj + 1); MojExpectNoErr(err); err = db.close(); MojAssertNoErr(err); MojRefCountedPtr<MojDbEnv> testEnv(new MojDbTestStorageEnv(env)); err = db.open(path.c_str(), testEnv); MojAssertNoErr(err); MojDbTestStorageEngine* testEngine = dynamic_cast<MojDbTestStorageEngine*> (db.storageEngine()); ASSERT_TRUE(testEngine); // test that failed put does not affect quota MojInt64 quotaUsage1 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.*"), quotaUsage1) ); EXPECT_LE( 0, quotaUsage1 ); err = testEngine->setNextError(_T("txn.commit"), MojErrDbDeadlock); MojAssertNoErr(err); err = obj.fromJson(MojTestKind3Objects[1]); MojAssertNoErr(err); EXPECT_EQ( MojErrDbDeadlock, db.put(obj) ); MojInt64 quotaUsage2 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.*"), quotaUsage2) ); EXPECT_LE( 0, quotaUsage2 ); EXPECT_EQ( quotaUsage1, quotaUsage2 ); // test that failed putQuota has no effect err = testEngine->setNextError(_T("txn.commit"), MojErrDbDeadlock); MojAssertNoErr(err); err = obj.fromJson(_T("{\"owner\":\"com.foo.boo\",\"size\":1000}")); MojAssertNoErr(err); EXPECT_EQ( MojErrDbDeadlock, db.putQuotas(&obj, &obj + 1) ); MojInt64 quotaUsage3 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.*"), quotaUsage3) ); EXPECT_LE( 0, quotaUsage3 ); EXPECT_EQ( quotaUsage1, quotaUsage3 ); // test that failed putKind has no effect err = testEngine->setNextError(_T("txn.commit"), MojErrDbDeadlock); MojAssertNoErr(err); err = obj.fromJson(MojTestKind3Str2); MojAssertNoErr(err); EXPECT_EQ( MojErrDbDeadlock, db.putKind(obj) ); MojInt64 quotaUsage4 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.*"), quotaUsage4) ); EXPECT_LE( 0, quotaUsage4 ); EXPECT_EQ( quotaUsage1, quotaUsage4 ); }
TEST_F(QuotaTest, multipleQuotas) { MojObject obj; // put quota (from testUsage) MojAssertNoErr( obj.fromJson(_T("{\"owner\":\"com.foo.bar\",\"size\":1000}")) ); MojAssertNoErr( db.putQuotas(&obj, &obj + 1) ); // quota for com.foo.baz MojAssertNoErr( obj.fromJson(_T("{\"owner\":\"com.foo.baz\",\"size\":1000}")) ); MojAssertNoErr( db.putQuotas(&obj, &obj + 1) ); // register kinds MojAssertNoErr( obj.fromJson(MojTestKind1Str1) ); MojExpectNoErr( db.putKind(obj) ); MojAssertNoErr( obj.fromJson(MojTestKind2Str1) ); MojExpectNoErr( db.putKind(obj) ); // put object of kind1 and kind2 EXPECT_NO_FATAL_FAILURE( put(db, MojTestKind1Objects[0]) ); EXPECT_NO_FATAL_FAILURE( put(db, MojTestKind2Objects[0]) ); MojInt64 quotaUsage1 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage1) ); EXPECT_LE( 0, quotaUsage1 ); MojInt64 quotaUsage2 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.baz"), quotaUsage2) ); EXPECT_LE( 0, quotaUsage2 ); EXPECT_LT( 0, quotaUsage1 ); EXPECT_EQ( 0, quotaUsage2 ); // change owner of kind2 to com.foo.baz MojAssertNoErr( obj.fromJson(MojTestKind2Str2) ); MojExpectNoErr( db.putKind(obj) ); MojInt64 quotaUsage3 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage3) ); EXPECT_LE( 0, quotaUsage3 ); MojInt64 quotaUsage4 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.baz"), quotaUsage4) ); EXPECT_LE( 0, quotaUsage4 ); EXPECT_LT( 0, quotaUsage3 ); EXPECT_EQ( quotaUsage3, quotaUsage4); // make kind2 inherit from kind1 MojAssertNoErr( obj.fromJson(MojTestKind2Str3) ); MojExpectNoErr( db.putKind(obj) ); MojInt64 quotaUsage5 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage5) ); MojInt64 quotaUsage6 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.baz"), quotaUsage6) ); EXPECT_GT( quotaUsage5, quotaUsage1 ); EXPECT_EQ( 0, quotaUsage6 ); // kind3 and object MojAssertNoErr( obj.fromJson(MojTestKind3Str1) ); MojExpectNoErr( db.putKind(obj) ); EXPECT_NO_FATAL_FAILURE( put(db, MojTestKind3Objects[0]) ); MojInt64 quotaUsage7 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage7) ); EXPECT_EQ( quotaUsage7, quotaUsage5 ); // wildcard MojAssertNoErr( obj.fromJson(_T("{\"owner\":\"com.foo.*\",\"size\":1000}")) ); MojExpectNoErr( db.putQuotas(&obj, &obj + 1) ); MojInt64 quotaUsage8 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage8) ); MojInt64 quotaUsage9 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.*"), quotaUsage9) ); EXPECT_EQ( quotaUsage5, quotaUsage8 ); EXPECT_LT( 0, quotaUsage9 ); }
TEST_F(QuotaTest, usage) { // put quota MojObject obj; MojAssertNoErr( obj.fromJson(_T("{\"owner\":\"com.foo.bar\",\"size\":1000}")) ); MojAssertNoErr( db.putQuotas(&obj, &obj + 1) ); // empty MojInt64 kindUsage = -1; EXPECT_NO_FATAL_FAILURE( getKindUsage(db, _T("Test:1"), kindUsage) ); EXPECT_EQ( 0, kindUsage ) << "Kind without objects should have zero usage"; MojInt64 quotaUsage = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage) ); EXPECT_EQ( 0, quotaUsage ) << "Quota without matching objects should have zero usage"; // new obj EXPECT_NO_FATAL_FAILURE( put(db, MojTestKind1Objects[0]) ); MojInt64 kindUsage1 = -1; EXPECT_NO_FATAL_FAILURE( getKindUsage(db, _T("Test:1"), kindUsage1) ); EXPECT_LT( 0, kindUsage1 ) << "Adding new object into kind should increase kind usage"; MojInt64 quotaUsage1 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage1) ); EXPECT_LT( 0, quotaUsage1 ) << "Adding new object matching quota should increase quota usage"; // add prop to existing obj MojAssertNoErr( obj.fromJson(MojTestKind1Objects[0]) ); MojAssertNoErr( obj.put(_T("bar"), 2) ); MojAssertNoErr( db.put(obj, MojDb::FlagForce) ); MojInt64 kindUsage2 = -1; EXPECT_NO_FATAL_FAILURE( getKindUsage(db, _T("Test:1"), kindUsage2) ); EXPECT_LE( 0, kindUsage2 ); EXPECT_LT( kindUsage1, kindUsage2 ) << "Adding property to existing object should increase kind usage"; MojInt64 quotaUsage2 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage2) ); EXPECT_LE( 0, quotaUsage2 ); EXPECT_LT( quotaUsage1, quotaUsage2 ) << "Adding property to existing object that matches quota should increase usage"; // add 2nd obj EXPECT_NO_FATAL_FAILURE( put(db, MojTestKind1Objects[1]) ); MojInt64 kindUsage3 = -1; EXPECT_NO_FATAL_FAILURE( getKindUsage(db, _T("Test:1"), kindUsage3) ); EXPECT_LE( 0, kindUsage3 ); EXPECT_LT( kindUsage2, kindUsage3 ) << "Adding another object should increase kind usage"; MojInt64 quotaUsage3 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage3) ); EXPECT_LE( 0, quotaUsage3 ); EXPECT_LT( quotaUsage2, quotaUsage3 ) << "Adding another object matching to quota should increase usage"; // del first obj bool found = false; MojExpectNoErr( db.del(1, found, MojDb::FlagPurge) ); EXPECT_TRUE( found ) << "Object should be deleted"; MojInt64 kindUsage4 = -1; EXPECT_NO_FATAL_FAILURE( getKindUsage(db, _T("Test:1"), kindUsage4) ); EXPECT_LE( 0, kindUsage4 ); EXPECT_EQ( kindUsage3 - kindUsage2, kindUsage4 ) << "Deletion of object should bring kind usage to expected value"; MojInt64 quotaUsage4 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage4) ); EXPECT_LE( 0, quotaUsage4 ); EXPECT_EQ( quotaUsage3 - quotaUsage2, quotaUsage4 ) << "Deletion of object should bring quota usage to expected value"; // add index MojAssertNoErr( obj.fromJson(MojTestKind1Str2) ); MojExpectNoErr( db.putKind(obj) ); MojInt64 kindUsage5 = -1; EXPECT_NO_FATAL_FAILURE( getKindUsage(db, _T("Test:1"), kindUsage5) ); EXPECT_LE( 0, kindUsage5 ); EXPECT_LT( kindUsage4, kindUsage5 ) << "Adding new index should increase kind usage"; MojInt64 quotaUsage5 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage5) ); EXPECT_LE( 0, quotaUsage5 ); EXPECT_LT( quotaUsage4, quotaUsage5 ) << "Adding new index should increase quota usage"; // update locale MojExpectNoErr( db.updateLocale(_T("FR_fr")) ); MojExpectNoErr( db.updateLocale(_T("EN_us")) ); MojInt64 kindUsage6 = -1; EXPECT_NO_FATAL_FAILURE( getKindUsage(db, _T("Test:1"), kindUsage6) ); EXPECT_LE( 0, kindUsage6 ); EXPECT_EQ( kindUsage5, kindUsage6 ) << "Switching locale forth and back shouldn't affect kind usage"; MojInt64 quotaUsage6 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage6) ); EXPECT_LE( 0, kindUsage6 ); EXPECT_EQ( quotaUsage5, quotaUsage6 ) << "Switching locale forth and back shouldn't affect quota usage"; // drop index MojAssertNoErr( obj.fromJson(MojTestKind1Str1) ); MojExpectNoErr( db.putKind(obj) ); MojInt64 kindUsage7 = -1; EXPECT_NO_FATAL_FAILURE( getKindUsage(db, _T("Test:1"), kindUsage7) ); EXPECT_LE( 0, kindUsage7 ); EXPECT_EQ( kindUsage4, kindUsage7 ) << "Dropping of index should bring kind usage to expected value"; MojInt64 quotaUsage7 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage7) ); EXPECT_LE( 0, quotaUsage7 ); EXPECT_EQ( quotaUsage4, quotaUsage7 ) << "Dropping of index should bring quota usage to expected value"; // drop kind MojString kindStr; MojAssertNoErr( kindStr.assign(_T("Test:1")) ); MojExpectNoErr( db.delKind(kindStr, found) ); EXPECT_TRUE( found ) << "Kind should be deleted"; MojInt64 kindUsage8 = -1; EXPECT_NO_FATAL_FAILURE( getKindUsage(db, _T("Test:1"), kindUsage8) ); EXPECT_EQ( 0, kindUsage8 ) << "Dropping of kind should bring its usage to zero"; MojInt64 quotaUsage8 = -1; EXPECT_NO_FATAL_FAILURE( getQuotaUsage(db, _T("com.foo.bar"), quotaUsage8) ); EXPECT_EQ( 0, quotaUsage8 ) << "Dropping of kind that matches quota should bring quota usage to zero"; MojExpectNoErr( db.quotaStats(obj) ); MojString statStr; MojExpectNoErr( obj.toJson(statStr) ); std::cerr << "quotaStats: " << statStr.data() << std::endl; }
void TearDown() { // TODO: clean DB MojExpectNoErr( db.close() ); }