File indexing completed on 2024-11-10 04:40:14
0001 /* 0002 SPDX-FileCopyrightText: 2006 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "monitortest.h" 0008 #include "agentinstance.h" 0009 #include "agentmanager.h" 0010 #include "collectioncreatejob.h" 0011 #include "collectiondeletejob.h" 0012 #include "collectionfetchjob.h" 0013 #include "collectionmodifyjob.h" 0014 #include "collectionmovejob.h" 0015 #include "collectionstatistics.h" 0016 #include "control.h" 0017 #include "itemcreatejob.h" 0018 #include "itemdeletejob.h" 0019 #include "itemfetchjob.h" 0020 #include "itemfetchscope.h" 0021 #include "itemmodifyjob.h" 0022 #include "itemmovejob.h" 0023 #include "monitor.h" 0024 #include "qtest_akonadi.h" 0025 #include "searchcreatejob.h" 0026 #include "searchquery.h" 0027 #include "subscriptionjob_p.h" 0028 0029 #include <QSignalSpy> 0030 #include <QVariant> 0031 0032 using namespace Akonadi; 0033 0034 QTEST_AKONADIMAIN(MonitorTest) 0035 0036 static Collection res3; 0037 0038 Q_DECLARE_METATYPE(Akonadi::Collection::Id) 0039 Q_DECLARE_METATYPE(QSet<QByteArray>) 0040 0041 void MonitorTest::initTestCase() 0042 { 0043 AkonadiTest::checkTestIsIsolated(); 0044 Control::start(); 0045 0046 res3 = Collection(AkonadiTest::collectionIdFromPath(QStringLiteral("res3"))); 0047 0048 AkonadiTest::setAllResourcesOffline(); 0049 } 0050 0051 void MonitorTest::testMonitor_data() 0052 { 0053 QTest::addColumn<bool>("fetchCol"); 0054 QTest::newRow("with collection fetching") << true; 0055 QTest::newRow("without collection fetching") << false; 0056 } 0057 0058 void MonitorTest::testMonitor() 0059 { 0060 QFETCH(bool, fetchCol); 0061 0062 Monitor monitor; 0063 monitor.setCollectionMonitored(Collection::root()); 0064 monitor.fetchCollection(fetchCol); 0065 monitor.itemFetchScope().fetchFullPayload(); 0066 monitor.itemFetchScope().setCacheOnly(true); 0067 QVERIFY(AkonadiTest::akWaitForSignal(&monitor, &Monitor::monitorReady)); 0068 0069 // monitor signals 0070 qRegisterMetaType<Akonadi::Collection>(); 0071 /* 0072 qRegisterMetaType<Akonadi::Collection::Id>() registers the type with a 0073 name of "qlonglong". Doing 0074 qRegisterMetaType<Akonadi::Collection::Id>( "Akonadi::Collection::Id" ) 0075 doesn't help. (works now , see QTBUG-937 and QTBUG-6833, -- dvratil) 0076 0077 The problem here is that Akonadi::Collection::Id is a typedef to qlonglong, 0078 and qlonglong is already a registered meta type. So the signal spy will 0079 give us a QVariant of type Akonadi::Collection::Id, but calling 0080 .value<Akonadi::Collection::Id>() on that variant will in fact end up 0081 calling qvariant_cast<qlonglong>. From the point of view of QMetaType, 0082 Akonadi::Collection::Id and qlonglong are different types, so QVariant 0083 can't convert, and returns a default-constructed qlonglong, zero. 0084 0085 When connecting to a real slot (without QSignalSpy), this problem is 0086 avoided, because the casting is done differently (via a lot of void 0087 pointers). 0088 0089 The docs say nothing about qRegisterMetaType -ing a typedef, so I'm not 0090 sure if this is a bug or not. (cberzan) 0091 */ 0092 qRegisterMetaType<Akonadi::Collection::Id>("Akonadi::Collection::Id"); 0093 qRegisterMetaType<Akonadi::Item>(); 0094 qRegisterMetaType<Akonadi::CollectionStatistics>(); 0095 qRegisterMetaType<QSet<QByteArray>>(); 0096 QSignalSpy caddspy(&monitor, &Monitor::collectionAdded); 0097 QSignalSpy cmodspy(&monitor, SIGNAL(collectionChanged(Akonadi::Collection, QSet<QByteArray>))); 0098 QSignalSpy cmvspy(&monitor, &Monitor::collectionMoved); 0099 QSignalSpy crmspy(&monitor, &Monitor::collectionRemoved); 0100 QSignalSpy cstatspy(&monitor, &Monitor::collectionStatisticsChanged); 0101 QSignalSpy cSubscribedSpy(&monitor, &Monitor::collectionSubscribed); 0102 QSignalSpy cUnsubscribedSpy(&monitor, &Monitor::collectionUnsubscribed); 0103 QSignalSpy iaddspy(&monitor, &Monitor::itemAdded); 0104 QSignalSpy imodspy(&monitor, &Monitor::itemChanged); 0105 QSignalSpy imvspy(&monitor, &Monitor::itemMoved); 0106 QSignalSpy irmspy(&monitor, &Monitor::itemRemoved); 0107 0108 QVERIFY(caddspy.isValid()); 0109 QVERIFY(cmodspy.isValid()); 0110 QVERIFY(cmvspy.isValid()); 0111 QVERIFY(crmspy.isValid()); 0112 QVERIFY(cstatspy.isValid()); 0113 QVERIFY(cSubscribedSpy.isEmpty()); 0114 QVERIFY(cUnsubscribedSpy.isEmpty()); 0115 QVERIFY(iaddspy.isValid()); 0116 QVERIFY(imodspy.isValid()); 0117 QVERIFY(imvspy.isValid()); 0118 QVERIFY(irmspy.isValid()); 0119 0120 // create a collection 0121 Collection monitorCol; 0122 monitorCol.setParentCollection(res3); 0123 monitorCol.setName(QStringLiteral("monitor")); 0124 auto create = new CollectionCreateJob(monitorCol, this); 0125 AKVERIFYEXEC(create); 0126 monitorCol = create->collection(); 0127 QVERIFY(monitorCol.isValid()); 0128 0129 QTRY_COMPARE(caddspy.count(), 1); 0130 QList<QVariant> arg = caddspy.takeFirst(); 0131 auto col = arg.at(0).value<Collection>(); 0132 QCOMPARE(col, monitorCol); 0133 if (fetchCol) { 0134 QCOMPARE(col.name(), QStringLiteral("monitor")); 0135 } 0136 auto parent = arg.at(1).value<Collection>(); 0137 QCOMPARE(parent, res3); 0138 0139 QVERIFY(cmodspy.isEmpty()); 0140 QVERIFY(cmvspy.isEmpty()); 0141 QVERIFY(crmspy.isEmpty()); 0142 QVERIFY(cstatspy.isEmpty()); 0143 QVERIFY(cSubscribedSpy.isEmpty()); 0144 QVERIFY(cUnsubscribedSpy.isEmpty()); 0145 QVERIFY(iaddspy.isEmpty()); 0146 QVERIFY(imodspy.isEmpty()); 0147 QVERIFY(imvspy.isEmpty()); 0148 QVERIFY(irmspy.isEmpty()); 0149 0150 // add an item 0151 Item newItem; 0152 newItem.setMimeType(QStringLiteral("application/octet-stream")); 0153 auto append = new ItemCreateJob(newItem, monitorCol, this); 0154 AKVERIFYEXEC(append); 0155 Item monitorRef = append->item(); 0156 QVERIFY(monitorRef.isValid()); 0157 0158 QTRY_COMPARE(cstatspy.count(), 1); 0159 arg = cstatspy.takeFirst(); 0160 QCOMPARE(arg.at(0).value<Akonadi::Collection::Id>(), monitorCol.id()); 0161 0162 QCOMPARE(iaddspy.count(), 1); 0163 arg = iaddspy.takeFirst(); 0164 Item item = arg.at(0).value<Item>(); 0165 QCOMPARE(item, monitorRef); 0166 QCOMPARE(item.mimeType(), QString::fromLatin1("application/octet-stream")); 0167 auto collection = arg.at(1).value<Collection>(); 0168 QCOMPARE(collection.id(), monitorCol.id()); 0169 0170 QVERIFY(caddspy.isEmpty()); 0171 QVERIFY(cmodspy.isEmpty()); 0172 QVERIFY(cmvspy.isEmpty()); 0173 QVERIFY(crmspy.isEmpty()); 0174 QVERIFY(cSubscribedSpy.isEmpty()); 0175 QVERIFY(cUnsubscribedSpy.isEmpty()); 0176 QVERIFY(imodspy.isEmpty()); 0177 QVERIFY(imvspy.isEmpty()); 0178 QVERIFY(irmspy.isEmpty()); 0179 0180 // modify an item 0181 item.setPayload<QByteArray>("some new content"); 0182 auto store = new ItemModifyJob(item, this); 0183 AKVERIFYEXEC(store); 0184 0185 QTRY_COMPARE(cstatspy.count(), 1); 0186 arg = cstatspy.takeFirst(); 0187 QCOMPARE(arg.at(0).value<Collection::Id>(), monitorCol.id()); 0188 0189 QCOMPARE(imodspy.count(), 1); 0190 arg = imodspy.takeFirst(); 0191 item = arg.at(0).value<Item>(); 0192 QCOMPARE(monitorRef, item); 0193 QVERIFY(item.hasPayload<QByteArray>()); 0194 QCOMPARE(item.payload<QByteArray>(), QByteArray("some new content")); 0195 auto parts = arg.at(1).value<QSet<QByteArray>>(); 0196 QCOMPARE(parts, QSet<QByteArray>() << "PLD:RFC822"); 0197 0198 QVERIFY(caddspy.isEmpty()); 0199 QVERIFY(cmodspy.isEmpty()); 0200 QVERIFY(cmvspy.isEmpty()); 0201 QVERIFY(crmspy.isEmpty()); 0202 QVERIFY(cSubscribedSpy.isEmpty()); 0203 QVERIFY(cUnsubscribedSpy.isEmpty()); 0204 QVERIFY(iaddspy.isEmpty()); 0205 QVERIFY(imvspy.isEmpty()); 0206 QVERIFY(irmspy.isEmpty()); 0207 0208 // move an item 0209 auto move = new ItemMoveJob(item, res3); 0210 AKVERIFYEXEC(move); 0211 QTRY_COMPARE(cstatspy.count(), 2); 0212 // NOTE: We don't make any assumptions about the order of the collectionStatisticsChanged 0213 // signals, they seem to arrive in random order 0214 QList<Collection::Id> notifiedCols; 0215 notifiedCols << cstatspy.takeFirst().at(0).value<Collection::Id>() << cstatspy.takeFirst().at(0).value<Collection::Id>(); 0216 QVERIFY(notifiedCols.contains(res3.id())); // destination 0217 QVERIFY(notifiedCols.contains(monitorCol.id())); // source 0218 0219 QCOMPARE(imvspy.count(), 1); 0220 arg = imvspy.takeFirst(); 0221 item = arg.at(0).value<Item>(); // the item 0222 QCOMPARE(monitorRef, item); 0223 col = arg.at(1).value<Collection>(); // the source collection 0224 QCOMPARE(col.id(), monitorCol.id()); 0225 col = arg.at(2).value<Collection>(); // the destination collection 0226 QCOMPARE(col.id(), res3.id()); 0227 0228 QVERIFY(caddspy.isEmpty()); 0229 QVERIFY(cmodspy.isEmpty()); 0230 QVERIFY(cmvspy.isEmpty()); 0231 QVERIFY(crmspy.isEmpty()); 0232 QVERIFY(cSubscribedSpy.isEmpty()); 0233 QVERIFY(cUnsubscribedSpy.isEmpty()); 0234 QVERIFY(iaddspy.isEmpty()); 0235 QVERIFY(imodspy.isEmpty()); 0236 QVERIFY(irmspy.isEmpty()); 0237 0238 // delete an item 0239 auto del = new ItemDeleteJob(monitorRef, this); 0240 AKVERIFYEXEC(del); 0241 0242 QTRY_COMPARE(cstatspy.count(), 1); 0243 arg = cstatspy.takeFirst(); 0244 QCOMPARE(arg.at(0).value<Collection::Id>(), res3.id()); 0245 cmodspy.clear(); 0246 0247 QCOMPARE(irmspy.count(), 1); 0248 arg = irmspy.takeFirst(); 0249 Item ref = qvariant_cast<Item>(arg.at(0)); 0250 QCOMPARE(monitorRef, ref); 0251 QCOMPARE(ref.parentCollection(), res3); 0252 0253 QVERIFY(caddspy.isEmpty()); 0254 QVERIFY(cmodspy.isEmpty()); 0255 QVERIFY(cmvspy.isEmpty()); 0256 QVERIFY(crmspy.isEmpty()); 0257 QVERIFY(cSubscribedSpy.isEmpty()); 0258 QVERIFY(cUnsubscribedSpy.isEmpty()); 0259 QVERIFY(iaddspy.isEmpty()); 0260 QVERIFY(imodspy.isEmpty()); 0261 QVERIFY(imvspy.isEmpty()); 0262 imvspy.clear(); 0263 0264 // Unsubscribe and re-subscribed a collection that existed before the monitor was created. 0265 Collection subCollection = Collection(AkonadiTest::collectionIdFromPath(QStringLiteral("res2/foo2"))); 0266 subCollection.setName(QStringLiteral("foo2")); 0267 QVERIFY(subCollection.isValid()); 0268 0269 auto subscribeJob = new SubscriptionJob(this); 0270 subscribeJob->unsubscribe(Collection::List() << subCollection); 0271 AKVERIFYEXEC(subscribeJob); 0272 // Wait for unsubscribed signal, it goes after changed, so we can check for both 0273 QTRY_COMPARE(cmodspy.size(), 1); 0274 arg = cmodspy.takeFirst(); 0275 col = arg.at(0).value<Collection>(); 0276 QCOMPARE(col.id(), subCollection.id()); 0277 0278 QVERIFY(cSubscribedSpy.isEmpty()); 0279 QTRY_COMPARE(cUnsubscribedSpy.size(), 1); 0280 arg = cUnsubscribedSpy.takeFirst(); 0281 col = arg.at(0).value<Collection>(); 0282 QCOMPARE(col.id(), subCollection.id()); 0283 0284 subscribeJob = new SubscriptionJob(this); 0285 subscribeJob->subscribe(Collection::List() << subCollection); 0286 AKVERIFYEXEC(subscribeJob); 0287 // Wait for subscribed signal, it goes after changed, so we can check for both 0288 QTRY_COMPARE(cmodspy.size(), 1); 0289 arg = cmodspy.takeFirst(); 0290 col = arg.at(0).value<Collection>(); 0291 QCOMPARE(col.id(), subCollection.id()); 0292 0293 QVERIFY(cUnsubscribedSpy.isEmpty()); 0294 QTRY_COMPARE(cSubscribedSpy.size(), 1); 0295 arg = cSubscribedSpy.takeFirst(); 0296 col = arg.at(0).value<Collection>(); 0297 QCOMPARE(col.id(), subCollection.id()); 0298 if (fetchCol) { 0299 QVERIFY(!col.name().isEmpty()); 0300 QCOMPARE(col.name(), subCollection.name()); 0301 } 0302 0303 QVERIFY(caddspy.isEmpty()); 0304 QVERIFY(cmodspy.isEmpty()); 0305 QVERIFY(cmvspy.isEmpty()); 0306 QVERIFY(crmspy.isEmpty()); 0307 QVERIFY(cstatspy.isEmpty()); 0308 QVERIFY(iaddspy.isEmpty()); 0309 QVERIFY(imodspy.isEmpty()); 0310 QVERIFY(imvspy.isEmpty()); 0311 QVERIFY(irmspy.isEmpty()); 0312 0313 // modify a collection 0314 monitorCol.setName(QStringLiteral("changed name")); 0315 auto mod = new CollectionModifyJob(monitorCol, this); 0316 AKVERIFYEXEC(mod); 0317 0318 QTRY_COMPARE(cmodspy.count(), 1); 0319 arg = cmodspy.takeFirst(); 0320 col = arg.at(0).value<Collection>(); 0321 QCOMPARE(col, monitorCol); 0322 if (fetchCol) { 0323 QCOMPARE(col.name(), QStringLiteral("changed name")); 0324 } 0325 0326 QVERIFY(caddspy.isEmpty()); 0327 QVERIFY(cmvspy.isEmpty()); 0328 QVERIFY(crmspy.isEmpty()); 0329 QVERIFY(cstatspy.isEmpty()); 0330 QVERIFY(cSubscribedSpy.isEmpty()); 0331 QVERIFY(cUnsubscribedSpy.isEmpty()); 0332 QVERIFY(iaddspy.isEmpty()); 0333 QVERIFY(imodspy.isEmpty()); 0334 QVERIFY(imvspy.isEmpty()); 0335 QVERIFY(irmspy.isEmpty()); 0336 0337 // move a collection 0338 Collection dest = Collection(AkonadiTest::collectionIdFromPath(QStringLiteral("res1/foo"))); 0339 auto cmove = new CollectionMoveJob(monitorCol, dest, this); 0340 AKVERIFYEXEC(cmove); 0341 0342 QTRY_COMPARE(cmvspy.count(), 1); 0343 arg = cmvspy.takeFirst(); 0344 col = arg.at(0).value<Collection>(); 0345 QCOMPARE(col, monitorCol); 0346 QCOMPARE(col.parentCollection(), dest); 0347 if (fetchCol) { 0348 QCOMPARE(col.name(), monitorCol.name()); 0349 } 0350 col = arg.at(1).value<Collection>(); 0351 QCOMPARE(col, res3); 0352 col = arg.at(2).value<Collection>(); 0353 QCOMPARE(col, dest); 0354 0355 QVERIFY(caddspy.isEmpty()); 0356 QVERIFY(cmodspy.isEmpty()); 0357 QVERIFY(crmspy.isEmpty()); 0358 QVERIFY(cstatspy.isEmpty()); 0359 QVERIFY(cSubscribedSpy.isEmpty()); 0360 QVERIFY(cUnsubscribedSpy.isEmpty()); 0361 QVERIFY(iaddspy.isEmpty()); 0362 QVERIFY(imodspy.isEmpty()); 0363 QVERIFY(imvspy.isEmpty()); 0364 QVERIFY(irmspy.isEmpty()); 0365 0366 // delete a collection 0367 auto cdel = new CollectionDeleteJob(monitorCol, this); 0368 AKVERIFYEXEC(cdel); 0369 0370 QTRY_COMPARE(crmspy.count(), 1); 0371 arg = crmspy.takeFirst(); 0372 col = arg.at(0).value<Collection>(); 0373 QCOMPARE(col.id(), monitorCol.id()); 0374 QCOMPARE(col.parentCollection(), dest); 0375 0376 QVERIFY(caddspy.isEmpty()); 0377 QVERIFY(cmodspy.isEmpty()); 0378 QVERIFY(cmvspy.isEmpty()); 0379 QVERIFY(cstatspy.isEmpty()); 0380 QVERIFY(cSubscribedSpy.isEmpty()); 0381 QVERIFY(cUnsubscribedSpy.isEmpty()); 0382 QVERIFY(iaddspy.isEmpty()); 0383 QVERIFY(imodspy.isEmpty()); 0384 QVERIFY(imvspy.isEmpty()); 0385 QVERIFY(irmspy.isEmpty()); 0386 } 0387 0388 void MonitorTest::testVirtualCollectionsMonitoring() 0389 { 0390 Monitor monitor; 0391 monitor.setCollectionMonitored(Collection(1)); // top-level 'Search' collection 0392 QVERIFY(AkonadiTest::akWaitForSignal(&monitor, &Monitor::monitorReady)); 0393 0394 QSignalSpy caddspy(&monitor, &Monitor::collectionAdded); 0395 0396 auto job = new SearchCreateJob(QStringLiteral("Test search collection"), Akonadi::SearchQuery(), this); 0397 AKVERIFYEXEC(job); 0398 QTRY_COMPARE(caddspy.count(), 1); 0399 } 0400 0401 #include "moc_monitortest.cpp"