1 /*
2     SPDX-FileCopyrightText: 2010 Volker Krause <vkrause@kde.org>
3 
4     SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include <QObject>
8 
9 #include "monitor_p.h"
10 #include <QTest>
11 #include <qtest_akonadi.h>
12 
13 using namespace Akonadi;
14 
15 Q_DECLARE_METATYPE(Akonadi::Protocol::ChangeNotification::Operation)
16 Q_DECLARE_METATYPE(QSet<QByteArray>)
17 
18 class MonitorFilterTest : public QObject
19 {
20     Q_OBJECT
21 private Q_SLOTS:
initTestCase()22     void initTestCase()
23     {
24         AkonadiTest::checkTestIsIsolated();
25         qRegisterMetaType<Akonadi::Item>();
26         qRegisterMetaType<Akonadi::Collection>();
27         qRegisterMetaType<QSet<QByteArray>>();
28         qRegisterMetaType<Akonadi::Item::List>();
29     }
30 
filterConnected_data()31     void filterConnected_data()
32     {
33         QTest::addColumn<Akonadi::Protocol::ChangeNotification::Operation>("op");
34         QTest::addColumn<QByteArray>("signalName");
35 
36         QTest::newRow("itemAdded") << Protocol::ChangeNotification::Add << QByteArray(SIGNAL(itemAdded(Akonadi::Item, Akonadi::Collection)));
37         QTest::newRow("itemChanged") << Protocol::ChangeNotification::Modify << QByteArray(SIGNAL(itemChanged(Akonadi::Item, QSet<QByteArray>)));
38         QTest::newRow("itemsFlagsChanged") << Protocol::ChangeNotification::ModifyFlags
39                                            << QByteArray(SIGNAL(itemsFlagsChanged(Akonadi::Item::List, QSet<QByteArray>, QSet<QByteArray>)));
40         QTest::newRow("itemRemoved") << Protocol::ChangeNotification::Remove << QByteArray(SIGNAL(itemRemoved(Akonadi::Item)));
41         QTest::newRow("itemMoved") << Protocol::ChangeNotification::Move
42                                    << QByteArray(SIGNAL(itemMoved(Akonadi::Item, Akonadi::Collection, Akonadi::Collection)));
43         QTest::newRow("itemLinked") << Protocol::ChangeNotification::Link << QByteArray(SIGNAL(itemLinked(Akonadi::Item, Akonadi::Collection)));
44         QTest::newRow("itemUnlinked") << Protocol::ChangeNotification::Unlink << QByteArray(SIGNAL(itemUnlinked(Akonadi::Item, Akonadi::Collection)));
45     }
46 
filterConnected()47     void filterConnected()
48     {
49         QFETCH(Protocol::ChangeNotification::Operation, op);
50         QFETCH(QByteArray, signalName);
51 
52         Monitor dummyMonitor;
53         MonitorPrivate m(0, &dummyMonitor);
54 
55         Protocol::ChangeNotification msg;
56         msg.addEntity(1);
57         msg.setOperation(op);
58         msg.setType(Akonadi::Protocol::ChangeNotification::Items);
59 
60         QVERIFY(!m.acceptNotification(msg));
61         m.monitorAll = true;
62         QVERIFY(m.acceptNotification(msg));
63         QSignalSpy spy(&dummyMonitor, signalName.constData());
64         QVERIFY(spy.isValid());
65         QVERIFY(m.acceptNotification(msg));
66         m.monitorAll = false;
67         QVERIFY(!m.acceptNotification(msg));
68     }
69 
filterSession()70     void filterSession()
71     {
72         Monitor dummyMonitor;
73         MonitorPrivate m(0, &dummyMonitor);
74         m.monitorAll = true;
75         QSignalSpy spy(&dummyMonitor, &Monitor::itemAdded);
76 
77         Protocol::ChangeNotification msg;
78         msg.addEntity(1);
79         msg.setOperation(Protocol::ChangeNotification::Add);
80         msg.setType(Akonadi::Protocol::ChangeNotification::Items);
81         msg.setSessionId("foo");
82 
83         QVERIFY(m.acceptNotification(msg));
84         m.sessions.append("bar");
85         QVERIFY(m.acceptNotification(msg));
86         m.sessions.append("foo");
87         QVERIFY(!m.acceptNotification(msg));
88     }
89 
filterResource_data()90     void filterResource_data()
91     {
92         QTest::addColumn<Akonadi::Protocol::ChangeNotification::Operation>("op");
93         QTest::addColumn<Akonadi::Protocol::ChangeNotification::Type>("type");
94         QTest::addColumn<QByteArray>("signalName");
95 
96         QTest::newRow("itemAdded") << Protocol::ChangeNotification::Add << Protocol::ChangeNotification::Items
97                                    << QByteArray(SIGNAL(itemAdded(Akonadi::Item, Akonadi::Collection)));
98         QTest::newRow("itemChanged") << Protocol::ChangeNotification::Modify << Protocol::ChangeNotification::Items
99                                      << QByteArray(SIGNAL(itemChanged(Akonadi::Item, QSet<QByteArray>)));
100         QTest::newRow("itemsFlagsChanged") << Protocol::ChangeNotification::ModifyFlags << Protocol::ChangeNotification::Items
101                                            << QByteArray(SIGNAL(itemsFlagsChanged(Akonadi::Item::List, QSet<QByteArray>, QSet<QByteArray>)));
102         QTest::newRow("itemRemoved") << Protocol::ChangeNotification::Remove << Protocol::ChangeNotification::Items
103                                      << QByteArray(SIGNAL(itemRemoved(Akonadi::Item)));
104         QTest::newRow("itemMoved") << Protocol::ChangeNotification::Move << Protocol::ChangeNotification::Items
105                                    << QByteArray(SIGNAL(itemMoved(Akonadi::Item, Akonadi::Collection, Akonadi::Collection)));
106         QTest::newRow("itemLinked") << Protocol::ChangeNotification::Link << Protocol::ChangeNotification::Items
107                                     << QByteArray(SIGNAL(itemLinked(Akonadi::Item, Akonadi::Collection)));
108         QTest::newRow("itemUnlinked") << Protocol::ChangeNotification::Unlink << Protocol::ChangeNotification::Items
109                                       << QByteArray(SIGNAL(itemUnlinked(Akonadi::Item, Akonadi::Collection)));
110 
111         QTest::newRow("colAdded") << Protocol::ChangeNotification::Add << Protocol::ChangeNotification::Collections
112                                   << QByteArray(SIGNAL(collectionAdded(Akonadi::Collection, Akonadi::Collection)));
113         QTest::newRow("colChanged") << Protocol::ChangeNotification::Modify << Protocol::ChangeNotification::Collections
114                                     << QByteArray(SIGNAL(collectionChanged(Akonadi::Collection, QSet<QByteArray>)));
115         QTest::newRow("colRemoved") << Protocol::ChangeNotification::Remove << Protocol::ChangeNotification::Collections
116                                     << QByteArray(SIGNAL(collectionRemoved(Akonadi::Collection)));
117         QTest::newRow("colMoved") << Protocol::ChangeNotification::Move << Protocol::ChangeNotification::Collections
118                                   << QByteArray(SIGNAL(collectionMoved(Akonadi::Collection, Akonadi::Collection, Akonadi::Collection)));
119         QTest::newRow("colSubscribed") << Protocol::ChangeNotification::Subscribe << Protocol::ChangeNotification::Collections
120                                        << QByteArray(SIGNAL(collectionSubscribed(Akonadi::Collection, Akonadi::Collection)));
121         QTest::newRow("colSubscribed") << Protocol::ChangeNotification::Unsubscribe << Protocol::ChangeNotification::Collections
122                                        << QByteArray(SIGNAL(collectionUnsubscribed(Akonadi::Collection)));
123     }
124 
filterResource()125     void filterResource()
126     {
127         QFETCH(Protocol::ChangeNotification::Operation, op);
128         QFETCH(Protocol::ChangeNotification::Type, type);
129         QFETCH(QByteArray, signalName);
130 
131         Monitor dummyMonitor;
132         MonitorPrivate m(0, &dummyMonitor);
133         QSignalSpy spy(&dummyMonitor, signalName.constData());
134         QVERIFY(spy.isValid());
135 
136         Protocol::ChangeNotification msg;
137         msg.addEntity(1);
138         msg.setOperation(op);
139         msg.setParentCollection(2);
140         msg.setType(type);
141         msg.setResource("foo");
142         msg.setSessionId("mysession");
143 
144         // using the right resource makes it pass
145         QVERIFY(!m.acceptNotification(msg));
146         m.resources.insert("bar");
147         QVERIFY(!m.acceptNotification(msg));
148         m.resources.insert("foo");
149         QVERIFY(m.acceptNotification(msg));
150 
151         // filtering out the session overwrites the resource
152         m.sessions.append("mysession");
153         QVERIFY(!m.acceptNotification(msg));
154     }
155 
filterDestinationResource_data()156     void filterDestinationResource_data()
157     {
158         QTest::addColumn<Akonadi::Protocol::ChangeNotification::Operation>("op");
159         QTest::addColumn<Akonadi::Protocol::ChangeNotification::Type>("type");
160         QTest::addColumn<QByteArray>("signalName");
161 
162         QTest::newRow("itemMoved") << Protocol::ChangeNotification::Move << Protocol::ChangeNotification::Items
163                                    << QByteArray(SIGNAL(itemMoved(Akonadi::Item, Akonadi::Collection, Akonadi::Collection)));
164         QTest::newRow("colMoved") << Protocol::ChangeNotification::Move << Protocol::ChangeNotification::Collections
165                                   << QByteArray(SIGNAL(collectionMoved(Akonadi::Collection, Akonadi::Collection, Akonadi::Collection)));
166     }
167 
filterDestinationResource()168     void filterDestinationResource()
169     {
170         QFETCH(Protocol::ChangeNotification::Operation, op);
171         QFETCH(Protocol::ChangeNotification::Type, type);
172         QFETCH(QByteArray, signalName);
173 
174         Monitor dummyMonitor;
175         MonitorPrivate m(0, &dummyMonitor);
176         QSignalSpy spy(&dummyMonitor, signalName.constData());
177         QVERIFY(spy.isValid());
178 
179         Protocol::ChangeNotification msg;
180         msg.setOperation(op);
181         msg.setType(type);
182         msg.setResource("foo");
183         msg.setDestinationResource("bar");
184         msg.setSessionId("mysession");
185         msg.addEntity(1);
186 
187         // using the right resource makes it pass
188         QVERIFY(!m.acceptNotification(msg));
189         m.resources.insert("bla");
190         QVERIFY(!m.acceptNotification(msg));
191         m.resources.insert("bar");
192         QVERIFY(m.acceptNotification(msg));
193 
194         // filtering out the mimetype does not overwrite resources
195         msg.addEntity(1, QString(), QString(), QStringLiteral("my/type"));
196         QVERIFY(m.acceptNotification(msg));
197 
198         // filtering out the session overwrites the resource
199         m.sessions.append("mysession");
200         QVERIFY(!m.acceptNotification(msg));
201     }
202 
filterMimeType_data()203     void filterMimeType_data()
204     {
205         QTest::addColumn<Akonadi::Protocol::ChangeNotification::Operation>("op");
206         QTest::addColumn<Akonadi::Protocol::ChangeNotification::Type>("type");
207         QTest::addColumn<QByteArray>("signalName");
208 
209         QTest::newRow("itemAdded") << Protocol::ChangeNotification::Add << Protocol::ChangeNotification::Items
210                                    << QByteArray(SIGNAL(itemAdded(Akonadi::Item, Akonadi::Collection)));
211         QTest::newRow("itemChanged") << Protocol::ChangeNotification::Modify << Protocol::ChangeNotification::Items
212                                      << QByteArray(SIGNAL(itemChanged(Akonadi::Item, QSet<QByteArray>)));
213         QTest::newRow("itemsFlagsChanged") << Protocol::ChangeNotification::ModifyFlags << Protocol::ChangeNotification::Items
214                                            << QByteArray(SIGNAL(itemsFlagsChanged(Akonadi::Item::List, QSet<QByteArray>, QSet<QByteArray>)));
215         QTest::newRow("itemRemoved") << Protocol::ChangeNotification::Remove << Protocol::ChangeNotification::Items
216                                      << QByteArray(SIGNAL(itemRemoved(Akonadi::Item)));
217         QTest::newRow("itemMoved") << Protocol::ChangeNotification::Move << Protocol::ChangeNotification::Items
218                                    << QByteArray(SIGNAL(itemMoved(Akonadi::Item, Akonadi::Collection, Akonadi::Collection)));
219         QTest::newRow("itemLinked") << Protocol::ChangeNotification::Link << Protocol::ChangeNotification::Items
220                                     << QByteArray(SIGNAL(itemLinked(Akonadi::Item, Akonadi::Collection)));
221         QTest::newRow("itemUnlinked") << Protocol::ChangeNotification::Unlink << Protocol::ChangeNotification::Items
222                                       << QByteArray(SIGNAL(itemUnlinked(Akonadi::Item, Akonadi::Collection)));
223 
224         QTest::newRow("colAdded") << Protocol::ChangeNotification::Add << Protocol::ChangeNotification::Collections
225                                   << QByteArray(SIGNAL(collectionAdded(Akonadi::Collection, Akonadi::Collection)));
226         QTest::newRow("colChanged") << Protocol::ChangeNotification::Modify << Protocol::ChangeNotification::Collections
227                                     << QByteArray(SIGNAL(collectionChanged(Akonadi::Collection, QSet<QByteArray>)));
228         QTest::newRow("colRemoved") << Protocol::ChangeNotification::Remove << Protocol::ChangeNotification::Collections
229                                     << QByteArray(SIGNAL(collectionRemoved(Akonadi::Collection)));
230         QTest::newRow("colMoved") << Protocol::ChangeNotification::Move << Protocol::ChangeNotification::Collections
231                                   << QByteArray(SIGNAL(collectionMoved(Akonadi::Collection, Akonadi::Collection, Akonadi::Collection)));
232         QTest::newRow("colSubscribed") << Protocol::ChangeNotification::Subscribe << Protocol::ChangeNotification::Collections
233                                        << QByteArray(SIGNAL(collectionSubscribed(Akonadi::Collection, Akonadi::Collection)));
234         QTest::newRow("colSubscribed") << Protocol::ChangeNotification::Unsubscribe << Protocol::ChangeNotification::Collections
235                                        << QByteArray(SIGNAL(collectionUnsubscribed(Akonadi::Collection)));
236     }
237 
filterMimeType()238     void filterMimeType()
239     {
240         QFETCH(Protocol::ChangeNotification::Operation, op);
241         QFETCH(Protocol::ChangeNotification::Type, type);
242         QFETCH(QByteArray, signalName);
243 
244         Monitor dummyMonitor;
245         MonitorPrivate m(0, &dummyMonitor);
246         QSignalSpy spy(&dummyMonitor, signalName.constData());
247         QVERIFY(spy.isValid());
248 
249         Protocol::ChangeNotification msg;
250         msg.addEntity(1, QString(), QString(), QStringLiteral("my/type"));
251         msg.setOperation(op);
252         msg.setParentCollection(2);
253         msg.setType(type);
254         msg.setResource("foo");
255         msg.setSessionId("mysession");
256 
257         // using the right resource makes it pass
258         QVERIFY(!m.acceptNotification(msg));
259         m.mimetypes.insert(QStringLiteral("your/type"));
260         QVERIFY(!m.acceptNotification(msg));
261         m.mimetypes.insert(QStringLiteral("my/type"));
262         QCOMPARE(m.acceptNotification(msg), type == Protocol::ChangeNotification::Items);
263 
264         // filter out the resource does not overwrite mimetype
265         m.resources.insert("bar");
266         QCOMPARE(m.acceptNotification(msg), type == Protocol::ChangeNotification::Items);
267 
268         // filtering out the session overwrites the mimetype
269         m.sessions.append("mysession");
270         QVERIFY(!m.acceptNotification(msg));
271     }
272 
filterCollection_data()273     void filterCollection_data()
274     {
275         QTest::addColumn<Akonadi::Protocol::ChangeNotification::Operation>("op");
276         QTest::addColumn<Akonadi::Protocol::ChangeNotification::Type>("type");
277         QTest::addColumn<QByteArray>("signalName");
278 
279         QTest::newRow("itemAdded") << Protocol::ChangeNotification::Add << Protocol::ChangeNotification::Items
280                                    << QByteArray(SIGNAL(itemAdded(Akonadi::Item, Akonadi::Collection)));
281         QTest::newRow("itemChanged") << Protocol::ChangeNotification::Modify << Protocol::ChangeNotification::Items
282                                      << QByteArray(SIGNAL(itemChanged(Akonadi::Item, QSet<QByteArray>)));
283         QTest::newRow("itemsFlagsChanged") << Protocol::ChangeNotification::ModifyFlags << Protocol::ChangeNotification::Items
284                                            << QByteArray(SIGNAL(itemsFlagsChanged(Akonadi::Item::List, QSet<QByteArray>, QSet<QByteArray>)));
285         QTest::newRow("itemRemoved") << Protocol::ChangeNotification::Remove << Protocol::ChangeNotification::Items
286                                      << QByteArray(SIGNAL(itemRemoved(Akonadi::Item)));
287         QTest::newRow("itemMoved") << Protocol::ChangeNotification::Move << Protocol::ChangeNotification::Items
288                                    << QByteArray(SIGNAL(itemMoved(Akonadi::Item, Akonadi::Collection, Akonadi::Collection)));
289         QTest::newRow("itemLinked") << Protocol::ChangeNotification::Link << Protocol::ChangeNotification::Items
290                                     << QByteArray(SIGNAL(itemLinked(Akonadi::Item, Akonadi::Collection)));
291         QTest::newRow("itemUnlinked") << Protocol::ChangeNotification::Unlink << Protocol::ChangeNotification::Items
292                                       << QByteArray(SIGNAL(itemUnlinked(Akonadi::Item, Akonadi::Collection)));
293 
294         QTest::newRow("colAdded") << Protocol::ChangeNotification::Add << Protocol::ChangeNotification::Collections
295                                   << QByteArray(SIGNAL(collectionAdded(Akonadi::Collection, Akonadi::Collection)));
296         QTest::newRow("colChanged") << Protocol::ChangeNotification::Modify << Protocol::ChangeNotification::Collections
297                                     << QByteArray(SIGNAL(collectionChanged(Akonadi::Collection, QSet<QByteArray>)));
298         QTest::newRow("colRemoved") << Protocol::ChangeNotification::Remove << Protocol::ChangeNotification::Collections
299                                     << QByteArray(SIGNAL(collectionRemoved(Akonadi::Collection)));
300         QTest::newRow("colMoved") << Protocol::ChangeNotification::Move << Protocol::ChangeNotification::Collections
301                                   << QByteArray(SIGNAL(collectionMoved(Akonadi::Collection, Akonadi::Collection, Akonadi::Collection)));
302         QTest::newRow("colSubscribed") << Protocol::ChangeNotification::Subscribe << Protocol::ChangeNotification::Collections
303                                        << QByteArray(SIGNAL(collectionSubscribed(Akonadi::Collection, Akonadi::Collection)));
304         QTest::newRow("colSubscribed") << Protocol::ChangeNotification::Unsubscribe << Protocol::ChangeNotification::Collections
305                                        << QByteArray(SIGNAL(collectionUnsubscribed(Akonadi::Collection)));
306     }
307 
filterCollection()308     void filterCollection()
309     {
310         QFETCH(Protocol::ChangeNotification::Operation, op);
311         QFETCH(Protocol::ChangeNotification::Type, type);
312         QFETCH(QByteArray, signalName);
313 
314         Monitor dummyMonitor;
315         MonitorPrivate m(0, &dummyMonitor);
316         QSignalSpy spy(&dummyMonitor, signalName.constData());
317         QVERIFY(spy.isValid());
318 
319         Protocol::ChangeNotification msg;
320         msg.addEntity(1, QString(), QString(), QStringLiteral("my/type"));
321         msg.setOperation(op);
322         msg.setParentCollection(2);
323         msg.setType(type);
324         msg.setResource("foo");
325         msg.setSessionId("mysession");
326 
327         // using the right resource makes it pass
328         QVERIFY(!m.acceptNotification(msg));
329         m.collections.append(Collection(3));
330         QVERIFY(!m.acceptNotification(msg));
331 
332         for (int colId = 0; colId < 3; ++colId) { // 0 == root, 1 == this, 2 == parent
333             if (colId == 1 && type == Protocol::ChangeNotification::Items) {
334                 continue;
335             }
336 
337             m.collections.clear();
338             m.collections.append(Collection(colId));
339 
340             QVERIFY(m.acceptNotification(msg));
341 
342             // filter out the resource does overwrite collection
343             m.resources.insert("bar");
344             QVERIFY(!m.acceptNotification(msg));
345             m.resources.clear();
346 
347             // filter out the mimetype does overwrite collection, for item operations (mimetype filter has no effect on collections)
348             m.mimetypes.insert(QStringLiteral("your/type"));
349             QCOMPARE(!m.acceptNotification(msg), type == Protocol::ChangeNotification::Items);
350             m.mimetypes.clear();
351 
352             // filtering out the session overwrites the mimetype
353             m.sessions.append("mysession");
354             QVERIFY(!m.acceptNotification(msg));
355             m.sessions.clear();
356 
357             // filter non-matching resource and matching mimetype make it pass
358             m.resources.insert("bar");
359             m.mimetypes.insert(QStringLiteral("my/type"));
360             QVERIFY(m.acceptNotification(msg));
361             m.resources.clear();
362             m.mimetypes.clear();
363         }
364     }
365 };
366 
367 QTEST_MAIN(MonitorFilterTest)
368 
369 #include "monitorfiltertest.moc"
370