From a4bb7e6269df1906a5ed0818fa25246ec39ecbe5 Mon Sep 17 00:00:00 2001 From: blue Date: Sat, 1 Apr 2023 17:45:20 +0300 Subject: [PATCH] a method to get the size of the storage with opened transaction, tests for readAll, and some test for transactions --- src/storage.cpp | 28 +++++---- src/storage.h | 7 ++- test/CMakeLists.txt | 1 + test/basic.cpp | 35 ++++++++++-- test/serialization.cpp | 8 +-- test/storagetransaction.cpp | 111 ++++++++++++++++++++++++++++++++++++ 6 files changed, 168 insertions(+), 22 deletions(-) create mode 100644 test/storagetransaction.cpp diff --git a/src/storage.cpp b/src/storage.cpp index 1823f44..b28afc3 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -59,25 +59,31 @@ void LMDBAL::iStorage::ensureOpened(const std::string& methodName) const { throw Closed(methodName, db->name, name); } -uint32_t LMDBAL::iStorage::count() const { +LMDBAL::SizeType LMDBAL::iStorage::count() const { ensureOpened(countMethodName); - MDB_txn *txn; + TransactionID txn = beginReadOnlyTransaction(); + SizeType amount; + try { + amount = count(txn); + } catch (...) { + abortTransaction(txn); + throw; + } + abortTransaction(txn); + + return amount; +} + +LMDBAL::SizeType LMDBAL::iStorage::count(TransactionID txn) const { MDB_stat stat; - int rc = mdb_txn_begin(db->environment, NULL, MDB_RDONLY, &txn); + int rc = mdb_stat(txn, dbi, &stat); if (rc) { mdb_txn_abort(txn); throw Unknown(db->name, mdb_strerror(rc), name); } - rc = mdb_stat(txn, dbi, &stat); - if (rc) { - mdb_txn_abort(txn); - throw Unknown(db->name, mdb_strerror(rc), name); - } - uint32_t amount = stat.ms_entries; - mdb_txn_abort(txn); - return amount; + return stat.ms_entries; } void LMDBAL::iStorage::throwDuplicateOrUnknown(int rc, TransactionID txn, const std::string& key) const { diff --git a/src/storage.h b/src/storage.h index ba7d022..dc00d38 100644 --- a/src/storage.h +++ b/src/storage.h @@ -24,8 +24,12 @@ namespace LMDBAL { +typedef uint32_t SizeType; + class iStorage { friend class Base; +public: + protected: iStorage(const std::string& name, Base* parent); virtual ~iStorage(); @@ -48,7 +52,8 @@ protected: public: virtual void drop(); - virtual uint32_t count() const; + virtual SizeType count() const; + virtual SizeType count(TransactionID txn) const; TransactionID beginReadOnlyTransaction() const; TransactionID beginTransaction() const; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d01a810..e961886 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,6 +5,7 @@ include_directories(${GTEST_INCLUDE_DIR}) add_executable(runUnitTests basic.cpp serialization.cpp + storagetransaction.cpp ) target_compile_options(runUnitTests PRIVATE -fPIC) diff --git a/test/basic.cpp b/test/basic.cpp index 509f896..fdef128 100644 --- a/test/basic.cpp +++ b/test/basic.cpp @@ -256,12 +256,12 @@ TEST_F(BaseTest, Change) { TEST_F(BaseTest, Force) { EXPECT_EQ(db->ready(), true); - t1->forceRecord(58, 35); //changing - t1->forceRecord(68, 36); //adding - t2->forceRecord("prophecy", "dumpling"); //adding - t2->forceRecord("lawfirm", "paracetamol"); //changing - c1->forceRecord(89, "canine"); //changing - c1->forceRecord(98, "duration"); //adding + EXPECT_EQ(t1->forceRecord(58, 35), false); //changing + EXPECT_EQ(t1->forceRecord(68, 36), true); //adding + EXPECT_EQ(t2->forceRecord("prophecy", "dumpling"), true); //adding + EXPECT_EQ(t2->forceRecord("lawfirm", "paracetamol"), false); //changing + EXPECT_EQ(c1->forceRecord(89, "canine"), false); //changing + EXPECT_EQ(c1->forceRecord(98, "duration"), true); //adding EXPECT_EQ(t1->getRecord(2), 49); EXPECT_EQ(t1->getRecord(58), 35); @@ -278,3 +278,26 @@ TEST_F(BaseTest, Force) { EXPECT_EQ(t2->count(), 3); EXPECT_EQ(c1->count(), 4); } + +TEST_F(BaseTest, ReadAll) { + EXPECT_EQ(db->ready(), true); + + std::map m1 = t1->readAll(); + std::map m2 = t2->readAll(); + std::map m3 = c1->readAll(); + + EXPECT_EQ(m1.at(2), 49); + EXPECT_EQ(m1.at(58), 35); + EXPECT_EQ(m1.at(68), 36); + EXPECT_EQ(m2.at("sdfhga"), "void"); + EXPECT_EQ(m2.at("prophecy"), "dumpling"); + EXPECT_EQ(m2.at("lawfirm"), "paracetamol"); + EXPECT_EQ(m3.at(15), "recording"); + EXPECT_EQ(m3.at(12), "thermal"); + EXPECT_EQ(m3.at(89), "canine"); + EXPECT_EQ(m3.at(98), "duration"); + + EXPECT_EQ(m1.size(), 3); + EXPECT_EQ(m2.size(), 3); + EXPECT_EQ(m3.size(), 4); +} diff --git a/test/serialization.cpp b/test/serialization.cpp index 1d7d0b3..b413d42 100644 --- a/test/serialization.cpp +++ b/test/serialization.cpp @@ -19,11 +19,11 @@ TEST(Serialization, Double) { double destination; serializer.deserialize(data, destination); - EXPECT_EQ(source, destination); + EXPECT_DOUBLE_EQ(source, destination); double dest2 = serializer.deserialize(data); - EXPECT_EQ(source, dest2); + EXPECT_DOUBLE_EQ(source, dest2); } TEST(Serialization, Float) { @@ -42,11 +42,11 @@ TEST(Serialization, Float) { float destination; serializer.deserialize(data, destination); - EXPECT_EQ(source, destination); + EXPECT_FLOAT_EQ(source, destination); float dest2 = serializer.deserialize(data); - EXPECT_EQ(source, dest2); + EXPECT_FLOAT_EQ(source, dest2); } TEST(Serialization, Int8) { diff --git a/test/storagetransaction.cpp b/test/storagetransaction.cpp new file mode 100644 index 0000000..294c1d2 --- /dev/null +++ b/test/storagetransaction.cpp @@ -0,0 +1,111 @@ +#include + +#include "base.h" +#include "storage.h" + +class StorageTransactionsTest : public testing::Test { +protected: + StorageTransactionsTest(): + testing::Test(), + t1(db->getStorage("table1")), + t2(db->getStorage("table2")) {} + + ~StorageTransactionsTest() {} + + static void SetUpTestSuite() { + if (db == nullptr) { + db = new LMDBAL::Base("storageTrnansactionsTestBase"); + db->addStorage("table1"); + db->addStorage("table2"); + } + + db->open(); + } + + static void TearDownTestSuite() { + db->close(); + db->removeDirectory(); + delete db; + db = nullptr; + } + + static LMDBAL::Base* db; + + LMDBAL::Storage* t1; + LMDBAL::Storage* t2; +}; + + +LMDBAL::Base* StorageTransactionsTest::db = nullptr; + +TEST_F(StorageTransactionsTest, Adding) { + EXPECT_EQ(db->ready(), true); + EXPECT_EQ(t1->count(), 0); + EXPECT_EQ(t2->count(), 0); + + LMDBAL::TransactionID txn = db->beginTransaction(); + t1->addRecord(5, 13, txn); + t1->addRecord(-53, 782, txn); + t1->addRecord(58392, -37829, txn); + + t2->addRecord("lorem", 481, txn); + t2->addRecord("decallence", 8532.48, txn); + t2->addRecord("prevent recovery", -64.64, txn); + + EXPECT_EQ(t1->count(), 0); + EXPECT_EQ(t2->count(), 0); + + db->commitTransaction(txn); + + EXPECT_EQ(t1->count(), 3); + EXPECT_EQ(t1->getRecord(5), 13); + EXPECT_EQ(t1->getRecord(-53), 782); + EXPECT_EQ(t1->getRecord(58392), -37829); + + EXPECT_EQ(t2->count(), 3); + EXPECT_FLOAT_EQ(t2->getRecord("lorem"), 481); + EXPECT_FLOAT_EQ(t2->getRecord("decallence"), 8532.48); + EXPECT_FLOAT_EQ(t2->getRecord("prevent recovery"), -64.64); +} + +TEST_F(StorageTransactionsTest, Aborting) { + EXPECT_EQ(db->ready(), true); + + LMDBAL::SizeType s1 = t1->count(); + LMDBAL::SizeType s2 = t2->count(); + + LMDBAL::TransactionID txn = t1->beginTransaction(); + t1->addRecord(18, 40, txn); + t1->addRecord(85, -4, txn); + t1->addRecord(-5, -3, txn); + + t2->addRecord("tapestry", .053, txn); + t2->addRecord("pepper plants are beautifull", -7, txn); + t2->addRecord("horrots", -23.976, txn); + + EXPECT_EQ(t1->count(), s1); + EXPECT_EQ(t2->count(), s2); + + t1->abortTransaction(txn); + + EXPECT_EQ(t1->count(), s1); + EXPECT_EQ(t2->count(), s2); +} + +TEST_F(StorageTransactionsTest, Reading) { + EXPECT_EQ(db->ready(), true); + + LMDBAL::TransactionID txn = db->beginReadOnlyTransaction(); + + EXPECT_EQ(t1->count(txn), 3); + EXPECT_EQ(t1->getRecord(5, txn), 13); + EXPECT_EQ(t1->getRecord(-53, txn), 782); + EXPECT_EQ(t1->getRecord(58392, txn), -37829); + + EXPECT_EQ(t2->count(txn), 3); + EXPECT_FLOAT_EQ(t2->getRecord("lorem", txn), 481); + EXPECT_FLOAT_EQ(t2->getRecord("decallence", txn), 8532.48); + EXPECT_FLOAT_EQ(t2->getRecord("prevent recovery", txn), -64.64); + + db->abortTransaction(txn); +}