From 9ea268a6d0f4054c31b2729ecd6cfcc9d07a2d6a Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 24 Mar 2017 22:15:18 +0100 Subject: Implemented notification support in the model. This will allow us to fold things like progress and sync status directly into the model. Usecases are mail download progress and folder sync progress. Ideally we would also solve the resource/account state through this. --- tests/CMakeLists.txt | 2 + tests/dummyresourcetest.cpp | 9 +--- tests/notificationtest.cpp | 124 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 tests/notificationtest.cpp (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7144d41..fef76bd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -44,6 +44,7 @@ auto_tests ( testaccounttest dummyresourcemailtest interresourcemovetest + notificationtest ) generate_flatbuffers(dummyresourcetest calendar) target_link_libraries(dummyresourcetest sink_resource_dummy) @@ -52,3 +53,4 @@ target_link_libraries(dummyresourcewritebenchmark sink_resource_dummy) target_link_libraries(querytest sink_resource_dummy) target_link_libraries(modelinteractivitytest sink_resource_dummy) target_link_libraries(inspectiontest sink_resource_dummy) +target_link_libraries(notificationtest sink_resource_dummy) diff --git a/tests/dummyresourcetest.cpp b/tests/dummyresourcetest.cpp index eea63c0..17df160 100644 --- a/tests/dummyresourcetest.cpp +++ b/tests/dummyresourcetest.cpp @@ -136,12 +136,7 @@ private slots: void testResourceSync() { ::DummyResource resource(getContext()); - auto job = resource.synchronizeWithSource(Sink::QueryBase()); - // TODO pass in optional timeout? - auto future = job.exec(); - future.waitForFinished(); - QVERIFY(!future.errorCode()); - QVERIFY(future.isFinished()); + VERIFYEXEC(resource.synchronizeWithSource(Sink::QueryBase())); QVERIFY(!resource.error()); auto processAllMessagesFuture = resource.processAllMessages().exec(); processAllMessagesFuture.waitForFinished(); @@ -152,7 +147,7 @@ private slots: const auto query = Query().resourceFilter("sink.dummy.instance1"); // Ensure all local data is processed - Sink::Store::synchronize(query).exec().waitForFinished(); + VERIFYEXEC(Sink::Store::synchronize(query)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1")); auto model = Sink::Store::loadModel(query); diff --git a/tests/notificationtest.cpp b/tests/notificationtest.cpp new file mode 100644 index 0000000..9433586 --- /dev/null +++ b/tests/notificationtest.cpp @@ -0,0 +1,124 @@ +#include + +#include +#include + +#include "store.h" +#include "resourceconfig.h" +#include "resourcecontrol.h" +#include "modelresult.h" +#include "log.h" +#include "test.h" +#include "testutils.h" +#include "notifier.h" +#include "notification.h" + +using namespace Sink; +using namespace Sink::ApplicationDomain; + +/** + * Test of complete system using the dummy resource. + * + * This test requires the dummy resource installed. + */ +class NotificationTest : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase() + { + Sink::Test::initTest(); + ResourceConfig::addResource("sink.dummy.instance1", "sink.dummy"); + } + + void cleanup() + { + VERIFYEXEC(Sink::Store::removeDataFromDisk(QByteArray("sink.dummy.instance1"))); + } + + void testSyncNotifications() + { + auto query = Query().resourceFilter("sink.dummy.instance1"); + query.setType(); + query.filter("id1"); + query.filter("id2"); + + QList statusNotifications; + QList infoNotifications; + Sink::Notifier notifier("sink.dummy.instance1"); + notifier.registerHandler([&] (const Sink::Notification &n){ + SinkLogCtx(Sink::Log::Context{"dummyresourcetest"}) << "Received notification " << n; + if (n.type == Notification::Status) { + statusNotifications << n; + } + if (n.type == Notification::Info) { + infoNotifications << n; + } + }); + + // Ensure all local data is processed + VERIFYEXEC(Sink::Store::synchronize(query)); + VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1")); + + //FIXME it can happen that we get a changereplay notification pair first. + QTRY_COMPARE(statusNotifications.size(), 5); + //Sync + QCOMPARE(statusNotifications.at(0).code, static_cast(ApplicationDomain::Status::ConnectedStatus)); + QCOMPARE(statusNotifications.at(1).code, static_cast(Sink::ApplicationDomain::Status::BusyStatus)); + QCOMPARE(statusNotifications.at(2).code, static_cast(Sink::ApplicationDomain::Status::ConnectedStatus)); + //Changereplay + QCOMPARE(statusNotifications.at(3).code, static_cast(Sink::ApplicationDomain::Status::BusyStatus)); + QCOMPARE(statusNotifications.at(4).code, static_cast(Sink::ApplicationDomain::Status::ConnectedStatus)); + + QTRY_COMPARE(infoNotifications.size(), 2); + QCOMPARE(infoNotifications.at(0).code, static_cast(ApplicationDomain::SyncStatus::SyncInProgress)); + QCOMPARE(infoNotifications.at(0).entities, QList{} << "id1" << "id2"); + QCOMPARE(infoNotifications.at(1).code, static_cast(ApplicationDomain::SyncStatus::SyncSuccess)); + QCOMPARE(infoNotifications.at(1).entities, QList{} << "id1" << "id2"); + + QCOMPARE(infoNotifications.at(1).code, static_cast(ApplicationDomain::SyncStatus::SyncSuccess)); + } + + void testModelNotifications() + { + auto query = Query().resourceFilter("sink.dummy.instance1"); + query.setType(); + query.setFlags(Query::LiveQuery | Query::UpdateStatus); + + VERIFYEXEC(Sink::Store::synchronize(query)); + VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1")); + + auto model = Sink::Store::loadModel(query); + QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); + QVERIFY(model->rowCount() >= 1); + + QSignalSpy changedSpy(model.data(), &QAbstractItemModel::dataChanged); + auto mail = model->index(0, 0, QModelIndex()).data(Sink::Store::DomainObjectRole).value(); + auto newQuery = query; + newQuery.filter(mail->identifier()); + + QList status; + QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [&] (const QModelIndex &begin, const QModelIndex &end, const QVector &roles) { + QVERIFY(begin.row() == end.row()); + if (begin.row() == 0) { + status << model->data(begin, Store::StatusRole).value(); + // qWarning() << "New status: " << status.last() << roles; + } + }); + + //This will trigger a modification of all previous items as well. + VERIFYEXEC(Sink::Store::synchronize(newQuery)); + VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(QByteArrayList() << "sink.dummy.instance1")); + + QCOMPARE(status.size(), 3); + //Sync progress of item + QCOMPARE(status.at(0), static_cast(ApplicationDomain::SyncStatus::SyncInProgress)); + QCOMPARE(status.at(1), static_cast(ApplicationDomain::SyncStatus::SyncSuccess)); + //Modification triggered during sync + QCOMPARE(status.at(2), static_cast(ApplicationDomain::SyncStatus::SyncSuccess)); + } +}; + +QTEST_MAIN(NotificationTest) +#include "notificationtest.moc" -- cgit v1.2.3