#include #include #include #include #include "base.h" #include "storage.h" #include "cursor.h" class DuplicatesTest : public ::testing::Test { protected: DuplicatesTest(): ::testing::Test(), tu1(db->getStorage("sameSizeInts")), tu2(db->getStorage("stringInt")), tu3(db->getStorage("floatFloat")), tu4(db->getStorage("intDouble")), tu5(db->getStorage("floatLong")) {} ~DuplicatesTest() {} uint32_t getTU1Flags() const {return tu1->flags();} uint32_t getTU2Flags() const {return tu2->flags();} uint32_t getTU3Flags() const {return tu3->flags();} uint32_t getTU4Flags() const {return tu4->flags();} uint32_t getTU5Flags() const {return tu5->flags();} static void SetUpTestSuite() { if (db == nullptr) { db = new LMDBAL::Base("testBase"); db->addStorage("sameSizeInts", true); db->addStorage("stringInt", true); db->addStorage("floatFloat", true); db->addStorage("intDouble", true); db->addStorage("floatLong", true); db->open(); } } static void TearDownTestSuite() { db->close(); db->removeDirectory(); delete db; db = nullptr; } static LMDBAL::Base* db; LMDBAL::Storage* tu1; LMDBAL::Storage* tu2; LMDBAL::Storage* tu3; LMDBAL::Storage* tu4; LMDBAL::Storage* tu5; }; LMDBAL::Base* DuplicatesTest::db = nullptr; TEST_F(DuplicatesTest, Flags) { uint32_t tu1Flags = getTU1Flags(); uint32_t tu2Flags = getTU2Flags(); uint32_t tu3Flags = getTU3Flags(); uint32_t tu4Flags = getTU4Flags(); uint32_t tu5Flags = getTU5Flags(); EXPECT_TRUE(tu1Flags & MDB_INTEGERKEY); EXPECT_TRUE(tu1Flags & MDB_DUPSORT); EXPECT_TRUE(tu1Flags & MDB_DUPFIXED); EXPECT_FALSE(tu1Flags & MDB_INTEGERDUP); EXPECT_FALSE(tu2Flags & MDB_INTEGERKEY); EXPECT_TRUE(tu2Flags & MDB_DUPSORT); EXPECT_TRUE(tu2Flags & MDB_DUPFIXED); EXPECT_FALSE(tu2Flags & MDB_INTEGERDUP); EXPECT_FALSE(tu3Flags & MDB_INTEGERKEY); EXPECT_TRUE(tu3Flags & MDB_DUPSORT); EXPECT_TRUE(tu3Flags & MDB_DUPFIXED); EXPECT_FALSE(tu3Flags & MDB_INTEGERDUP); EXPECT_TRUE(tu4Flags & MDB_INTEGERKEY); EXPECT_TRUE(tu4Flags & MDB_DUPSORT); EXPECT_TRUE(tu4Flags & MDB_DUPFIXED); EXPECT_FALSE(tu4Flags & MDB_INTEGERDUP); EXPECT_FALSE(tu5Flags & MDB_INTEGERKEY); EXPECT_TRUE(tu5Flags & MDB_DUPSORT); EXPECT_TRUE(tu5Flags & MDB_DUPFIXED); EXPECT_TRUE(tu5Flags & MDB_INTEGERDUP); } TEST_F(DuplicatesTest, Adding) { tu1->addRecord(1, 1); tu1->addRecord(2, 2); tu1->addRecord(2, 1); tu1->addRecord(1, 2); EXPECT_THROW(tu1->addRecord(1, 1), LMDBAL::Exist); EXPECT_THROW(tu1->addRecord(1, 2), LMDBAL::Exist); EXPECT_THROW(tu1->addRecord(2, 2), LMDBAL::Exist); EXPECT_EQ(tu1->count(), 4); EXPECT_EQ(tu1->getRecord(1), 1); EXPECT_EQ(tu1->getRecord(2), 1); tu2->addRecord("brass boulers", -54); tu2->addRecord("grief ", 61); tu2->addRecord("grief ", 19); tu2->addRecord("grief ", 32); tu2->addRecord("miracles of a lunch", 44); tu2->addRecord("miracles of a lunch", 102); tu2->addRecord("miracles of a lunch", -72); EXPECT_THROW(tu2->addRecord("grief ", 19), LMDBAL::Exist); EXPECT_THROW(tu2->addRecord("brass boulers", -54), LMDBAL::Exist); EXPECT_EQ(tu2->count(), 7); EXPECT_EQ(tu2->getRecord("grief "), 19); EXPECT_EQ(tu2->getRecord("miracles of a lunch"), 44); //apparently ints are compared as uints tu3->addRecord(7.2, 697); tu3->addRecord(5119, -998.53); tu3->addRecord(7.2001, 4); tu3->addRecord(7.2, -113); tu3->addRecord(7.2, -53.5478); float tu3ds = 0.432924; tu3->addRecord(5119, tu3ds); EXPECT_THROW(tu3->addRecord(5119, -998.53), LMDBAL::Exist); EXPECT_THROW(tu3->addRecord(7.2001, 4), LMDBAL::Exist); tu3->addRecord(7.20001, 4.00000001); //not sure how exactly, but it works EXPECT_EQ(tu3->count(), 7); EXPECT_EQ(tu3->getRecord(7.2), -113); float tu3dd = tu3->getRecord(5119); EXPECT_TRUE(tu3ds == tu3dd); EXPECT_EQ(tu3ds, tu3dd); tu4->addRecord(327, 463.28348); tu4->addRecord(327, 79.624923); tu4->addRecord(172, 0.00001); tu4->addRecord(172, 0.00000001); EXPECT_THROW(tu4->addRecord(172, 0.00000001), LMDBAL::Exist); EXPECT_THROW(tu4->addRecord(172, 0.00001), LMDBAL::Exist); EXPECT_THROW(tu4->addRecord(327, 79.624923), LMDBAL::Exist); EXPECT_EQ(tu4->count(), 4); EXPECT_EQ(tu4->getRecord(172), 0.00000001); EXPECT_EQ(tu4->getRecord(327), 463.28348); //since they are not int's they are compared sort of lexicographically tu5->addRecord(-84.7, 45656753); EXPECT_THROW(tu5->addRecord(-84.7, 45656753), LMDBAL::Exist); tu5->addRecord(-84.7, 45656754); int64_t intMax = std::numeric_limits::max(); int64_t intMin = std::numeric_limits::min(); int64_t longMax = std::numeric_limits::max(); int64_t longMin = std::numeric_limits::min(); tu5->addRecord(52.87, intMax); EXPECT_THROW(tu5->addRecord(52.87, intMax), LMDBAL::Exist); tu5->addRecord(52.87, intMin); EXPECT_THROW(tu5->addRecord(52.87, intMin), LMDBAL::Exist); tu5->addRecord(52.87, longMax); EXPECT_THROW(tu5->addRecord(52.87, longMax), LMDBAL::Exist); tu5->addRecord(52.87, longMin); EXPECT_THROW(tu5->addRecord(52.87, longMin), LMDBAL::Exist); EXPECT_EQ(tu5->count(), 6); EXPECT_EQ(tu5->getRecord(-84.7), 45656753); EXPECT_EQ(tu5->getRecord(52.87), intMax); } TEST_F(DuplicatesTest, Forcing) { LMDBAL::SizeType tu1Size = tu1->count(); tu1->addRecord(-56, 71); tu1->addRecord(-56, 274); tu1->addRecord(-56, 732); EXPECT_EQ(tu1->count(), tu1Size += 3); EXPECT_TRUE(tu1->forceRecord(-56, 322)); EXPECT_EQ(tu1->count(), tu1Size += 1); EXPECT_EQ(tu1->getRecord(-56), 274); //like yeah, it's really counterintuitive, since it's compared byte by byte EXPECT_TRUE(tu1->forceRecord(-56, 14)); EXPECT_EQ(tu1->count(), tu1Size += 1); EXPECT_EQ(tu1->getRecord(-56), 14); EXPECT_FALSE(tu1->forceRecord(-56, 274)); EXPECT_EQ(tu1->count(), tu1Size); LMDBAL::SizeType tu2Size = tu2->count(); tu2->addRecord("printable", -2); tu2->addRecord("printable", 4); EXPECT_EQ(tu2->count(), tu2Size += 2); EXPECT_TRUE(tu2->forceRecord("printable", 18)); EXPECT_EQ(tu2->count(), tu2Size += 1); EXPECT_EQ(tu2->getRecord("printable"), 4); EXPECT_TRUE(tu2->forceRecord("printable", 3)); EXPECT_EQ(tu2->count(), tu2Size += 1); EXPECT_EQ(tu2->getRecord("printable"), 3); EXPECT_FALSE(tu2->forceRecord("printable", 4)); EXPECT_EQ(tu2->count(), tu2Size); LMDBAL::SizeType tu3Size = tu3->count(); tu3->addRecord(17.3, 93.21); tu3->addRecord(17.3, 6.6); tu3->addRecord(17.3, 105.1); EXPECT_EQ(tu3->count(), tu3Size += 3); EXPECT_TRUE(tu3->forceRecord(17.3, 74.9)); EXPECT_EQ(tu3->count(), tu3Size += 1); EXPECT_EQ(tu3->getRecord(17.3), 105.1f); //here too, really one should not use this function with duplicates, EXPECT_TRUE(tu3->forceRecord(17.3, 5.1)); //unless he wishes for kinda randomish result EXPECT_EQ(tu3->count(), tu3Size += 1); EXPECT_EQ(tu3->getRecord(17.3), 5.1f); EXPECT_FALSE(tu3->forceRecord(17.3, 93.21)); EXPECT_EQ(tu3->count(), tu3Size); LMDBAL::SizeType tu4Size = tu4->count(); tu4->addRecord(84, -359.109); tu4->addRecord(84, 2879.654); EXPECT_EQ(tu4->count(), tu4Size += 2); EXPECT_TRUE(tu4->forceRecord(84, 72.9)); EXPECT_EQ(tu4->count(), tu4Size += 1); EXPECT_EQ(tu4->getRecord(84), 2879.654); EXPECT_TRUE(tu4->forceRecord(84, 2679.5)); EXPECT_EQ(tu4->count(), tu4Size += 1); EXPECT_EQ(tu4->getRecord(84), 2679.5); EXPECT_FALSE(tu4->forceRecord(84, -359.109)); EXPECT_EQ(tu4->count(), tu4Size); LMDBAL::SizeType tu5Size = tu5->count(); tu5->addRecord(0.45, -85645); tu5->addRecord(0.45, 10573); tu5->addRecord(0.45, 573); tu5->addRecord(0.45, 73285); EXPECT_EQ(tu5->count(), tu5Size += 4); EXPECT_TRUE(tu5->forceRecord(0.45, -473)); EXPECT_EQ(tu5->count(), tu5Size += 1); EXPECT_EQ(tu5->getRecord(0.45), 573); EXPECT_TRUE(tu5->forceRecord(0.45, 394)); EXPECT_EQ(tu5->count(), tu5Size += 1); EXPECT_EQ(tu5->getRecord(0.45), 394); EXPECT_FALSE(tu5->forceRecord(0.45, 10573)); EXPECT_EQ(tu5->count(), tu5Size); } TEST_F(DuplicatesTest, Changing) { LMDBAL::SizeType tu1Size = tu1->count(); EXPECT_THROW(tu1->changeRecord(-31, 53), LMDBAL::NotFound); EXPECT_EQ(tu1->count(), tu1Size); tu1->addRecord(-31, 53); EXPECT_EQ(tu1->count(), tu1Size += 1); EXPECT_EQ(tu1->getRecord(-31), 53); tu1->changeRecord(-31, 53); //should just do nothing usefull, but work normally EXPECT_EQ(tu1->getRecord(-31), 53); tu1->changeRecord(-31, 19); EXPECT_EQ(tu1->count(), tu1Size); EXPECT_EQ(tu1->getRecord(-31), 19); tu1->addRecord(-31, 60); EXPECT_EQ(tu1->count(), tu1Size += 1); EXPECT_EQ(tu1->getRecord(-31), 19); tu1->changeRecord(-31, 16); EXPECT_EQ(tu1->count(), tu1Size); EXPECT_EQ(tu1->getRecord(-31), 16); tu1->changeRecord(-31, 203); EXPECT_EQ(tu1->count(), tu1Size); EXPECT_EQ(tu1->getRecord(-31), 60); EXPECT_THROW(tu1->changeRecord(-31, 203), LMDBAL::Exist); LMDBAL::SizeType tu2Size = tu2->count(); EXPECT_THROW(tu2->changeRecord("jeremy spins", -5), LMDBAL::NotFound); EXPECT_EQ(tu2->count(), tu2Size); tu2->addRecord("jeremy spins", -5); EXPECT_EQ(tu2->count(), tu2Size += 1); EXPECT_EQ(tu2->getRecord("jeremy spins"), -5); tu2->changeRecord("jeremy spins", -5); //should just do nothing usefull, but work normally EXPECT_EQ(tu2->getRecord("jeremy spins"), -5); tu2->changeRecord("jeremy spins", 11); EXPECT_EQ(tu2->count(), tu2Size); EXPECT_EQ(tu2->getRecord("jeremy spins"), 11); tu2->addRecord("jeremy spins", 24); EXPECT_EQ(tu2->count(), tu2Size += 1); EXPECT_EQ(tu2->getRecord("jeremy spins"), 11); tu2->changeRecord("jeremy spins", 4); EXPECT_EQ(tu2->count(), tu2Size); EXPECT_EQ(tu2->getRecord("jeremy spins"), 4); tu2->changeRecord("jeremy spins", -7); EXPECT_EQ(tu2->count(), tu2Size); EXPECT_EQ(tu2->getRecord("jeremy spins"), 24); //cuz it's compared as usigned down there EXPECT_THROW(tu2->changeRecord("jeremy spins", -7), LMDBAL::Exist); LMDBAL::SizeType tu3Size = tu3->count(); EXPECT_THROW(tu3->changeRecord(26.7, 68.22), LMDBAL::NotFound); EXPECT_EQ(tu3->count(), tu3Size); tu3->addRecord(26.7, 68.22); EXPECT_EQ(tu3->count(), tu3Size += 1); EXPECT_EQ(tu3->getRecord(26.7), 68.22f); tu3->changeRecord(26.7, 68.22); //should just do nothing usefull, but work normally EXPECT_EQ(tu3->getRecord(26.7), 68.22f); tu3->changeRecord(26.7, 23.18); EXPECT_EQ(tu3->count(), tu3Size); EXPECT_EQ(tu3->getRecord(26.7), 23.18f); tu3->addRecord(26.7, 22.16); EXPECT_EQ(tu3->count(), tu3Size += 1); EXPECT_EQ(tu3->getRecord(26.7), 23.18f); tu3->changeRecord(26.7, 21.7); EXPECT_EQ(tu3->count(), tu3Size); EXPECT_EQ(tu3->getRecord(26.7), 21.7f); tu3->changeRecord(26.7, 54.33); EXPECT_EQ(tu3->count(), tu3Size); EXPECT_EQ(tu3->getRecord(26.7), 22.16f); EXPECT_THROW(tu3->changeRecord(26.7, 54.33), LMDBAL::Exist); LMDBAL::SizeType tu4Size = tu4->count(); EXPECT_THROW(tu4->changeRecord(852, 6795.349), LMDBAL::NotFound); EXPECT_EQ(tu4->count(), tu4Size); tu4->addRecord(852, 6795.349); EXPECT_EQ(tu4->count(), tu4Size += 1); EXPECT_EQ(tu4->getRecord(852), 6795.349); tu4->changeRecord(852, 6795.349); //should just do nothing usefull, but work normally EXPECT_EQ(tu4->getRecord(852), 6795.349); tu4->changeRecord(852, 13.54); EXPECT_EQ(tu4->count(), tu4Size); EXPECT_EQ(tu4->getRecord(852), 13.54); tu4->addRecord(852, 213.85); EXPECT_EQ(tu4->count(), tu4Size += 1); EXPECT_EQ(tu4->getRecord(852), 13.54); tu4->changeRecord(852, 236.21); EXPECT_EQ(tu4->count(), tu4Size); EXPECT_EQ(tu4->getRecord(852), 236.21); tu4->changeRecord(852, 46324.1135); EXPECT_EQ(tu4->count(), tu4Size); EXPECT_EQ(tu4->getRecord(852), 213.85); EXPECT_THROW(tu4->changeRecord(852, 46324.1135), LMDBAL::Exist); } TEST_F(DuplicatesTest, GettingAllRecords) { LMDBAL::Transaction txn = db->beginReadOnlyTransaction(); bool cycle; LMDBAL::SizeType iterations; std::map m1; std::set k1; LMDBAL::Cursor c1 = tu1->createCursor(); tu1->readAll(m1, txn); c1.open(txn); cycle = false; iterations = 0; do { try { std::pair pair = c1.next(); cycle = true; std::pair::const_iterator, bool> probe = k1.insert(pair.first); if (probe.second) { uint16_t valueAll = m1.at(pair.first); uint16_t valueGet; EXPECT_NO_THROW(tu1->getRecord(pair.first, valueGet, txn)); EXPECT_EQ(valueAll, valueGet); } ++iterations; } catch (const LMDBAL::NotFound& e) { cycle = false; } } while (cycle); EXPECT_EQ(iterations, tu1->count(txn)); EXPECT_EQ(k1.size(), m1.size()); EXPECT_NE(iterations, 0); EXPECT_NE(k1.size(), 0); c1.drop(); std::map m2; std::set k2; LMDBAL::Cursor c2 = tu2->createCursor(); tu2->readAll(m2, txn); c2.open(txn); cycle = false; iterations = 0; do { try { std::pair pair = c2.next(); cycle = true; std::pair::const_iterator, bool> probe = k2.insert(pair.first); if (probe.second) { int8_t valueAll = m2.at(pair.first); int8_t valueGet; EXPECT_NO_THROW(tu2->getRecord(pair.first, valueGet, txn)); EXPECT_EQ(valueAll, valueGet); } ++iterations; } catch (const LMDBAL::NotFound& e) { cycle = false; } } while (cycle); EXPECT_EQ(iterations, tu2->count(txn)); EXPECT_EQ(k2.size(), m2.size()); EXPECT_NE(iterations, 0); EXPECT_NE(k2.size(), 0); c2.drop(); std::map m3; std::set k3; LMDBAL::Cursor c3 = tu3->createCursor(); tu3->readAll(m3, txn); c3.open(txn); cycle = false; iterations = 0; do { try { std::pair pair = c3.next(); cycle = true; std::pair::const_iterator, bool> probe = k3.insert(pair.first); if (probe.second) { float valueAll = m3.at(pair.first); float valueGet; EXPECT_NO_THROW(tu3->getRecord(pair.first, valueGet, txn)); EXPECT_EQ(valueAll, valueGet); } ++iterations; } catch (const LMDBAL::NotFound& e) { cycle = false; } } while (cycle); EXPECT_EQ(iterations, tu3->count(txn)); EXPECT_EQ(k3.size(), m3.size()); EXPECT_NE(iterations, 0); EXPECT_NE(k3.size(), 0); c3.drop(); std::map m4; std::set k4; LMDBAL::Cursor c4 = tu4->createCursor(); tu4->readAll(m4, txn); c4.open(txn); cycle = false; iterations = 0; do { try { std::pair pair = c4.next(); cycle = true; std::pair::const_iterator, bool> probe = k4.insert(pair.first); if (probe.second) { double valueAll = m4.at(pair.first); double valueGet; EXPECT_NO_THROW(tu4->getRecord(pair.first, valueGet, txn)); EXPECT_EQ(valueAll, valueGet); } ++iterations; } catch (const LMDBAL::NotFound& e) { cycle = false; } } while (cycle); c4.drop(); EXPECT_EQ(iterations, tu4->count(txn)); EXPECT_EQ(k4.size(), m4.size()); EXPECT_NE(iterations, 0); EXPECT_NE(k4.size(), 0); txn.terminate(); }