From fdd74a41929b4343902f1d1dfcd5116534a79f4f Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Thu, 11 Dec 2014 00:44:44 +0100 Subject: Dummyresourcefacade test. Huzaa, we can read a value! --- client/CMakeLists.txt | 9 +++-- client/clientapi.h | 10 ++++-- dummyresource/CMakeLists.txt | 2 +- dummyresource/facade.cpp | 52 ++++++++++++++++++++++------ dummyresource/facade.h | 2 -- tests/CMakeLists.txt | 4 +++ tests/dummyresourcefacadetest.cpp | 73 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 134 insertions(+), 18 deletions(-) create mode 100644 tests/dummyresourcefacadetest.cpp diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index a0ebe3a..8001d5f 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -3,12 +3,15 @@ project(akonadi2_client) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) set(akonadi2client_SRCS - main.cpp resourceaccess.cpp ) -add_executable(${PROJECT_NAME} ${akonadi2client_SRCS}) -target_link_libraries(${PROJECT_NAME} akonadi2common) +add_library(${PROJECT_NAME}_lib ${akonadi2client_SRCS}) +target_link_libraries(${PROJECT_NAME}_lib akonadi2common) +qt5_use_modules(${PROJECT_NAME}_lib Widgets Network) + +add_executable(${PROJECT_NAME} main.cpp) +target_link_libraries(${PROJECT_NAME} akonadi2_client_lib akonadi2common) qt5_use_modules(${PROJECT_NAME} Widgets Network) install(TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/client/clientapi.h b/client/clientapi.h index 59efe32..592fa48 100644 --- a/client/clientapi.h +++ b/client/clientapi.h @@ -185,8 +185,14 @@ using namespace async; class Query { public: - //Resources to search - QSet resources; + //Could also be a propertyFilter + QStringList resources; + //Could also be a propertyFilter + QStringList ids; + //Filters to apply + QHash propertyFilter; + //Properties to retrieve + QSet requestedProperties; }; diff --git a/dummyresource/CMakeLists.txt b/dummyresource/CMakeLists.txt index e814f41..8fa2eee 100644 --- a/dummyresource/CMakeLists.txt +++ b/dummyresource/CMakeLists.txt @@ -6,7 +6,7 @@ generate_flatbuffers(dummycalendar) #Client plugin add_library(${PROJECT_NAME}_facade SHARED facade.cpp) -target_link_libraries(${PROJECT_NAME}_facade akonadi2common) +target_link_libraries(${PROJECT_NAME}_facade akonadi2common akonadi2_client_lib) qt5_use_modules(${PROJECT_NAME}_facade Widgets Network) #install(TARGETS ${PROJECT_NAME}_facade DESTINATION bin) diff --git a/dummyresource/facade.cpp b/dummyresource/facade.cpp index bfe1de4..44056f8 100644 --- a/dummyresource/facade.cpp +++ b/dummyresource/facade.cpp @@ -10,8 +10,7 @@ using namespace flatbuffers; DummyResourceFacade::DummyResourceFacade() : Akonadi2::StoreFacade(), - mResourceAccess(new ResourceAccess("dummyresource")), - mStorage(new Storage(Akonadi2::Store::storageLocation(), "dummyresource")) + mResourceAccess(/* new ResourceAccess("dummyresource") */) { // connect(mResourceAccess.data(), &ResourceAccess::ready, this, onReadyChanged); } @@ -47,7 +46,10 @@ void DummyResourceFacade::remove(const Akonadi2::Domain::Event &domainObject) //=> perhaps do heap allocate and use smart pointer? class DummyEventAdaptor : public Akonadi2::Domain::Event { public: - DummyEventAdaptor(const QString &resource, const QString &identifier, qint64 revision):Akonadi2::Domain::Event(resource, identifier, revision){}; + DummyEventAdaptor(const QString &resource, const QString &identifier, qint64 revision) + :Akonadi2::Domain::Event(resource, identifier, revision) + { + } //TODO // void setProperty(const QString &key, const QVariant &value) @@ -75,15 +77,45 @@ public: void DummyResourceFacade::load(const Akonadi2::Query &query, const std::function &resultCallback) { qDebug() << "load called"; - //TODO only read values matching the query auto storage = QSharedPointer::create(Akonadi2::Store::storageLocation(), "dummyresource"); - storage->read("", [resultCallback, storage](void *data, int size) -> bool { + + //Compose some functions to make query matching fast. + //This way we can process the query once, and convert all values into something that can be compared quickly + std::function preparedQuery; + if (!query.ids.isEmpty()) { + //Match by id + //TODO: for id's a direct lookup would be way faster + + //We convert the id's to std::string so we don't have to convert each key during the scan. (This runs only once, and the query will be run for every key) + //Probably a premature optimization, but perhaps a useful technique to be investigated. + QVector ids; + for (const auto &id : query.ids) { + ids << id.toStdString(); + } + preparedQuery = [ids](const std::string &key, DummyEvent const *buffer) { + if (ids.contains(key)) { + return true; + } + return false; + }; + } else { + //Match everything + preparedQuery = [](const std::string &key, DummyEvent const *buffer) { + return true; + }; + } + + //Because we have no indexes yet, we always do a full scan + storage->scan("", [=](void *keyValue, int keySize, void *dataValue, int dataSize) -> bool { //TODO read second buffer as well - auto eventBuffer = GetDummyEvent(data); - auto event = QSharedPointer::create("dummyresource", "key", 0); - event->buffer = eventBuffer; - event->storage = storage; - resultCallback(event); + auto eventBuffer = GetDummyEvent(dataValue); + if (preparedQuery && preparedQuery(std::string(static_cast(keyValue), keySize), eventBuffer)) { + //TODO read the revision from the generic portion of the buffer + auto event = QSharedPointer::create("dummyresource", QString::fromUtf8(static_cast(keyValue), keySize), 0); + event->buffer = eventBuffer; + event->storage = storage; + resultCallback(event); + } return true; }); } diff --git a/dummyresource/facade.h b/dummyresource/facade.h index 310ef77..56889aa 100644 --- a/dummyresource/facade.h +++ b/dummyresource/facade.h @@ -13,10 +13,8 @@ public: virtual void create(const Akonadi2::Domain::Event &domainObject); virtual void modify(const Akonadi2::Domain::Event &domainObject); virtual void remove(const Akonadi2::Domain::Event &domainObject); - // virtual void load(const Akonadi2::Query &query, const std::function &resultCallback); virtual void load(const Akonadi2::Query &query, const std::function &resultCallback); private: QSharedPointer mResourceAccess; - QSharedPointer mStorage; }; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9ee3f5e..95aba64 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,4 +14,8 @@ endmacro(manual_tests) manual_tests ( storagebenchmark storagetest + dummyresourcefacadetest ) + +target_link_libraries(dummyresourcefacadetest akonadi2_dummyresource_facade) + diff --git a/tests/dummyresourcefacadetest.cpp b/tests/dummyresourcefacadetest.cpp new file mode 100644 index 0000000..26daa23 --- /dev/null +++ b/tests/dummyresourcefacadetest.cpp @@ -0,0 +1,73 @@ +#include + +#include + +#include +#include +#include + +#include "common/storage.h" +#include "dummyresource/facade.h" + +class DummyResourceFacadeTest : public QObject +{ + Q_OBJECT +private: + QString testDataPath; + QString dbName; + const char *keyPrefix = "key"; + + void populate(int count) + { + Storage storage(testDataPath, dbName, Storage::ReadWrite); + for (int i = 0; i < count; i++) { + storage.write(keyPrefix + std::to_string(i), keyPrefix + std::to_string(i)); + } + storage.commitTransaction(); + } + +private Q_SLOTS: + void initTestCase() + { + testDataPath = Akonadi2::Store::storageLocation(); + dbName = "dummyresource"; + Akonadi2::FacadeFactory::instance().registerFacade("dummyresource", []() { + return new DummyResourceFacade(); + }); + } + + void cleanupTestCase() + { + Storage storage(testDataPath, dbName); + storage.removeFromDisk(); + } + + void testScan() + { + const int count = 100; + populate(count); + + Akonadi2::Query query; + query.ids << "key50"; + query.resources << "dummyresource"; + + auto result = Akonadi2::Store::load(query); + bool complete = false; + QVector results; + result->onAdded([&results](const Akonadi2::Domain::Event::Ptr &e) { + results << e; + }); + result->onComplete([&complete]() { + complete = true; + }); + QTRY_VERIFY(complete); + QCOMPARE(results.size(), 1); + + Storage storage(testDataPath, dbName); + storage.removeFromDisk(); + } + +}; + +QTEST_MAIN(DummyResourceFacadeTest) +#include "dummyresourcefacadetest.moc" -- cgit v1.2.3