File indexing completed on 2024-11-10 04:40:21
0001 /* 0002 SPDX-FileCopyrightText: 2013 Daniel Vrátil <dvratil@redhat.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "aktest.h" 0008 0009 #include "entities.h" 0010 #include "notificationsubscriber.h" 0011 0012 #include <QObject> 0013 #include <QTest> 0014 0015 using namespace Akonadi; 0016 using namespace Akonadi::Server; 0017 0018 Q_DECLARE_METATYPE(QList<QString>) 0019 0020 class TestableNotificationSubscriber : public NotificationSubscriber 0021 { 0022 public: 0023 TestableNotificationSubscriber() 0024 { 0025 mSubscriber = "TestSubscriber"; 0026 } 0027 0028 void setAllMonitored(bool allMonitored) 0029 { 0030 mAllMonitored = allMonitored; 0031 } 0032 0033 void setMonitoredCollection(qint64 collection, bool monitored) 0034 { 0035 if (monitored) { 0036 mMonitoredCollections.insert(collection); 0037 } else { 0038 mMonitoredCollections.remove(collection); 0039 } 0040 } 0041 0042 void setMonitoredItem(qint64 item, bool monitored) 0043 { 0044 if (monitored) { 0045 mMonitoredItems.insert(item); 0046 } else { 0047 mMonitoredItems.remove(item); 0048 } 0049 } 0050 0051 void setMonitoredResource(const QByteArray &resource, bool monitored) 0052 { 0053 if (monitored) { 0054 mMonitoredResources.insert(resource); 0055 } else { 0056 mMonitoredResources.remove(resource); 0057 } 0058 } 0059 0060 void setMonitoredMimeType(const QString &mimeType, bool monitored) 0061 { 0062 if (monitored) { 0063 mMonitoredMimeTypes.insert(mimeType); 0064 } else { 0065 mMonitoredMimeTypes.remove(mimeType); 0066 } 0067 } 0068 0069 void setIgnoredSession(const QByteArray &session, bool ignored) 0070 { 0071 if (ignored) { 0072 mIgnoredSessions.insert(session); 0073 } else { 0074 mIgnoredSessions.remove(session); 0075 } 0076 } 0077 0078 void writeNotification(const Protocol::ChangeNotificationPtr ¬ification) override 0079 { 0080 emittedNotifications << notification; 0081 } 0082 0083 Protocol::ChangeNotificationList emittedNotifications; 0084 }; 0085 0086 class NotificationSubscriberTest : public QObject 0087 { 0088 Q_OBJECT 0089 0090 using NSList = QList<NotificationSubscriber *>; 0091 0092 Protocol::FetchItemsResponse itemResponse(qint64 id, const QString &rid, const QString &rrev, const QString &mt) 0093 { 0094 Protocol::FetchItemsResponse item; 0095 item.setId(id); 0096 item.setRemoteId(rid); 0097 item.setRemoteRevision(rrev); 0098 item.setMimeType(mt); 0099 return item; 0100 } 0101 0102 private Q_SLOTS: 0103 void testSourceFilter_data() 0104 { 0105 qRegisterMetaType<Protocol::ChangeNotificationList>(); 0106 0107 QTest::addColumn<bool>("allMonitored"); 0108 QTest::addColumn<QList<Entity::Id>>("monitoredCollections"); 0109 QTest::addColumn<QList<Entity::Id>>("monitoredItems"); 0110 QTest::addColumn<QList<QByteArray>>("monitoredResources"); 0111 QTest::addColumn<QList<QString>>("monitoredMimeTypes"); 0112 QTest::addColumn<QList<QByteArray>>("ignoredSessions"); 0113 QTest::addColumn<Protocol::ChangeNotificationPtr>("notification"); 0114 QTest::addColumn<bool>("accepted"); 0115 0116 #define EmptyList(T) (QList<T>()) 0117 #define List(T, x) (QList<T>() << (x)) 0118 0119 auto itemMsg = Protocol::ItemChangeNotificationPtr::create(); 0120 itemMsg->setOperation(Protocol::ItemChangeNotification::Add); 0121 itemMsg->setParentCollection(1); 0122 QTest::newRow("monitorAll vs notification without items") 0123 << true << EmptyList(Entity::Id) << EmptyList(Entity::Id) << EmptyList(QByteArray) << EmptyList(QString) << EmptyList(QByteArray) 0124 << itemMsg.staticCast<Protocol::ChangeNotification>() << false; 0125 0126 itemMsg = Protocol::ItemChangeNotificationPtr::create(*itemMsg); 0127 itemMsg->setItems({itemResponse(1, QString(), QString(), QStringLiteral("message/rfc822"))}); 0128 QTest::newRow("monitorAll vs notification with one item") 0129 << true << EmptyList(Entity::Id) << EmptyList(Entity::Id) << EmptyList(QByteArray) << EmptyList(QString) << EmptyList(QByteArray) 0130 << itemMsg.staticCast<Protocol::ChangeNotification>() << true; 0131 0132 QTest::newRow("item monitored but different mimetype") 0133 << false << EmptyList(Entity::Id) << List(Entity::Id, 1 << 2) << EmptyList(QByteArray) << List(QString, QStringLiteral("random/mimetype")) 0134 << EmptyList(QByteArray) << Protocol::ItemChangeNotificationPtr::create(*itemMsg).staticCast<Protocol::ChangeNotification>() << false; 0135 0136 QTest::newRow("item not monitored, but mimetype matches") 0137 << false << EmptyList(Entity::Id) << EmptyList(Entity::Id) << EmptyList(QByteArray) << List(QString, QStringLiteral("message/rfc822")) 0138 << EmptyList(QByteArray) << Protocol::ItemChangeNotificationPtr::create(*itemMsg).staticCast<Protocol::ChangeNotification>() << true; 0139 0140 itemMsg = Protocol::ItemChangeNotificationPtr::create(*itemMsg); 0141 itemMsg->setSessionId("testSession"); 0142 QTest::newRow("item monitored but session ignored") 0143 << false << EmptyList(Entity::Id) << List(Entity::Id, 1) << EmptyList(QByteArray) << EmptyList(QString) << List(QByteArray, "testSession") 0144 << itemMsg.staticCast<Protocol::ChangeNotification>() << false; 0145 0146 // Simulate adding a new resource 0147 auto colMsg = Protocol::CollectionChangeNotificationPtr::create(); 0148 colMsg->setOperation(Protocol::CollectionChangeNotification::Add); 0149 Protocol::FetchCollectionsResponse col; 0150 col.setId(1); 0151 col.setRemoteId(QStringLiteral("imap://user@some.domain/")); 0152 colMsg->setCollection(std::move(col)); 0153 colMsg->setParentCollection(0); 0154 colMsg->setSessionId("akonadi_imap_resource_0"); 0155 colMsg->setResource("akonadi_imap_resource_0"); 0156 QTest::newRow("new root collection in non-monitored resource") 0157 << false << List(Entity::Id, 0) << EmptyList(Entity::Id) << List(QByteArray, "akonadi_search_resource") 0158 << List(QString, QStringLiteral("message/rfc822")) << EmptyList(QByteArray) << colMsg.staticCast<Protocol::ChangeNotification>() << true; 0159 0160 itemMsg = Protocol::ItemChangeNotificationPtr::create(); 0161 itemMsg->setOperation(Protocol::ItemChangeNotification::Move); 0162 itemMsg->setResource("akonadi_resource_1"); 0163 itemMsg->setDestinationResource("akonadi_resource_2"); 0164 itemMsg->setParentCollection(1); 0165 itemMsg->setParentDestCollection(2); 0166 itemMsg->setSessionId("kmail"); 0167 itemMsg->setItems({itemResponse(10, QStringLiteral("123"), QStringLiteral("1"), QStringLiteral("message/rfc822"))}); 0168 QTest::newRow("inter-resource move, source source") << false << EmptyList(Entity::Id) << EmptyList(Entity::Id) << List(QByteArray, "akonadi_resource_1") 0169 << List(QString, QStringLiteral("message/rfc822")) << List(QByteArray, "akonadi_resource_1") 0170 << itemMsg.staticCast<Protocol::ChangeNotification>() << true; 0171 0172 QTest::newRow("inter-resource move, destination source") 0173 << false << EmptyList(Entity::Id) << EmptyList(Entity::Id) << List(QByteArray, "akonadi_resource_2") 0174 << List(QString, QStringLiteral("message/rfc822")) << List(QByteArray, "akonadi_resource_2") << itemMsg.staticCast<Protocol::ChangeNotification>() 0175 << true; 0176 0177 QTest::newRow("inter-resource move, uninterested party") 0178 << false << List(Entity::Id, 12) << EmptyList(Entity::Id) << EmptyList(QByteArray) << List(QString, QStringLiteral("inode/directory")) 0179 << EmptyList(QByteArray) << itemMsg.staticCast<Protocol::ChangeNotification>() << false; 0180 0181 itemMsg = Protocol::ItemChangeNotificationPtr::create(); 0182 itemMsg->setOperation(Protocol::ItemChangeNotification::Move); 0183 itemMsg->setResource("akonadi_resource_0"); 0184 itemMsg->setDestinationResource("akonadi_resource_0"); 0185 itemMsg->setParentCollection(1); 0186 itemMsg->setParentDestCollection(2); 0187 itemMsg->setSessionId("kmail"); 0188 itemMsg->setItems({itemResponse(10, QStringLiteral("123"), QStringLiteral("1"), QStringLiteral("message/rfc822")), 0189 itemResponse(11, QStringLiteral("456"), QStringLiteral("1"), QStringLiteral("message/rfc822"))}); 0190 QTest::newRow("intra-resource move, owning resource") 0191 << false << EmptyList(Entity::Id) << EmptyList(Entity::Id) << List(QByteArray, "akonadi_imap_resource_0") 0192 << List(QString, QStringLiteral("message/rfc822")) << List(QByteArray, "akonadi_imap_resource_0") 0193 << itemMsg.staticCast<Protocol::ChangeNotification>() << true; 0194 0195 colMsg = Protocol::CollectionChangeNotificationPtr::create(); 0196 colMsg->setOperation(Protocol::CollectionChangeNotification::Add); 0197 colMsg->setSessionId("kmail"); 0198 colMsg->setResource("akonadi_resource_1"); 0199 colMsg->setParentCollection(1); 0200 QTest::newRow("new subfolder") << false << List(Entity::Id, 0) << EmptyList(Entity::Id) << EmptyList(QByteArray) 0201 << List(QString, QStringLiteral("message/rfc822")) << EmptyList(QByteArray) 0202 << colMsg.staticCast<Protocol::ChangeNotification>() << false; 0203 0204 itemMsg = Protocol::ItemChangeNotificationPtr::create(); 0205 itemMsg->setOperation(Protocol::ItemChangeNotification::Add); 0206 itemMsg->setSessionId("randomSession"); 0207 itemMsg->setResource("randomResource"); 0208 itemMsg->setParentCollection(1); 0209 itemMsg->setItems({itemResponse(10, QString(), QString(), QStringLiteral("message/rfc822"))}); 0210 QTest::newRow("new mail for mailfilter or maildispatcher") 0211 << false << List(Entity::Id, 0) << EmptyList(Entity::Id) << EmptyList(QByteArray) << List(QString, QStringLiteral("message/rfc822")) 0212 << EmptyList(QByteArray) << itemMsg.staticCast<Protocol::ChangeNotification>() << true; 0213 0214 auto tagMsg = Protocol::TagChangeNotificationPtr::create(); 0215 tagMsg->setOperation(Protocol::TagChangeNotification::Remove); 0216 tagMsg->setSessionId("randomSession"); 0217 tagMsg->setResource("akonadi_random_resource_0"); 0218 { 0219 Protocol::FetchTagsResponse tagMsgTag; 0220 tagMsgTag.setId(1); 0221 tagMsgTag.setRemoteId("TAG"); 0222 tagMsg->setTag(std::move(tagMsgTag)); 0223 } 0224 QTest::newRow("Tag removal - resource notification - matching resource source") 0225 << false << EmptyList(Entity::Id) << EmptyList(Entity::Id) << EmptyList(QByteArray) << EmptyList(QString) 0226 << List(QByteArray, "akonadi_random_resource_0") << tagMsg.staticCast<Protocol::ChangeNotification>() << true; 0227 0228 QTest::newRow("Tag removal - resource notification - wrong resource source") 0229 << false << EmptyList(Entity::Id) << EmptyList(Entity::Id) << EmptyList(QByteArray) << EmptyList(QString) 0230 << List(QByteArray, "akonadi_another_resource_1") << tagMsg.staticCast<Protocol::ChangeNotification>() << false; 0231 0232 tagMsg = Protocol::TagChangeNotificationPtr::create(); 0233 tagMsg->setOperation(Protocol::TagChangeNotification::Remove); 0234 tagMsg->setSessionId("randomSession"); 0235 { 0236 Protocol::FetchTagsResponse tagMsgTag; 0237 tagMsgTag.setId(1); 0238 tagMsgTag.setRemoteId("TAG"); 0239 tagMsg->setTag(std::move(tagMsgTag)); 0240 } 0241 QTest::newRow("Tag removal - client notification - client source") 0242 << false << EmptyList(Entity::Id) << EmptyList(Entity::Id) << EmptyList(QByteArray) << EmptyList(QString) << EmptyList(QByteArray) 0243 << tagMsg.staticCast<Protocol::ChangeNotification>() << true; 0244 0245 QTest::newRow("Tag removal - client notification - resource source") 0246 << false << EmptyList(Entity::Id) << EmptyList(Entity::Id) << EmptyList(QByteArray) << EmptyList(QString) 0247 << List(QByteArray, "akonadi_some_resource_0") << tagMsg.staticCast<Protocol::ChangeNotification>() << false; 0248 } 0249 0250 void testSourceFilter() 0251 { 0252 QFETCH(bool, allMonitored); 0253 QFETCH(QList<Entity::Id>, monitoredCollections); 0254 QFETCH(QList<Entity::Id>, monitoredItems); 0255 QFETCH(QList<QByteArray>, monitoredResources); 0256 QFETCH(QList<QString>, monitoredMimeTypes); 0257 QFETCH(QList<QByteArray>, ignoredSessions); 0258 QFETCH(Protocol::ChangeNotificationPtr, notification); 0259 QFETCH(bool, accepted); 0260 0261 TestableNotificationSubscriber subscriber; 0262 0263 subscriber.setAllMonitored(allMonitored); 0264 for (Entity::Id id : monitoredCollections) { 0265 subscriber.setMonitoredCollection(id, true); 0266 } 0267 for (Entity::Id id : monitoredItems) { 0268 subscriber.setMonitoredItem(id, true); 0269 } 0270 for (const QByteArray &res : monitoredResources) { 0271 subscriber.setMonitoredResource(res, true); 0272 } 0273 for (const QString &mimeType : monitoredMimeTypes) { 0274 subscriber.setMonitoredMimeType(mimeType, true); 0275 } 0276 for (const QByteArray &session : ignoredSessions) { 0277 subscriber.setIgnoredSession(session, true); 0278 } 0279 0280 subscriber.notify({notification}); 0281 0282 QTRY_COMPARE(subscriber.emittedNotifications.count(), accepted ? 1 : 0); 0283 0284 if (accepted) { 0285 const Protocol::ChangeNotificationPtr ntf = subscriber.emittedNotifications.at(0); 0286 QVERIFY(ntf->isValid()); 0287 } 0288 } 0289 }; 0290 0291 AKTEST_MAIN(NotificationSubscriberTest) 0292 0293 #include "notificationsubscribertest.moc"