diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/CMakeLists.txt | 17 | ||||
-rw-r--r-- | tests/calendar.fbs | 12 | ||||
-rw-r--r-- | tests/storagebenchmark.cpp | 161 | ||||
-rw-r--r-- | tests/storagetest.cpp | 112 |
4 files changed, 302 insertions, 0 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..1629acb --- /dev/null +++ b/tests/CMakeLists.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | set(CMAKE_AUTOMOC ON) | ||
2 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) | ||
3 | |||
4 | generate_flatbuffers(calendar) | ||
5 | |||
6 | macro(manual_tests) | ||
7 | foreach(_testname ${ARGN}) | ||
8 | add_executable(${_testname} ${_testname}.cpp) | ||
9 | qt5_use_modules(${_testname} Core Test Concurrent) | ||
10 | target_link_libraries(${_testname} akonadinextcommon) | ||
11 | endforeach(_testname) | ||
12 | endmacro(manual_tests) | ||
13 | |||
14 | manual_tests ( | ||
15 | storagebenchmark | ||
16 | storagetest | ||
17 | ) | ||
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 @@ | |||
1 | // example IDL file | ||
2 | |||
3 | namespace Calendar; | ||
4 | |||
5 | table Event { | ||
6 | summary:string; | ||
7 | description:string; | ||
8 | attachment:[byte]; | ||
9 | } | ||
10 | |||
11 | root_type Event; | ||
12 | file_identifier "AKFB"; | ||
diff --git a/tests/storagebenchmark.cpp b/tests/storagebenchmark.cpp new file mode 100644 index 0000000..f9fea7c --- /dev/null +++ b/tests/storagebenchmark.cpp | |||
@@ -0,0 +1,161 @@ | |||
1 | #include <QtTest> | ||
2 | |||
3 | #include "calendar_generated.h" | ||
4 | |||
5 | #include <iostream> | ||
6 | #include <fstream> | ||
7 | |||
8 | #include <QDebug> | ||
9 | #include <QString> | ||
10 | #include <QTime> | ||
11 | |||
12 | #include "common/storage.h" | ||
13 | |||
14 | using namespace Calendar; | ||
15 | using namespace flatbuffers; | ||
16 | |||
17 | static std::string createEvent() | ||
18 | { | ||
19 | FlatBufferBuilder fbb; | ||
20 | { | ||
21 | auto summary = fbb.CreateString("summary"); | ||
22 | |||
23 | const int attachmentSize = 1024*2; // 2KB | ||
24 | int8_t rawData[attachmentSize]; | ||
25 | auto data = fbb.CreateVector(rawData, attachmentSize); | ||
26 | |||
27 | Calendar::EventBuilder eventBuilder(fbb); | ||
28 | eventBuilder.add_summary(summary); | ||
29 | eventBuilder.add_attachment(data); | ||
30 | auto eventLocation = eventBuilder.Finish(); | ||
31 | FinishEventBuffer(fbb, eventLocation); | ||
32 | } | ||
33 | return std::string(reinterpret_cast<const char *>(fbb.GetBufferPointer()), fbb.GetSize()); | ||
34 | } | ||
35 | |||
36 | // static void readEvent(const std::string &data) | ||
37 | // { | ||
38 | // auto readEvent = GetEvent(data.c_str()); | ||
39 | // std::cout << readEvent->summary()->c_str() << std::endl; | ||
40 | // } | ||
41 | |||
42 | class StorageBenchmark : public QObject | ||
43 | { | ||
44 | Q_OBJECT | ||
45 | private: | ||
46 | //This should point to a directory on disk and not a ramdisk (since we're measuring performance) | ||
47 | QString testDataPath; | ||
48 | QString dbName; | ||
49 | QString filePath; | ||
50 | const int count = 50000; | ||
51 | |||
52 | private Q_SLOTS: | ||
53 | void initTestCase() | ||
54 | { | ||
55 | testDataPath = "./testdb"; | ||
56 | dbName = "test"; | ||
57 | filePath = testDataPath + "buffer.fb"; | ||
58 | } | ||
59 | |||
60 | void cleanupTestCase() | ||
61 | { | ||
62 | Storage store(testDataPath, dbName); | ||
63 | store.removeFromDisk(); | ||
64 | } | ||
65 | |||
66 | void testWriteRead_data() | ||
67 | { | ||
68 | QTest::addColumn<bool>("useDb"); | ||
69 | QTest::addColumn<int>("count"); | ||
70 | |||
71 | QTest::newRow("db, 50k") << true << count; | ||
72 | QTest::newRow("file, 50k") << false << count; | ||
73 | } | ||
74 | |||
75 | void testWriteRead() | ||
76 | { | ||
77 | QFETCH(bool, useDb); | ||
78 | QFETCH(int, count); | ||
79 | |||
80 | Storage *store = 0; | ||
81 | if (useDb) { | ||
82 | store = new Storage(testDataPath, dbName); | ||
83 | } | ||
84 | |||
85 | std::ofstream myfile; | ||
86 | myfile.open(filePath.toStdString()); | ||
87 | const char *keyPrefix = "key"; | ||
88 | |||
89 | QTime time; | ||
90 | |||
91 | time.start(); | ||
92 | { | ||
93 | auto event = createEvent(); | ||
94 | for (int i = 0; i < count; i++) { | ||
95 | if (store) { | ||
96 | if (i % 10000 == 0) { | ||
97 | if (i > 0) { | ||
98 | store->commitTransaction(); | ||
99 | } | ||
100 | store->startTransaction(); | ||
101 | } | ||
102 | |||
103 | store->write(keyPrefix + std::to_string(i), event); | ||
104 | } else { | ||
105 | myfile << event; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | if (store) { | ||
110 | store->commitTransaction(); | ||
111 | } else { | ||
112 | myfile.close(); | ||
113 | } | ||
114 | } | ||
115 | const int writeDuration = time.restart(); | ||
116 | qDebug() << "Writing took[ms]: " << writeDuration; | ||
117 | |||
118 | { | ||
119 | for (int i = 0; i < count; i++) { | ||
120 | if (store) { | ||
121 | store->read(keyPrefix + std::to_string(i), [](std::string value){}); | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | const int readDuration = time.restart(); | ||
126 | |||
127 | if (store) { | ||
128 | qDebug() << "Reading took[ms]: " << readDuration; | ||
129 | } else { | ||
130 | qDebug() << "File reading is not implemented."; | ||
131 | } | ||
132 | |||
133 | delete store; | ||
134 | } | ||
135 | |||
136 | void testBufferCreation() | ||
137 | { | ||
138 | QTime time; | ||
139 | |||
140 | time.start(); | ||
141 | { | ||
142 | for (int i = 0; i < count; i++) { | ||
143 | auto event = createEvent(); | ||
144 | } | ||
145 | } | ||
146 | const int bufferDuration = time.elapsed(); | ||
147 | qDebug() << "Creating buffers took[ms]: " << bufferDuration; | ||
148 | } | ||
149 | |||
150 | void testSizes() | ||
151 | { | ||
152 | Storage store(testDataPath, dbName); | ||
153 | qDebug() << "Database size [kb]: " << store.diskUsage()/1024; | ||
154 | |||
155 | QFileInfo fileInfo(filePath); | ||
156 | qDebug() << "File size [kb]: " << fileInfo.size()/1024; | ||
157 | } | ||
158 | }; | ||
159 | |||
160 | QTEST_MAIN(StorageBenchmark) | ||
161 | #include "storagebenchmark.moc" | ||
diff --git a/tests/storagetest.cpp b/tests/storagetest.cpp new file mode 100644 index 0000000..2b2805d --- /dev/null +++ b/tests/storagetest.cpp | |||
@@ -0,0 +1,112 @@ | |||
1 | #include <QtTest> | ||
2 | |||
3 | #include <iostream> | ||
4 | |||
5 | #include <QDebug> | ||
6 | #include <QString> | ||
7 | #include <QtConcurrent/QtConcurrentRun> | ||
8 | |||
9 | #include "common/storage.h" | ||
10 | |||
11 | class StorageTest : public QObject | ||
12 | { | ||
13 | Q_OBJECT | ||
14 | private: | ||
15 | //This should point to a directory on disk and not a ramdisk (since we're measuring performance) | ||
16 | QString testDataPath; | ||
17 | QString dbName; | ||
18 | const char *keyPrefix = "key"; | ||
19 | |||
20 | void populate(int count) | ||
21 | { | ||
22 | Storage storage(testDataPath, dbName); | ||
23 | for (int i = 0; i < count; i++) { | ||
24 | //This should perhaps become an implementation detail of the db? | ||
25 | if (i % 10000 == 0) { | ||
26 | if (i > 0) { | ||
27 | storage.commitTransaction(); | ||
28 | } | ||
29 | storage.startTransaction(); | ||
30 | } | ||
31 | storage.write(keyPrefix + std::to_string(i), keyPrefix + std::to_string(i)); | ||
32 | } | ||
33 | storage.commitTransaction(); | ||
34 | } | ||
35 | |||
36 | bool verify(Storage &storage, int i) | ||
37 | { | ||
38 | bool success = true; | ||
39 | bool keyMatch = true; | ||
40 | const auto reference = keyPrefix + std::to_string(i); | ||
41 | success = storage.read(keyPrefix + std::to_string(i), [&error, &reference](const std::string &value) { | ||
42 | if (value != reference) { | ||
43 | qDebug() << "Mismatch while reading"; | ||
44 | keyMatch = false; | ||
45 | } | ||
46 | }); | ||
47 | return succes && keyMatch; | ||
48 | } | ||
49 | |||
50 | private Q_SLOTS: | ||
51 | void initTestCase() | ||
52 | { | ||
53 | testDataPath = "./testdb"; | ||
54 | dbName = "test"; | ||
55 | } | ||
56 | |||
57 | void cleanupTestCase() | ||
58 | { | ||
59 | Database db(testDataPath, dbName); | ||
60 | db.removeFromDisk(); | ||
61 | } | ||
62 | |||
63 | |||
64 | void testRead() | ||
65 | { | ||
66 | const int count = 100; | ||
67 | |||
68 | populate(count); | ||
69 | |||
70 | //ensure we can read everything back correctly | ||
71 | { | ||
72 | Database db(testDataPath, dbName); | ||
73 | for (int i = 0; i < count; i++) { | ||
74 | QVERIFY(verify(db, i)); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | Database db(testDataPath, dbName); | ||
79 | db.removeFromDisk(); | ||
80 | } | ||
81 | |||
82 | void testConcurrentRead() | ||
83 | { | ||
84 | const int count = 10000; | ||
85 | |||
86 | populate(count); | ||
87 | |||
88 | //Try to concurrently read | ||
89 | QList<QFuture<void> > futures; | ||
90 | const int concurrencyLevel = 4; | ||
91 | for (int num = 0; num < concurrencyLevel; num++) { | ||
92 | futures << QtConcurrent::run([this, count](){ | ||
93 | Database db(testDataPath, dbName); | ||
94 | for (int i = 0; i < count; i++) { | ||
95 | if (!verify(db, i)) { | ||
96 | qWarning() << "invalid value"; | ||
97 | break; | ||
98 | } | ||
99 | } | ||
100 | }); | ||
101 | } | ||
102 | for(auto future : futures) { | ||
103 | future.waitForFinished(); | ||
104 | } | ||
105 | |||
106 | Database db(testDataPath, dbName); | ||
107 | db.removeFromDisk(); | ||
108 | } | ||
109 | }; | ||
110 | |||
111 | QTEST_MAIN(StorageTest) | ||
112 | #include "storagetest.moc" | ||