diff --git a/autotests/libs/monitornotificationtest.cpp b/autotests/libs/monitornotificationtest.cpp index b738ee4fe..0e5ed423a 100644 --- a/autotests/libs/monitornotificationtest.cpp +++ b/autotests/libs/monitornotificationtest.cpp @@ -1,308 +1,319 @@ /* Copyright (c) 2011 Stephen Kelly This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "monitor.h" #include "fakeserverdata.h" #include "fakesession.h" #include "inspectablemonitor.h" #include "inspectablechangerecorder.h" #include "akonaditestfake_export.h" #include #include using namespace Akonadi; class MonitorNotificationTest : public QObject { Q_OBJECT public: MonitorNotificationTest(QObject *parent = nullptr) : QObject(parent) { m_sessionName = "MonitorNotificationTest fake session"; m_fakeSession = new FakeSession(m_sessionName, FakeSession::EndJobsImmediately); m_fakeSession->setAsDefaultSession(); } + ~MonitorNotificationTest() + { + delete m_fakeSession; + } + private Q_SLOTS: void testSingleMessage(); void testFillPipeline(); void testMonitor(); void testSingleMessage_data(); void testFillPipeline_data(); void testMonitor_data(); private: template void testSingleMessage_impl(MonitorImpl *monitor, FakeCollectionCache *collectionCache, FakeItemCache *itemCache); template void testFillPipeline_impl(MonitorImpl *monitor, FakeCollectionCache *collectionCache, FakeItemCache *itemCache); template void testMonitor_impl(MonitorImpl *monitor, FakeCollectionCache *collectionCache, FakeItemCache *itemCache); private: FakeSession *m_fakeSession = nullptr; QByteArray m_sessionName; }; void MonitorNotificationTest::testSingleMessage_data() { QTest::addColumn("useChangeRecorder"); QTest::newRow("useChangeRecorder") << true; QTest::newRow("useMonitor") << false; } void MonitorNotificationTest::testSingleMessage() { QFETCH(bool, useChangeRecorder); FakeCollectionCache *collectionCache = new FakeCollectionCache(m_fakeSession); FakeItemCache *itemCache = new FakeItemCache(m_fakeSession); FakeMonitorDependeciesFactory *depsFactory = new FakeMonitorDependeciesFactory(itemCache, collectionCache); if (!useChangeRecorder) { testSingleMessage_impl(new InspectableMonitor(depsFactory, this), collectionCache, itemCache); } else { InspectableChangeRecorder *changeRecorder = new InspectableChangeRecorder(depsFactory, this); changeRecorder->setChangeRecordingEnabled(false); testSingleMessage_impl(changeRecorder, collectionCache, itemCache); } } template void MonitorNotificationTest::testSingleMessage_impl(MonitorImpl *monitor, FakeCollectionCache *collectionCache, FakeItemCache *itemCache) { Q_UNUSED(itemCache) // Workaround for the QTimer::singleShot() in fake monitors to happen QTest::qWait(10); monitor->setSession(m_fakeSession); monitor->fetchCollection(true); Protocol::ChangeNotificationList list; Collection parent(1); Collection added(2); auto msg = Protocol::CollectionChangeNotificationPtr::create(); msg->setParentCollection(parent.id()); msg->setOperation(Protocol::CollectionChangeNotification::Add); msg->setCollection(Protocol::FetchCollectionsResponsePtr::create(added.id())); + // With notification payloads most requests by-pass the pipeline as the + // notification already contains everything. To force pipelineing we set + // the internal metadata (normally set by ChangeRecorder) + msg->addMetadata("FETCH_COLLECTION"); QHash data; data.insert(parent.id(), parent); data.insert(added.id(), added); // Pending notifications remains empty because we don't fill the pipeline with one message. QVERIFY(monitor->pipeline().isEmpty()); QVERIFY(monitor->pendingNotifications().isEmpty()); monitor->notificationConnection()->emitNotify(msg); - QCOMPARE(monitor->pipeline().size(), 1); + QTRY_COMPARE(monitor->pipeline().size(), 1); QVERIFY(monitor->pendingNotifications().isEmpty()); collectionCache->setData(data); collectionCache->emitDataAvailable(); QVERIFY(monitor->pipeline().isEmpty()); QVERIFY(monitor->pendingNotifications().isEmpty()); } void MonitorNotificationTest::testFillPipeline_data() { QTest::addColumn("useChangeRecorder"); QTest::newRow("useChangeRecorder") << true; QTest::newRow("useMonitor") << false; } void MonitorNotificationTest::testFillPipeline() { QFETCH(bool, useChangeRecorder); FakeCollectionCache *collectionCache = new FakeCollectionCache(m_fakeSession); FakeItemCache *itemCache = new FakeItemCache(m_fakeSession); FakeMonitorDependeciesFactory *depsFactory = new FakeMonitorDependeciesFactory(itemCache, collectionCache); if (!useChangeRecorder) { testFillPipeline_impl(new InspectableMonitor(depsFactory, this), collectionCache, itemCache); } else { InspectableChangeRecorder *changeRecorder = new InspectableChangeRecorder(depsFactory, this); changeRecorder->setChangeRecordingEnabled(false); testFillPipeline_impl(changeRecorder, collectionCache, itemCache); } } template void MonitorNotificationTest::testFillPipeline_impl(MonitorImpl *monitor, FakeCollectionCache *collectionCache, FakeItemCache *itemCache) { Q_UNUSED(itemCache) monitor->setSession(m_fakeSession); monitor->fetchCollection(true); Protocol::ChangeNotificationList list; QHash data; int i = 1; while (i < 40) { Collection parent(i++); Collection added(i++); auto msg = Protocol::CollectionChangeNotificationPtr::create(); msg->setParentCollection(parent.id()); msg->setOperation(Protocol::CollectionChangeNotification::Add); msg->setCollection(Protocol::FetchCollectionsResponsePtr::create(added.id())); + msg->addMetadata("FETCH_COLLECTION"); data.insert(parent.id(), parent); data.insert(added.id(), added); list << msg; } QVERIFY(monitor->pipeline().isEmpty()); QVERIFY(monitor->pendingNotifications().isEmpty()); Q_FOREACH (const Protocol::ChangeNotificationPtr &ntf, list) { monitor->notificationConnection()->emitNotify(ntf); } - QCOMPARE(monitor->pipeline().size(), 5); + QTRY_COMPARE(monitor->pipeline().size(), 5); QCOMPARE(monitor->pendingNotifications().size(), 15); collectionCache->setData(data); collectionCache->emitDataAvailable(); QVERIFY(monitor->pipeline().isEmpty()); QVERIFY(monitor->pendingNotifications().isEmpty()); } void MonitorNotificationTest::testMonitor_data() { QTest::addColumn("useChangeRecorder"); QTest::newRow("useChangeRecorder") << true; QTest::newRow("useMonitor") << false; } void MonitorNotificationTest::testMonitor() { QFETCH(bool, useChangeRecorder); FakeCollectionCache *collectionCache = new FakeCollectionCache(m_fakeSession); FakeItemCache *itemCache = new FakeItemCache(m_fakeSession); FakeMonitorDependeciesFactory *depsFactory = new FakeMonitorDependeciesFactory(itemCache, collectionCache); if (!useChangeRecorder) { testMonitor_impl(new InspectableMonitor(depsFactory, this), collectionCache, itemCache); } else { InspectableChangeRecorder *changeRecorder = new InspectableChangeRecorder(depsFactory, this); changeRecorder->setChangeRecordingEnabled(false); testMonitor_impl(changeRecorder, collectionCache, itemCache); } } template void MonitorNotificationTest::testMonitor_impl(MonitorImpl *monitor, FakeCollectionCache *collectionCache, FakeItemCache *itemCache) { Q_UNUSED(itemCache) monitor->setSession(m_fakeSession); monitor->fetchCollection(true); Protocol::ChangeNotificationList list; Collection col2(2); col2.setParentCollection(Collection::root()); collectionCache->insert(col2); int i = 4; while (i < 8) { Collection added(i++); auto msg = Protocol::CollectionChangeNotificationPtr::create(); msg->setParentCollection(i % 2 ? 2 : added.id() - 1); msg->setOperation(Protocol::CollectionChangeNotification::Add); msg->setCollection(Protocol::FetchCollectionsResponsePtr::create(added.id())); + msg->addMetadata("FETCH_COLLECTION"); list << msg; } QVERIFY(monitor->pipeline().isEmpty()); QVERIFY(monitor->pendingNotifications().isEmpty()); Collection col4(4); col4.setParentCollection(col2); Collection col6(6); col6.setParentCollection(col2); collectionCache->insert(col4); collectionCache->insert(col6); qRegisterMetaType(); QSignalSpy collectionAddedSpy(monitor, SIGNAL(collectionAdded(Akonadi::Collection,Akonadi::Collection))); collectionCache->emitDataAvailable(); - QVERIFY(monitor->pipeline().isEmpty()); + QTRY_VERIFY(monitor->pipeline().isEmpty()); QVERIFY(monitor->pendingNotifications().isEmpty()); Q_FOREACH (const Protocol::ChangeNotificationPtr &ntf, list) { monitor->notificationConnection()->emitNotify(ntf); } // Collection 6 is not notified, because Collection 5 has held up the pipeline - QCOMPARE(collectionAddedSpy.size(), 1); + QTRY_COMPARE(collectionAddedSpy.size(), 1); QCOMPARE((int)collectionAddedSpy.takeFirst().first().value().id(), 4); QCOMPARE(monitor->pipeline().size(), 3); QCOMPARE(monitor->pendingNotifications().size(), 0); Collection col7(7); col7.setParentCollection(col6); collectionCache->insert(col7); collectionCache->emitDataAvailable(); // Collection 5 is still holding the pipeline QCOMPARE(collectionAddedSpy.size(), 0); QCOMPARE(monitor->pipeline().size(), 3); QCOMPARE(monitor->pendingNotifications().size(), 0); Collection col5(5); col5.setParentCollection(col4); collectionCache->insert(col5); collectionCache->emitDataAvailable(); // Collection 5 is in cache, pipeline is flushed QCOMPARE(collectionAddedSpy.size(), 3); QCOMPARE(monitor->pipeline().size(), 0); QCOMPARE(monitor->pendingNotifications().size(), 0); } QTEST_MAIN(MonitorNotificationTest) #include "monitornotificationtest.moc"