From 2f34fa69e8714f5df07a88f5169e8d93dc2110be Mon Sep 17 00:00:00 2001 From: blue Date: Sat, 17 Sep 2022 15:31:58 +0300 Subject: [PATCH] some more primitive specializations, counting rows, dropping tables, tests --- CMakeLists.txt | 8 +++ database.cpp | 24 ++++++++- database.h | 3 +- exceptions.cpp | 23 ++++---- exceptions.h | 8 +-- serializer.h | 8 +++ serializer_double.hpp | 53 ++++++++++++++++++ serializer_float.hpp | 53 ++++++++++++++++++ serializer_int16.hpp | 50 +++++++++++++++++ serializer_int32.hpp | 53 ++++++++++++++++++ serializer_int64.hpp | 53 ++++++++++++++++++ serializer_int8.hpp | 53 ++++++++++++++++++ serializer_qstring.hpp | 58 ++++++++++++++++++++ serializer_stdstring.hpp | 54 +++++++++++++++++++ serializer_uint16.hpp | 2 +- serializer_uint32.hpp | 2 +- serializer_uint64.hpp | 2 +- serializer_uint8.hpp | 2 +- table.cpp | 43 +++++++++++++++ table.h | 11 +++- table.hpp | 20 +++++++ test/basic.cpp | 112 ++++++++++++++++++++++++++++++++++++--- 22 files changed, 667 insertions(+), 28 deletions(-) create mode 100644 serializer_double.hpp create mode 100644 serializer_float.hpp create mode 100644 serializer_int16.hpp create mode 100644 serializer_int32.hpp create mode 100644 serializer_int64.hpp create mode 100644 serializer_int8.hpp create mode 100644 serializer_qstring.hpp create mode 100644 serializer_stdstring.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d9702c4..1cd7f21 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,14 @@ set(HEADERS serializer_uint16.hpp serializer_uint32.hpp serializer_uint64.hpp + serializer_int8.hpp + serializer_int16.hpp + serializer_int32.hpp + serializer_int64.hpp + serializer_float.hpp + serializer_double.hpp + serializer_stdstring.hpp + serializer_qstring.hpp ) if (BUILD_STATIC) diff --git a/database.cpp b/database.cpp index 78351a2..8904bf7 100644 --- a/database.cpp +++ b/database.cpp @@ -85,7 +85,7 @@ void DataBase::open() bool DataBase::removeDirectory() { if (opened) { - throw Opened(name, ""); + throw Opened(name, "remove database directory"); } QString path(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)); path += "/" + getName(); @@ -108,3 +108,25 @@ bool DataBase::ready() const return opened; } +void DataBase::drop() +{ + if (!opened) { + throw Closed("drop", name); + } + + MDB_txn *txn; + int rc = mdb_txn_begin(environment, NULL, 0, &txn); + if (rc) { + throw Unknown(name, mdb_strerror(rc)); + } + for (const std::pair& pair : tables) { + rc = pair.second->drop(txn); + if (rc) { + throw Unknown(name, mdb_strerror(rc), pair.first); + } + } + + mdb_txn_commit(txn); +} + + diff --git a/database.h b/database.h index 9872ecb..167fc95 100644 --- a/database.h +++ b/database.h @@ -42,6 +42,7 @@ public: bool ready() const; bool removeDirectory(); QString getName() const; + void drop(); template Table* addTable(const std::string& name); @@ -72,7 +73,7 @@ private: template DataBase::Table* DataBase::addTable(const std::string& p_name) { if (opened) { - throw Opened(name, p_name); + throw Opened(name, "add table " + p_name); } DataBase::Table* table = new DataBase::Table(p_name, this); tables.insert(std::make_pair(p_name, (_Table*)table)); diff --git a/exceptions.cpp b/exceptions.cpp index a210372..086649e 100644 --- a/exceptions.cpp +++ b/exceptions.cpp @@ -38,7 +38,7 @@ std::string DataBase::Directory::getMessage() const { DataBase::Closed::Closed( const std::string& p_operation, const std::string& p_dbName, - const std::string& p_tableName + const std::optional& p_tableName ): Exception(), operation(p_operation), @@ -46,22 +46,25 @@ DataBase::Closed::Closed( tableName(p_tableName) {} std::string DataBase::Closed::getMessage() const { - return "An attempt to perform operation " + operation - + " on closed database " + dbName - + " on table " + tableName; + std::string msg = "An attempt to perform operation " + operation + + " on closed database " + dbName; + if (tableName.has_value()) { + msg += + " on table " + tableName.value(); + } + return msg; + } -DataBase::Opened::Opened(const std::string& p_dbName, const std::string& p_tableName): +DataBase::Opened::Opened(const std::string& p_dbName, const std::string& p_action): Exception(), dbName(p_dbName), - tableName(p_tableName) {} + action(p_action) {} std::string DataBase::Opened::getMessage() const { - return "An attempt to add table " + tableName - + " to the database " + dbName - + " but it's can't be done because the DataBase is already opened." - + " Please add all tables before opening DataBase."; + return "An attempt to " + action + + " (the database " + dbName + + ") but it's can't be done because the DataBase is already opened"; } DataBase::NotFound::NotFound( diff --git a/exceptions.h b/exceptions.h index bdfd62a..2d06535 100644 --- a/exceptions.h +++ b/exceptions.h @@ -43,23 +43,23 @@ private: class DataBase::Closed : public DataBase::Exception { public: - Closed(const std::string& p_operation, const std::string& dbName, const std::string& tableName); + Closed(const std::string& p_operation, const std::string& dbName, const std::optional& tableName = std::nullopt); std::string getMessage() const; private: std::string operation; std::string dbName; - std::string tableName; + std::optional tableName; }; class DataBase::Opened : public DataBase::Exception { public: - Opened(const std::string& dbName, const std::string& tableName); + Opened(const std::string& dbName, const std::string& action); std::string getMessage() const; private: std::string dbName; - std::string tableName; + std::string action; }; class DataBase::NotFound : public DataBase::Exception { diff --git a/serializer.h b/serializer.h index 1adbabc..82f9880 100644 --- a/serializer.h +++ b/serializer.h @@ -51,5 +51,13 @@ private: #include "serializer_uint32.hpp" #include "serializer_uint16.hpp" #include "serializer_uint8.hpp" +#include "serializer_int64.hpp" +#include "serializer_int32.hpp" +#include "serializer_int16.hpp" +#include "serializer_int8.hpp" +#include "serializer_float.hpp" +#include "serializer_double.hpp" +#include "serializer_stdstring.hpp" +#include "serializer_qstring.hpp" #endif // CORE_DATABASE_SERIALIZER_H diff --git a/serializer_double.hpp b/serializer_double.hpp new file mode 100644 index 0000000..aaab3b1 --- /dev/null +++ b/serializer_double.hpp @@ -0,0 +1,53 @@ +// Squawk messenger. +// Copyright (C) 2019 Yury Gubich +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + + +#ifndef CORE_DATABASE_SERIALIZER_DOUBLE_HPP +#define CORE_DATABASE_SERIALIZER_DOUBLE_HPP + +template<> +class DataBase::Serializer +{ +public: + Serializer():value(0) {}; + Serializer(const double& p_value):value(p_value) {}; + ~Serializer() {}; + + double deserialize(const MDB_val& data) { + std::memcpy(&value, data.mv_data, 8); + return value; + }; + MDB_val setData(const double& data) { + value = data; + return getData(); + }; + MDB_val getData() { + MDB_val result; + result.mv_data = &value; + result.mv_size = 8; + return result; + }; + void clear() {}; //not possible; + +private: + double value; +}; + + +#endif //CORE_DATABASE_SERIALIZER_DOUBLE_HPP + + + diff --git a/serializer_float.hpp b/serializer_float.hpp new file mode 100644 index 0000000..6a79946 --- /dev/null +++ b/serializer_float.hpp @@ -0,0 +1,53 @@ +// Squawk messenger. +// Copyright (C) 2019 Yury Gubich +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + + +#ifndef CORE_DATABASE_SERIALIZER_FLOAT_HPP +#define CORE_DATABASE_SERIALIZER_FLOAT_HPP + +template<> +class DataBase::Serializer +{ +public: + Serializer():value(0) {}; + Serializer(const float& p_value):value(p_value) {}; + ~Serializer() {}; + + float deserialize(const MDB_val& data) { + std::memcpy(&value, data.mv_data, 4); + return value; + }; + MDB_val setData(const float& data) { + value = data; + return getData(); + }; + MDB_val getData() { + MDB_val result; + result.mv_data = &value; + result.mv_size = 4; + return result; + }; + void clear() {}; //not possible; + +private: + float value; +}; + + +#endif //CORE_DATABASE_SERIALIZER_FLOAT_HPP + + + diff --git a/serializer_int16.hpp b/serializer_int16.hpp new file mode 100644 index 0000000..380b184 --- /dev/null +++ b/serializer_int16.hpp @@ -0,0 +1,50 @@ +// Squawk messenger. +// Copyright (C) 2019 Yury Gubich +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + + +#ifndef CORE_DATABASE_SERIALIZER_INT16_HPP +#define CORE_DATABASE_SERIALIZER_INT16_HPP + +template<> +class DataBase::Serializer +{ +public: + Serializer():value(0) {}; + Serializer(const int16_t& p_value):value(p_value) {}; + ~Serializer() {}; + + int16_t deserialize(const MDB_val& data) { + std::memcpy(&value, data.mv_data, 2); + return value; + }; + MDB_val setData(const int16_t& data) { + value = data; + return getData(); + }; + MDB_val getData() { + MDB_val result; + result.mv_data = &value; + result.mv_size = 2; + return result; + }; + void clear() {}; //not possible; + +private: + int16_t value; +}; + + +#endif //CORE_DATABASE_SERIALIZER_INT16_HPP diff --git a/serializer_int32.hpp b/serializer_int32.hpp new file mode 100644 index 0000000..da89324 --- /dev/null +++ b/serializer_int32.hpp @@ -0,0 +1,53 @@ +// Squawk messenger. +// Copyright (C) 2019 Yury Gubich +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + + +#ifndef CORE_DATABASE_SERIALIZER_INT32_HPP +#define CORE_DATABASE_SERIALIZER_INT32_HPP + +template<> +class DataBase::Serializer +{ +public: + Serializer():value(0) {}; + Serializer(const int32_t& p_value):value(p_value) {}; + ~Serializer() {}; + + int32_t deserialize(const MDB_val& data) { + std::memcpy(&value, data.mv_data, 4); + return value; + }; + MDB_val setData(const int32_t& data) { + value = data; + return getData(); + }; + MDB_val getData() { + MDB_val result; + result.mv_data = &value; + result.mv_size = 4; + return result; + }; + void clear() {}; //not possible; + +private: + int32_t value; +}; + + +#endif //CORE_DATABASE_SERIALIZER_INT32_HPP + + + diff --git a/serializer_int64.hpp b/serializer_int64.hpp new file mode 100644 index 0000000..d39a368 --- /dev/null +++ b/serializer_int64.hpp @@ -0,0 +1,53 @@ +// Squawk messenger. +// Copyright (C) 2019 Yury Gubich +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + + +#ifndef CORE_DATABASE_SERIALIZER_INT64_HPP +#define CORE_DATABASE_SERIALIZER_INT64_HPP + +template<> +class DataBase::Serializer +{ +public: + Serializer():value(0) {}; + Serializer(const int64_t& p_value):value(p_value) {}; + ~Serializer() {}; + + int64_t deserialize(const MDB_val& data) { + std::memcpy(&value, data.mv_data, 8); + return value; + }; + MDB_val setData(const int64_t& data) { + value = data; + return getData(); + }; + MDB_val getData() { + MDB_val result; + result.mv_data = &value; + result.mv_size = 8; + return result; + }; + void clear() {}; //not possible; + +private: + int64_t value; +}; + + +#endif //CORE_DATABASE_SERIALIZER_INT64_HPP + + + diff --git a/serializer_int8.hpp b/serializer_int8.hpp new file mode 100644 index 0000000..a1e0404 --- /dev/null +++ b/serializer_int8.hpp @@ -0,0 +1,53 @@ +// Squawk messenger. +// Copyright (C) 2019 Yury Gubich +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + + +#ifndef CORE_DATABASE_SERIALIZER_INT8_HPP +#define CORE_DATABASE_SERIALIZER_INT8_HPP + +template<> +class DataBase::Serializer +{ +public: + Serializer():value(0) {}; + Serializer(const int8_t& p_value):value(p_value) {}; + ~Serializer() {}; + + int8_t deserialize(const MDB_val& data) { + std::memcpy(&value, data.mv_data, 1); + return value; + }; + MDB_val setData(const int8_t& data) { + value = data; + return getData(); + }; + MDB_val getData() { + MDB_val result; + result.mv_data = &value; + result.mv_size = 1; + return result; + }; + void clear() {}; //not possible; + +private: + int8_t value; +}; + + +#endif //CORE_DATABASE_SERIALIZER_INT8_HPP + + + diff --git a/serializer_qstring.hpp b/serializer_qstring.hpp new file mode 100644 index 0000000..72c33dd --- /dev/null +++ b/serializer_qstring.hpp @@ -0,0 +1,58 @@ +// Squawk messenger. +// Copyright (C) 2019 Yury Gubich +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + + +#ifndef CORE_DATABASE_SERIALIZER_QSTRING_HPP +#define CORE_DATABASE_SERIALIZER_QSTRING_HPP + +#include +#include + +template<> +class DataBase::Serializer +{ +public: + Serializer():value() {}; + Serializer(const QString& p_value):value(p_value.toUtf8()) {}; + ~Serializer() {}; + + QString deserialize(const MDB_val& data) { + value = QByteArray((char*)data.mv_data, data.mv_size); + return QString::fromUtf8(value); + }; + MDB_val setData(const QString& data) { + value = data.toUtf8(); + return getData(); + }; + MDB_val getData() { + MDB_val result; + result.mv_data = value.data(); + result.mv_size = value.size(); + return result; + }; + void clear() {}; //not possible; + +private: + QByteArray value; +}; + + +#endif //CORE_DATABASE_SERIALIZER_QSTRING_HPP + + + + + diff --git a/serializer_stdstring.hpp b/serializer_stdstring.hpp new file mode 100644 index 0000000..a17a6f1 --- /dev/null +++ b/serializer_stdstring.hpp @@ -0,0 +1,54 @@ +// Squawk messenger. +// Copyright (C) 2019 Yury Gubich +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + + +#ifndef CORE_DATABASE_SERIALIZER_STDSTRING_HPP +#define CORE_DATABASE_SERIALIZER_STDSTRING_HPP + +template<> +class DataBase::Serializer +{ +public: + Serializer():value() {}; + Serializer(const std::string& p_value):value(p_value) {}; + ~Serializer() {}; + + std::string deserialize(const MDB_val& data) { + value = std::string((char*)data.mv_data, data.mv_size); + return value; + }; + MDB_val setData(const std::string& data) { + value = data; + return getData(); + }; + MDB_val getData() { + MDB_val result; + result.mv_data = (char*)value.c_str(); + result.mv_size = value.size(); + return result; + }; + void clear() {}; //not possible; + +private: + std::string value; +}; + + +#endif //CORE_DATABASE_SERIALIZER_STDSTRING_HPP + + + + diff --git a/serializer_uint16.hpp b/serializer_uint16.hpp index 3551de2..b5df796 100644 --- a/serializer_uint16.hpp +++ b/serializer_uint16.hpp @@ -36,7 +36,7 @@ public: }; MDB_val getData() { MDB_val result; - result.mv_data = &value, + result.mv_data = &value; result.mv_size = 2; return result; }; diff --git a/serializer_uint32.hpp b/serializer_uint32.hpp index 7c1832e..590ecb2 100644 --- a/serializer_uint32.hpp +++ b/serializer_uint32.hpp @@ -36,7 +36,7 @@ public: }; MDB_val getData() { MDB_val result; - result.mv_data = &value, + result.mv_data = &value; result.mv_size = 4; return result; }; diff --git a/serializer_uint64.hpp b/serializer_uint64.hpp index 2b19b9d..6edbbb5 100644 --- a/serializer_uint64.hpp +++ b/serializer_uint64.hpp @@ -36,7 +36,7 @@ public: }; MDB_val getData() { MDB_val result; - result.mv_data = &value, + result.mv_data = &value; result.mv_size = 8; return result; }; diff --git a/serializer_uint8.hpp b/serializer_uint8.hpp index 97f76b0..bb1fc7e 100644 --- a/serializer_uint8.hpp +++ b/serializer_uint8.hpp @@ -36,7 +36,7 @@ public: }; MDB_val getData() { MDB_val result; - result.mv_data = &value, + result.mv_data = &value; result.mv_size = 1; return result; }; diff --git a/table.cpp b/table.cpp index ea26110..141df13 100644 --- a/table.cpp +++ b/table.cpp @@ -24,3 +24,46 @@ DataBase::_Table::_Table(const std::string& p_name, DataBase* parent): } DataBase::_Table::~_Table() {} + + +void DataBase::_Table::drop() +{ + if (!db->opened) { + throw Closed("drop", db->name, name); + } + + MDB_txn *txn; + int rc = mdb_txn_begin(db->environment, NULL, 0, &txn); + if (rc) { + throw Unknown(db->name, mdb_strerror(rc), name); + } + rc = drop(txn); + if (rc) { + throw Unknown(db->name, mdb_strerror(rc), name); + } + + mdb_txn_commit(txn); +} + +int DataBase::_Table::drop(MDB_txn* transaction) +{ + return mdb_drop(transaction, dbi, 0); +} + +uint32_t DataBase::_Table::count() const +{ + if (!db->opened) { + throw Closed("count", db->name, name); + } + + MDB_txn *txn; + MDB_stat stat; + int rc = mdb_txn_begin(db->environment, NULL, 0, &txn); + rc = mdb_stat(txn, dbi, &stat); + if (rc) { + throw Unknown(db->name, mdb_strerror(rc), name); + } + uint32_t amount = stat.ms_entries; + mdb_txn_abort(txn); + return amount; +} diff --git a/table.h b/table.h index 0c25231..082518c 100644 --- a/table.h +++ b/table.h @@ -21,12 +21,19 @@ #include "serializer.h" class DataBase::_Table { -public: + friend class DataBase; +protected: _Table(const std::string& name, DataBase* parent); virtual ~_Table(); virtual int createTable(MDB_txn * transaction) = 0; + virtual int drop(MDB_txn * transaction); + public: + virtual void drop(); + virtual uint32_t count() const; + +protected: MDB_dbi dbi; DataBase* db; const std::string name; @@ -40,7 +47,7 @@ protected: }; template -class DataBase::Table : private DataBase::_Table { +class DataBase::Table : public DataBase::_Table { friend class DataBase; private: Table(const std::string& name, DataBase* parent); diff --git a/table.hpp b/table.hpp index 47b135c..8fa315b 100644 --- a/table.hpp +++ b/table.hpp @@ -164,6 +164,26 @@ inline int DataBase::_Table::makeTable(MDB_txn* transaction) { return mdb_dbi_open(transaction, name.c_str(), MDB_CREATE | MDB_INTEGERKEY, &dbi); } +template<> +inline int DataBase::_Table::makeTable(MDB_txn* transaction) { + return mdb_dbi_open(transaction, name.c_str(), MDB_CREATE | MDB_INTEGERKEY, &dbi); +} + +template<> +inline int DataBase::_Table::makeTable(MDB_txn* transaction) { + return mdb_dbi_open(transaction, name.c_str(), MDB_CREATE | MDB_INTEGERKEY, &dbi); +} + +template<> +inline int DataBase::_Table::makeTable(MDB_txn* transaction) { + return mdb_dbi_open(transaction, name.c_str(), MDB_CREATE | MDB_INTEGERKEY, &dbi); +} + +template<> +inline int DataBase::_Table::makeTable(MDB_txn* transaction) { + return mdb_dbi_open(transaction, name.c_str(), MDB_CREATE | MDB_INTEGERKEY, &dbi); +} + template inline std::string DataBase::_Table::toString(const T& value) { return std::to_string(value); diff --git a/test/basic.cpp b/test/basic.cpp index affbd4e..e68f521 100644 --- a/test/basic.cpp +++ b/test/basic.cpp @@ -12,8 +12,7 @@ protected: t1(db->getTable("table1")), t2(db->getTable("table2")) {} - ~DataBaseTest() { - } + ~DataBaseTest() {} static void SetUpTestSuite() { if (db == nullptr) { @@ -43,7 +42,12 @@ TEST_F(DataBaseTest, RemovingDirectory) { EXPECT_EQ(db->removeDirectory(), true); } -TEST_F(DataBaseTest, OpeningDatabase) { +TEST_F(DataBaseTest, OpeningClosingDatabase) { + EXPECT_EQ(db->ready(), false); + db->open(); + EXPECT_EQ(db->ready(), true); + db->close(); + EXPECT_EQ(db->ready(), false); db->open(); EXPECT_EQ(db->ready(), true); } @@ -51,16 +55,112 @@ TEST_F(DataBaseTest, OpeningDatabase) { TEST_F(DataBaseTest, AddingIntegerKey) { EXPECT_EQ(db->ready(), true); t1->addRecord(1, 2); + t1->addRecord(2, 2); + t1->addRecord(3, 15); EXPECT_EQ(t1->getRecord(1), 2); } TEST_F(DataBaseTest, AddingQStringKey) { EXPECT_EQ(db->ready(), true); t2->addRecord("hello", "world"); + t2->addRecord("aaa", "gagdfsdf"); + t2->addRecord("sdfhga", "DSFFDG"); + t2->addRecord("sdfsda", "shgsdgfa"); EXPECT_EQ(t2->getRecord("hello"), "world"); } -TEST_F(DataBaseTest, ClosingDatabase) { - db->close(); - EXPECT_EQ(db->ready(), false); +TEST_F(DataBaseTest, AddingRepeatingIntegerKey) { + EXPECT_EQ(db->ready(), true); + bool thrown = false; + try { + t1->addRecord(3, 24); + } catch (const DataBase::Exist e) { + thrown = true; + } + ASSERT_EQ(thrown, true) << "The expected behaviour is to throw exception on duplicate, but it didn't happened"; + EXPECT_EQ(t1->getRecord(3), 15); } + +TEST_F(DataBaseTest, AddingRepeatingStringKey) { + EXPECT_EQ(db->ready(), true); + bool thrown = false; + try { + t2->addRecord("sdfhga", "world"); + } catch (const DataBase::Exist e) { + thrown = true; + } + ASSERT_EQ(thrown, true) << "The expected behaviour is to throw exception on duplicate, but it didn't happened"; + EXPECT_EQ(t2->getRecord("sdfhga"), "DSFFDG"); +} + +TEST_F(DataBaseTest, GettingNotExistingKeys) { + EXPECT_EQ(db->ready(), true); + bool thrown = false; + try { + QString wrong = t2->getRecord("almonds"); + } catch (const DataBase::NotFound e) { + thrown = true; + } + ASSERT_EQ(thrown, true) << "The expected behaviour is to throw exception on duplicate, but it didn't happened"; + + thrown = false; + try { + uint32_t wrong = t1->getRecord(64); + } catch (const DataBase::NotFound e) { + thrown = true; + } + ASSERT_EQ(thrown, true) << "The expected behaviour is to throw exception on duplicate, but it didn't happened"; +} + +TEST_F(DataBaseTest, Persistence) { + EXPECT_EQ(db->ready(), true); + db->close(); + delete db; + + db = new DataBase("testBase"); + t1 = db->addTable("table1"); + t2 = db->addTable("table2"); + db->open(); + + EXPECT_EQ(t1->getRecord(3), 15); + EXPECT_EQ(t1->getRecord(1), 2); + EXPECT_EQ(t1->getRecord(2), 2); + EXPECT_EQ(t2->getRecord("hello"), "world"); + EXPECT_EQ(t2->getRecord("aaa"), "gagdfsdf"); + EXPECT_EQ(t2->getRecord("sdfhga"), "DSFFDG"); + EXPECT_EQ(t2->getRecord("sdfsda"), "shgsdgfa"); + + bool thrown = false; + try { + QString wrong = t2->getRecord("cats"); + } catch (const DataBase::NotFound e) { + thrown = true; + } + ASSERT_EQ(thrown, true) << "The expected behaviour is to throw exception on duplicate, but it didn't happened"; + + thrown = false; + try { + uint32_t wrong = t1->getRecord(7893); + } catch (const DataBase::NotFound e) { + thrown = true; + } + ASSERT_EQ(thrown, true) << "The expected behaviour is to throw exception on duplicate, but it didn't happened"; +} + +TEST_F(DataBaseTest, CountAndDrop) { + EXPECT_EQ(db->ready(), true); + EXPECT_EQ(t1->count(), 3); + EXPECT_EQ(t2->count(), 4); + + db->drop(); + + EXPECT_EQ(t1->count(), 0); + EXPECT_EQ(t2->count(), 0); + + t1->addRecord(2, 2); + t2->addRecord("sdfhga", "world"); + + EXPECT_EQ(t1->count(), 1); + EXPECT_EQ(t2->count(), 1); +} +