From 767312e2063f4e58af3de0f27aba52de49e14295 Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Fri, 5 Dec 2014 09:17:46 +0100 Subject: major reorg that puts Storage (previously Database) into common there is now a top-level tests dir, and a compile time switch for lmdb vs kyotocabinet --- tests/CMakeLists.txt | 16 +++++ tests/calendar.fbs | 12 ++++ tests/storagebenchmark.cpp | 157 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 tests/CMakeLists.txt create mode 100644 tests/calendar.fbs create mode 100644 tests/storagebenchmark.cpp (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..23776a1 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,16 @@ +set(CMAKE_AUTOMOC ON) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +generate_flatbuffers(calendar) + +macro(manual_tests) + foreach(_testname ${ARGN}) + add_executable(${_testname} ${_testname}.cpp) + qt5_use_modules(${_testname} Core Test) + target_link_libraries(${_testname} akonadinextcommon) + endforeach(_testname) +endmacro(manual_tests) + +manual_tests ( + storagebenchmark +) diff --git a/tests/calendar.fbs b/tests/calendar.fbs new file mode 100644 index 0000000..203ee43 --- /dev/null +++ b/tests/calendar.fbs @@ -0,0 +1,12 @@ +// example IDL file + +namespace Calendar; + +table Event { + summary:string; + description:string; + attachment:[byte]; +} + +root_type Event; +file_identifier "AKFB"; diff --git a/tests/storagebenchmark.cpp b/tests/storagebenchmark.cpp new file mode 100644 index 0000000..15da9da --- /dev/null +++ b/tests/storagebenchmark.cpp @@ -0,0 +1,157 @@ +#include + +#include "calendar_generated.h" + +#include +#include + +#include +#include +#include +#include + +#include "common/storage.h" + +using namespace Calendar; +using namespace flatbuffers; + +static std::string createEvent() +{ + FlatBufferBuilder fbb; + { + auto summary = fbb.CreateString("summary"); + + const int attachmentSize = 1024*2; // 2KB + int8_t rawData[attachmentSize]; + auto data = fbb.CreateVector(rawData, attachmentSize); + + Calendar::EventBuilder eventBuilder(fbb); + eventBuilder.add_summary(summary); + eventBuilder.add_attachment(data); + auto eventLocation = eventBuilder.Finish(); + FinishEventBuffer(fbb, eventLocation); + } + return std::string(reinterpret_cast(fbb.GetBufferPointer()), fbb.GetSize()); +} + +// static void readEvent(const std::string &data) +// { +// auto readEvent = GetEvent(data.c_str()); +// std::cout << readEvent->summary()->c_str() << std::endl; +// } + +class StorageBenchmark : public QObject +{ + Q_OBJECT +private: + //This should point to a directory on disk and not a ramdisk (since we're measuring performance) + QString testDataPath; + QString dbName; + QString filePath; + const int count = 50000; + +private Q_SLOTS: + void initTestCase() + { + testDataPath = "./testdb"; + dbName = "test"; + filePath = testDataPath + "buffer.fb"; + } + + void testWriteRead_data() + { + QTest::addColumn("useDb"); + QTest::addColumn("count"); + + QTest::newRow("db, 50k") << true << count; + QTest::newRow("file, 50k") << false << count; + } + + void testWriteRead() + { + QFETCH(bool, useDb); + QFETCH(int, count); + + Storage *store = 0; + if (useDb) { + store = new Storage(testDataPath, dbName); + } + + std::ofstream myfile; + myfile.open(filePath.toStdString()); + const char *keyPrefix = "key"; + + QTime time; + + time.start(); + { + auto event = createEvent(); + for (int i = 0; i < count; i++) { + if (store) { + if (i % 10000 == 0) { + if (i > 0) { + store->commitTransaction(); + } + store->startTransaction(); + } + + store->write(keyPrefix + std::to_string(i), event); + } else { + myfile << event; + } + } + + if (store) { + store->commitTransaction(); + } else { + myfile.close(); + } + } + const int writeDuration = time.restart(); + qDebug() << "Writing took[ms]: " << writeDuration; + + { + for (int i = 0; i < count; i++) { + if (store) { + store->read(keyPrefix + std::to_string(i), [](std::string value){}); + } + } + } + const int readDuration = time.restart(); + + if (store) { + qDebug() << "Reading took[ms]: " << readDuration; + } else { + qDebug() << "File reading is not implemented."; + } + + delete store; + } + + void testBufferCreation() + { + QTime time; + + time.start(); + { + for (int i = 0; i < count; i++) { + auto event = createEvent(); + } + } + const int bufferDuration = time.elapsed(); + qDebug() << "Creating buffers took[ms]: " << bufferDuration; + } + + void testSizes() + { + Storage store(testDataPath, dbName); + qDebug() << "Database size [kb]: " << store.diskUsage()/1024; + store.removeFromDisk(); + + QFileInfo fileInfo(filePath); + qDebug() << "File size [kb]: " << fileInfo.size()/1024; + } +}; + +QTEST_MAIN(StorageBenchmark) +#include "storagebenchmark.moc" -- cgit v1.2.3 From 88085fd52f886692c9cbb534166e68b791d5abce Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Fri, 5 Dec 2014 09:29:37 +0100 Subject: port over 707344 by cmollekopf: small cleanup --- tests/storagebenchmark.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/storagebenchmark.cpp b/tests/storagebenchmark.cpp index 15da9da..f9fea7c 100644 --- a/tests/storagebenchmark.cpp +++ b/tests/storagebenchmark.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include @@ -58,6 +57,12 @@ private Q_SLOTS: filePath = testDataPath + "buffer.fb"; } + void cleanupTestCase() + { + Storage store(testDataPath, dbName); + store.removeFromDisk(); + } + void testWriteRead_data() { QTest::addColumn("useDb"); @@ -146,7 +151,6 @@ private Q_SLOTS: { Storage store(testDataPath, dbName); qDebug() << "Database size [kb]: " << store.diskUsage()/1024; - store.removeFromDisk(); QFileInfo fileInfo(filePath); qDebug() << "File size [kb]: " << fileInfo.size()/1024; -- cgit v1.2.3 From ee41f8d17bdc667fbbbc83deeff766faf048cf5e Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 5 Dec 2014 00:57:03 +0100 Subject: A storagetest including concurrency read test. Conflicts: tests/CMakeLists.txt --- tests/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 23776a1..1629acb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,11 +6,12 @@ generate_flatbuffers(calendar) macro(manual_tests) foreach(_testname ${ARGN}) add_executable(${_testname} ${_testname}.cpp) - qt5_use_modules(${_testname} Core Test) + qt5_use_modules(${_testname} Core Test Concurrent) target_link_libraries(${_testname} akonadinextcommon) endforeach(_testname) endmacro(manual_tests) manual_tests ( storagebenchmark + storagetest ) -- cgit v1.2.3 From 0c1400c7f0cf2f545a6cd7347314c1158fbfa36f Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Fri, 5 Dec 2014 09:33:35 +0100 Subject: mv storagetest.cpp to the right location --- tests/storagetest.cpp | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 tests/storagetest.cpp (limited to 'tests') diff --git a/tests/storagetest.cpp b/tests/storagetest.cpp new file mode 100644 index 0000000..1b105af --- /dev/null +++ b/tests/storagetest.cpp @@ -0,0 +1,111 @@ +#include + +#include + +#include +#include +#include + +#include "store/database.h" + +class StorageTest : public QObject +{ + Q_OBJECT +private: + //This should point to a directory on disk and not a ramdisk (since we're measuring performance) + QString testDataPath; + QString dbName; + const char *keyPrefix = "key"; + + void populate(int count) + { + Database db(testDataPath, dbName); + for (int i = 0; i < count; i++) { + //This should perhaps become an implementation detail of the db? + if (i % 10000 == 0) { + if (i > 0) { + db.commitTransaction(); + } + db.startTransaction(); + } + db.write(keyPrefix + std::to_string(i), keyPrefix + std::to_string(i)); + } + db.commitTransaction(); + } + + bool verify(Database &db, int i) + { + bool error = false; + const auto reference = keyPrefix + std::to_string(i); + db.read(keyPrefix + std::to_string(i), [&error, &reference](const std::string &value) { + if (value != reference) { + qDebug() << "Mismatch while reading"; + error = true; + } + }); + return !error; + } + +private Q_SLOTS: + void initTestCase() + { + testDataPath = "./testdb"; + dbName = "test"; + } + + void cleanupTestCase() + { + Database db(testDataPath, dbName); + db.removeFromDisk(); + } + + + void testRead() + { + const int count = 100; + + populate(count); + + //ensure we can read everything back correctly + { + Database db(testDataPath, dbName); + for (int i = 0; i < count; i++) { + QVERIFY(verify(db, i)); + } + } + + Database db(testDataPath, dbName); + db.removeFromDisk(); + } + + void testConcurrentRead() + { + const int count = 10000; + + populate(count); + + //Try to concurrently read + QList > futures; + const int concurrencyLevel = 4; + for (int num = 0; num < concurrencyLevel; num++) { + futures << QtConcurrent::run([this, count](){ + Database db(testDataPath, dbName); + for (int i = 0; i < count; i++) { + if (!verify(db, i)) { + qWarning() << "invalid value"; + break; + } + } + }); + } + for(auto future : futures) { + future.waitForFinished(); + } + + Database db(testDataPath, dbName); + db.removeFromDisk(); + } +}; + +QTEST_MAIN(StorageTest) +#include "storagetest.moc" -- cgit v1.2.3 From 351a66b5fb1c8659bff8ea20d60f5a6d2d3263ad Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Fri, 5 Dec 2014 09:46:53 +0100 Subject: make read return a bool on success not happy with this API, but we need to discuss the whole read thing anyways --- tests/storagetest.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'tests') diff --git a/tests/storagetest.cpp b/tests/storagetest.cpp index 1b105af..2b2805d 100644 --- a/tests/storagetest.cpp +++ b/tests/storagetest.cpp @@ -6,7 +6,7 @@ #include #include -#include "store/database.h" +#include "common/storage.h" class StorageTest : public QObject { @@ -19,31 +19,32 @@ private: void populate(int count) { - Database db(testDataPath, dbName); + Storage storage(testDataPath, dbName); for (int i = 0; i < count; i++) { //This should perhaps become an implementation detail of the db? if (i % 10000 == 0) { if (i > 0) { - db.commitTransaction(); + storage.commitTransaction(); } - db.startTransaction(); + storage.startTransaction(); } - db.write(keyPrefix + std::to_string(i), keyPrefix + std::to_string(i)); + storage.write(keyPrefix + std::to_string(i), keyPrefix + std::to_string(i)); } - db.commitTransaction(); + storage.commitTransaction(); } - bool verify(Database &db, int i) + bool verify(Storage &storage, int i) { - bool error = false; + bool success = true; + bool keyMatch = true; const auto reference = keyPrefix + std::to_string(i); - db.read(keyPrefix + std::to_string(i), [&error, &reference](const std::string &value) { + success = storage.read(keyPrefix + std::to_string(i), [&error, &reference](const std::string &value) { if (value != reference) { qDebug() << "Mismatch while reading"; - error = true; + keyMatch = false; } }); - return !error; + return succes && keyMatch; } private Q_SLOTS: -- cgit v1.2.3