#include #include "base.h" #include "storage.h" #include "cursor.h" class StorageCursorTest : public ::testing::Test { protected: StorageCursorTest(): ::testing::Test(), table (db->getStorage("table1")), emptyTable (db->getStorage("empty")) {} ~StorageCursorTest() {} static void SetUpTestSuite() { if (db == nullptr) { db = new LMDBAL::Base("testBase"); db->addStorage("table1"); db->addStorage("empty"); db->open(); } } static void TearDownTestSuite() { transaction.terminate(); db->close(); db->removeDirectory(); delete db; db = nullptr; cursor = nullptr; emptyCursor = nullptr; } static LMDBAL::Base* db; static LMDBAL::Cursor* cursor; static LMDBAL::Cursor* emptyCursor; static LMDBAL::Transaction transaction; LMDBAL::Storage* table; LMDBAL::Storage* emptyTable; }; LMDBAL::Base* StorageCursorTest::db = nullptr; LMDBAL::Cursor* StorageCursorTest::cursor = nullptr; LMDBAL::Cursor* StorageCursorTest::emptyCursor = nullptr; LMDBAL::Transaction StorageCursorTest::transaction = LMDBAL::Transaction(); static const std::map data({ {245665783, "bothering nerds"}, {3458, "resilent pick forefront"}, {105190, "apportunity legal bat"}, {6510, "outside"}, {7438537, "damocles plush apparently rusty"}, {19373572, "local guidence"}, {138842, "forgetting tusks prepare"}, {981874, "butchered soaking pawn"}, {19302, "tanned inmate"}, {178239, "custody speaks neurotic"}, }); TEST_F(StorageCursorTest, PopulatingTheTable) { uint32_t amount = table->addRecords(data); EXPECT_EQ(amount, data.size()); } TEST_F(StorageCursorTest, Creation) { cursor = table->createCursor(); emptyCursor = emptyTable->createCursor(); EXPECT_THROW(cursor->first(), LMDBAL::CursorNotReady); EXPECT_THROW(cursor->last(), LMDBAL::CursorNotReady); EXPECT_THROW(cursor->next(), LMDBAL::CursorNotReady); EXPECT_THROW(cursor->prev(), LMDBAL::CursorNotReady); EXPECT_THROW(cursor->current(), LMDBAL::CursorNotReady); cursor->open(); } TEST_F(StorageCursorTest, FirstPrivate) { std::pair element = cursor->first(); std::map::const_iterator reference = data.begin(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } TEST_F(StorageCursorTest, NextPrivate) { std::map::const_iterator reference = data.begin(); reference++; for (; reference != data.end(); ++reference) { std::pair element = cursor->next(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } EXPECT_THROW(cursor->next(), LMDBAL::NotFound); std::pair element = cursor->first(); reference = data.begin(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } TEST_F(StorageCursorTest, LastPrivate) { std::pair element = cursor->last(); std::map::const_reverse_iterator reference = data.rbegin(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } TEST_F(StorageCursorTest, PrevPrivate) { std::map::const_reverse_iterator reference = data.rbegin(); reference++; for (; reference != data.rend(); ++reference) { std::pair element = cursor->prev(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } EXPECT_THROW(cursor->prev(), LMDBAL::NotFound); std::pair element = cursor->last(); reference = data.rbegin(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } TEST_F(StorageCursorTest, CurrentPrivate) { std::pair element = cursor->first(); std::map::const_iterator reference = data.begin(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); element = cursor->current(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); cursor->next(); element = cursor->current(); ++reference; EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); cursor->next(); cursor->next(); cursor->prev(); element = cursor->current(); ++reference; ++reference; --reference; EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } TEST_F(StorageCursorTest, Destruction) { cursor->close(); EXPECT_THROW(cursor->first(), LMDBAL::CursorNotReady); EXPECT_THROW(cursor->last(), LMDBAL::CursorNotReady); EXPECT_THROW(cursor->next(), LMDBAL::CursorNotReady); EXPECT_THROW(cursor->prev(), LMDBAL::CursorNotReady); EXPECT_THROW(cursor->current(), LMDBAL::CursorNotReady); EXPECT_THROW(emptyTable->destroyCursor(cursor), LMDBAL::Unknown); table->destroyCursor(cursor); cursor = table->createCursor(); } TEST_F(StorageCursorTest, FirstPublic) { transaction = db->beginReadOnlyTransaction(); cursor->open(transaction); std::pair element = cursor->first(); std::map::const_iterator reference = data.begin(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } TEST_F(StorageCursorTest, NextPublic) { std::map::const_iterator reference = data.begin(); reference++; for (; reference != data.end(); ++reference) { std::pair element = cursor->next(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } EXPECT_THROW(cursor->next(), LMDBAL::NotFound); std::pair element = cursor->first(); reference = data.begin(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } TEST_F(StorageCursorTest, LastPublic) { std::pair element = cursor->last(); std::map::const_reverse_iterator reference = data.rbegin(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } TEST_F(StorageCursorTest, PrevPublic) { std::map::const_reverse_iterator reference = data.rbegin(); reference++; for (; reference != data.rend(); ++reference) { std::pair element = cursor->prev(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } EXPECT_THROW(cursor->prev(), LMDBAL::NotFound); std::pair element = cursor->last(); reference = data.rbegin(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } TEST_F(StorageCursorTest, CurrentPublic) { std::pair element = cursor->first(); std::map::const_iterator reference = data.begin(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); element = cursor->current(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); cursor->next(); element = cursor->current(); ++reference; EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); cursor->next(); cursor->next(); cursor->prev(); element = cursor->current(); ++reference; ++reference; --reference; EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); } TEST_F(StorageCursorTest, CornerCases) { transaction.terminate(); EXPECT_THROW(cursor->current(), LMDBAL::Unknown); cursor->close(); emptyCursor->open(); EXPECT_THROW(emptyCursor->first(), LMDBAL::NotFound); EXPECT_THROW(emptyCursor->last(), LMDBAL::NotFound); EXPECT_THROW(emptyCursor->next(), LMDBAL::NotFound); EXPECT_THROW(emptyCursor->prev(), LMDBAL::NotFound); EXPECT_THROW(emptyCursor->current(), LMDBAL::Unknown); emptyCursor->close(); cursor->open(); EXPECT_THROW(cursor->current(), LMDBAL::Unknown); //yeah, nice thing to write in the doc std::map::const_reverse_iterator breference = data.rbegin(); std::pair element(cursor->prev()); EXPECT_EQ(element.first, breference->first); //nice thing to write in the doc, again! EXPECT_EQ(element.second, breference->second); element = cursor->current(); EXPECT_EQ(element.first, breference->first); EXPECT_EQ(element.second, breference->second); EXPECT_THROW(cursor->next(), LMDBAL::NotFound); cursor->close(); cursor->open(); element = cursor->next(); std::map::const_iterator reference = data.begin(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); element = cursor->current(); EXPECT_EQ(element.first, reference->first); EXPECT_EQ(element.second, reference->second); EXPECT_THROW(cursor->prev(), LMDBAL::NotFound); }