File indexing completed on 2025-01-05 04:59:50

0001 /*
0002  * SPDX-FileCopyrightText: 2017 Kevin Ottens <ervin@kde.org>
0003  SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 
0007 #include <testlib/qtest_zanshin.h>
0008 
0009 #include "akonadi/akonadicache.h"
0010 #include "akonadi/akonadiserializer.h"
0011 
0012 #include "testlib/akonadifakemonitor.h"
0013 #include "testlib/gencollection.h"
0014 #include "testlib/gentodo.h"
0015 
0016 using namespace Testlib;
0017 
0018 class AkonadiCacheTest : public QObject
0019 {
0020     Q_OBJECT
0021 
0022 private slots:
0023     void shouldHaveDefaultState()
0024     {
0025         // GIVEN
0026         auto monitor = AkonadiFakeMonitor::Ptr::create();
0027         auto cache = Akonadi::Cache::Ptr::create(Akonadi::SerializerInterface::Ptr(new Akonadi::Serializer), monitor);
0028 
0029         // THEN
0030         QVERIFY(!cache->isCollectionListPopulated());
0031         QVERIFY(cache->collections().isEmpty());
0032     }
0033 
0034     void shouldStoreCollectionsAndUpdate()
0035     {
0036         // GIVEN
0037         const auto noteCollection = Akonadi::Collection(GenCollection().withRootAsParent()
0038                                                                        .withId(1)
0039                                                                        .withName("notes")
0040                                                                        .withNoteContent());
0041         const auto taskCollection = Akonadi::Collection(GenCollection().withRootAsParent()
0042                                                                        .withId(2)
0043                                                                        .withName("tasks")
0044                                                                        .withTaskContent());
0045         const auto noteTaskCollection = Akonadi::Collection(GenCollection().withRootAsParent()
0046                                                                            .withId(3)
0047                                                                            .withName("tasks+notes")
0048                                                                            .withTaskContent()
0049                                                                            .withNoteContent());
0050         const auto stuffCollection = Akonadi::Collection(GenCollection().withRootAsParent()
0051                                                                         .withId(4)
0052                                                                         .withName("stuff"));
0053 
0054         auto monitor = AkonadiFakeMonitor::Ptr::create();
0055         auto cache = Akonadi::Cache::Ptr::create(Akonadi::Serializer::Ptr(new Akonadi::Serializer), monitor);
0056 
0057         // WHEN
0058         cache->setCollections(Akonadi::Collection::List() << stuffCollection << noteTaskCollection
0059                                                           << taskCollection << noteCollection);
0060 
0061         // THEN
0062         QVERIFY(cache->isCollectionListPopulated());
0063         QVERIFY(cache->isCollectionKnown(stuffCollection.id()));
0064         QVERIFY(!cache->isCollectionPopulated(stuffCollection.id()));
0065         QVERIFY(cache->items(stuffCollection).isEmpty());
0066         QCOMPARE(cache->collections(),
0067                  Akonadi::Collection::List() << noteTaskCollection << taskCollection);
0068         QCOMPARE(cache->allCollections(),
0069                  Akonadi::Collection::List() << stuffCollection << noteTaskCollection
0070                  << taskCollection << noteCollection);
0071         QCOMPARE(cache->collection(stuffCollection.id()), stuffCollection);
0072         QCOMPARE(cache->collection(stuffCollection.id()).name(), stuffCollection.name());
0073 
0074         // WHEN
0075         monitor->changeCollection(GenCollection(stuffCollection).withName("stuff2"));
0076 
0077         // THEN
0078         QCOMPARE(cache->collection(stuffCollection.id()).name(), QStringLiteral("stuff2"));
0079 
0080         // WHEN
0081         monitor->changeCollection(GenCollection(noteTaskCollection).withName("note+task2"));
0082 
0083         // THEN
0084         QCOMPARE(cache->collection(noteTaskCollection.id()).name(), QStringLiteral("note+task2"));
0085 
0086         // WHEN
0087         monitor->changeCollection(GenCollection(taskCollection).withName("task2"));
0088 
0089         // THEN
0090         QCOMPARE(cache->collection(taskCollection.id()).name(), QStringLiteral("task2"));
0091     }
0092 
0093     void shouldHandleCollectionAdds_data()
0094     {
0095         QTest::addColumn<Akonadi::Collection>("collection");
0096         QTest::addColumn<bool>("seen");
0097 
0098         const auto none = Akonadi::Collection(GenCollection().withRootAsParent()
0099                                                              .withId(2)
0100                                                              .withName("collection"));
0101         const auto task = Akonadi::Collection(GenCollection(none).withTaskContent());
0102         const auto note = Akonadi::Collection(GenCollection(none).withNoteContent());
0103         const auto taskNote = Akonadi::Collection(GenCollection(none).withNoteContent().withTaskContent());
0104 
0105         QTest::newRow("tasks vs none") << none << false;
0106         QTest::newRow("tasks vs task") << task << true;
0107         QTest::newRow("tasks vs note") << note << false;
0108         QTest::newRow("tasks vs taskNote") << taskNote << true;
0109     }
0110 
0111     void shouldHandleCollectionAdds()
0112     {
0113         // GIVEN
0114         QFETCH(Akonadi::Collection, collection);
0115 
0116         auto monitor = AkonadiFakeMonitor::Ptr::create();
0117         auto cache = Akonadi::Cache::Ptr::create(Akonadi::Serializer::Ptr(new Akonadi::Serializer), monitor);
0118 
0119         // WHEN
0120         monitor->addCollection(collection);
0121 
0122         // THEN
0123         QVERIFY(!cache->isCollectionListPopulated());
0124         QVERIFY(cache->collections().isEmpty());
0125         QCOMPARE(cache->collection(collection.id()), Akonadi::Collection());
0126 
0127         // WHEN
0128         cache->setCollections(Akonadi::Collection::List());
0129         monitor->addCollection(collection);
0130 
0131         // THEN
0132         QVERIFY(cache->isCollectionListPopulated());
0133         QFETCH(bool, seen);
0134         if (seen) {
0135             QVERIFY(!cache->collections().isEmpty());
0136             QCOMPARE(cache->collection(collection.id()), collection);
0137             QCOMPARE(cache->collection(collection.id()).name(), collection.name());
0138         } else {
0139             QVERIFY(cache->collections().isEmpty());
0140             QCOMPARE(cache->collection(collection.id()), Akonadi::Collection());
0141         }
0142     }
0143 
0144     void shouldHandleCollectionChanges()
0145     {
0146         // GIVEN
0147         const auto collection = Akonadi::Collection(GenCollection().withRootAsParent()
0148                                                                    .withId(2)
0149                                                                    .withName("tasks")
0150                                                                    .withTaskContent());
0151 
0152         auto monitor = AkonadiFakeMonitor::Ptr::create();
0153         auto cache = Akonadi::Cache::Ptr::create(Akonadi::Serializer::Ptr(new Akonadi::Serializer), monitor);
0154         cache->setCollections(Akonadi::Collection::List() << collection);
0155 
0156         // WHEN
0157         const auto collection2 = Akonadi::Collection(GenCollection().withRootAsParent()
0158                                                                     .withId(2)
0159                                                                     .withName("tasks2")
0160                                                                     .withTaskContent());
0161         monitor->changeCollection(collection2);
0162 
0163         // THEN
0164         QCOMPARE(cache->collection(collection.id()).name(), QStringLiteral("tasks2"));
0165     }
0166 
0167     void shouldPopulateCollectionsWithItems()
0168     {
0169         // GIVEN
0170         const auto taskCollection1 = Akonadi::Collection(GenCollection().withRootAsParent()
0171                                                                         .withId(1)
0172                                                                         .withName("tasks1")
0173                                                                         .withTaskContent());
0174         const auto items1 = Akonadi::Item::List() << Akonadi::Item(GenTodo().withId(1).withTitle("item1"))
0175                                                   << Akonadi::Item(GenTodo().withId(2).withTitle("item2"));
0176         const auto taskCollection2 = Akonadi::Collection(GenCollection().withRootAsParent()
0177                                                                         .withId(2)
0178                                                                         .withName("tasks2")
0179                                                                         .withTaskContent());
0180         const auto items2 = Akonadi::Item::List() << Akonadi::Item(GenTodo().withId(3).withTitle("item3"))
0181                                                   << Akonadi::Item(GenTodo().withId(4).withTitle("item4"));
0182 
0183         auto monitor = AkonadiFakeMonitor::Ptr::create();
0184         auto serializer = Akonadi::Serializer::Ptr(new Akonadi::Serializer);
0185         auto cache = Akonadi::Cache::Ptr::create(serializer, monitor);
0186         cache->setCollections(Akonadi::Collection::List() << taskCollection1 << taskCollection2);
0187 
0188         // WHEN
0189         cache->populateCollection(taskCollection1, items1);
0190 
0191         // THEN
0192         QVERIFY(cache->isCollectionPopulated(taskCollection1.id()));
0193         QCOMPARE(cache->items(taskCollection1), items1);
0194         QCOMPARE(cache->item(items1.at(0).id()), items1.at(0));
0195         QCOMPARE(cache->item(items1.at(1).id()), items1.at(1));
0196 
0197         // WHEN
0198         cache->populateCollection(taskCollection2, items2);
0199 
0200         // THEN
0201         QVERIFY(cache->isCollectionPopulated(taskCollection2.id()));
0202         QCOMPARE(cache->items(taskCollection2), items2);
0203         QCOMPARE(cache->item(items2.at(0).id()), items2.at(0));
0204         QCOMPARE(cache->item(items2.at(1).id()), items2.at(1));
0205     }
0206 
0207     void shouldHandleCollectionRemoves()
0208     {
0209         // GIVEN
0210         const auto collection1 = Akonadi::Collection(GenCollection().withRootAsParent()
0211                                                                     .withId(1)
0212                                                                     .withName("tasks1")
0213                                                                     .withTaskContent());
0214         const auto items1 = Akonadi::Item::List() << Akonadi::Item(GenTodo().withId(1).withTitle("item1"))
0215                                                   << Akonadi::Item(GenTodo().withId(2).withTitle("item2"));
0216         const auto collection2 = Akonadi::Collection(GenCollection().withRootAsParent()
0217                                                                     .withId(2)
0218                                                                     .withName("tasks2")
0219                                                                     .withTaskContent());
0220         const auto items2 = Akonadi::Item::List() << Akonadi::Item(GenTodo().withId(3).withTitle("item3"))
0221                                                   << Akonadi::Item(GenTodo().withId(4).withTitle("item4"));
0222 
0223         auto monitor = AkonadiFakeMonitor::Ptr::create();
0224         auto cache = Akonadi::Cache::Ptr::create(Akonadi::Serializer::Ptr(new Akonadi::Serializer), monitor);
0225         cache->setCollections(Akonadi::Collection::List() << collection1 << collection2);
0226         cache->populateCollection(collection1, items1);
0227         cache->populateCollection(collection2, items2);
0228 
0229         // WHEN
0230         monitor->removeCollection(collection1);
0231 
0232         // THEN
0233         QVERIFY(!cache->isCollectionPopulated(collection1.id()));
0234         QVERIFY(cache->items(collection1).isEmpty());
0235         QCOMPARE(cache->item(items1.at(0).id()), Akonadi::Item());
0236         QCOMPARE(cache->item(items1.at(1).id()), Akonadi::Item());
0237 
0238         QVERIFY(cache->isCollectionPopulated(collection2.id()));
0239         QCOMPARE(cache->items(collection2), items2);
0240         QCOMPARE(cache->item(items2.at(0).id()), items2.at(0));
0241         QCOMPARE(cache->item(items2.at(1).id()), items2.at(1));
0242     }
0243 
0244     void shouldHandleItemChanges()
0245     {
0246         // GIVEN
0247         const auto collection1 = Akonadi::Collection(GenCollection().withRootAsParent()
0248                                                                     .withId(1)
0249                                                                     .withName("tasks1")
0250                                                                     .withTaskContent());
0251         const auto collection2 = Akonadi::Collection(GenCollection().withRootAsParent()
0252                                                                     .withId(2)
0253                                                                     .withName("tasks2")
0254                                                                     .withTaskContent());
0255         const auto collection3 = Akonadi::Collection(GenCollection().withRootAsParent()
0256                                                                     .withId(3)
0257                                                                     .withName("tasks3")
0258                                                                     .withTaskContent());
0259         const auto items = Akonadi::Item::List() << Akonadi::Item(GenTodo().withId(1).withParent(1).withContexts({"ctx-1"}).withTitle("item1"))
0260                                                  << Akonadi::Item(GenTodo().withId(2).withParent(1).withContexts({"ctx-1"}).withTitle("item2"));
0261         const auto item3 = Akonadi::Item(GenTodo().withId(3).withParent(1).withContexts({"ctx-1"}).withTitle("item3"));
0262 
0263 
0264         auto monitor = AkonadiFakeMonitor::Ptr::create();
0265         auto serializer = Akonadi::Serializer::Ptr(new Akonadi::Serializer);
0266         auto cache = Akonadi::Cache::Ptr::create(serializer, monitor);
0267         cache->setCollections(Akonadi::Collection::List() << collection1 << collection2 << collection3);
0268         cache->populateCollection(collection1, items);
0269         cache->populateCollection(collection2, Akonadi::Item::List());
0270 
0271         // WHEN
0272         monitor->changeItem(GenTodo(items.at(0)).withTitle("item1bis"));
0273 
0274         // THEN
0275         auto todo = serializer->createTaskFromItem(cache->item(items.at(0).id()));
0276         QCOMPARE(todo->title(), QStringLiteral("item1bis"));
0277 
0278         QVERIFY(cache->isCollectionPopulated(collection1.id()));
0279         QVERIFY(cache->items(collection1).contains(items.at(0)));
0280         QVERIFY(cache->isCollectionPopulated(collection2.id()));
0281         QVERIFY(!cache->items(collection2).contains(items.at(0)));
0282         QVERIFY(!cache->isCollectionPopulated(collection3.id()));
0283         QVERIFY(!cache->items(collection3).contains(items.at(0)));
0284 
0285         // WHEN
0286         monitor->changeItem(GenTodo(items.at(0)).withParent(2));
0287 
0288         // THEN
0289         QVERIFY(cache->isCollectionPopulated(collection1.id()));
0290         QVERIFY(!cache->items(collection1).contains(items.at(0)));
0291         QVERIFY(cache->isCollectionPopulated(collection2.id()));
0292         QVERIFY(cache->items(collection2).contains(items.at(0)));
0293         QVERIFY(!cache->isCollectionPopulated(collection3.id()));
0294         QVERIFY(!cache->items(collection3).contains(items.at(0)));
0295 
0296         // WHEN
0297         monitor->changeItem(GenTodo(items.at(0)).withParent(3));
0298 
0299         // THEN
0300         QVERIFY(cache->isCollectionPopulated(collection1.id()));
0301         QVERIFY(!cache->items(collection1).contains(items.at(0)));
0302         QVERIFY(cache->isCollectionPopulated(collection2.id()));
0303         QVERIFY(!cache->items(collection2).contains(items.at(0)));
0304         QVERIFY(!cache->isCollectionPopulated(collection3.id()));
0305         QVERIFY(!cache->items(collection3).contains(items.at(0)));
0306 
0307         // WHEN
0308         monitor->changeItem(GenTodo().withId(1).withParent(2).withContexts({"ctx-2"}).withTitle("item1"));
0309 
0310         // THEN
0311         QVERIFY(cache->isCollectionPopulated(collection1.id()));
0312         QVERIFY(!cache->items(collection1).contains(items.at(0)));
0313         QVERIFY(cache->isCollectionPopulated(collection2.id()));
0314         QVERIFY(cache->items(collection2).contains(items.at(0)));
0315         QVERIFY(!cache->isCollectionPopulated(collection3.id()));
0316         QVERIFY(!cache->items(collection3).contains(items.at(0)));
0317 
0318         // WHEN
0319         monitor->changeItem(item3);
0320 
0321         // THEN
0322         QVERIFY(cache->items(collection1).contains(item3));
0323     }
0324 
0325     void shouldHandleItemAdds()
0326     {
0327         // GIVEN
0328         const auto collection1 = Akonadi::Collection(GenCollection().withRootAsParent()
0329                                                                     .withId(1)
0330                                                                     .withName("tasks1")
0331                                                                     .withTaskContent());
0332         const auto collection2 = Akonadi::Collection(GenCollection().withRootAsParent()
0333                                                      .withId(2)
0334                                                      .withName("tasks2")
0335                                                      .withTaskContent());
0336         const auto item1 = Akonadi::Item(GenTodo().withId(1).withParent(1).withContexts({"ctx-1"}).withTitle("item1"));
0337         const auto item2 = Akonadi::Item(GenTodo().withId(2).withParent(2).withContexts({"ctx-2"}).withTitle("item2"));
0338 
0339 
0340         auto monitor = AkonadiFakeMonitor::Ptr::create();
0341         auto serializer = Akonadi::Serializer::Ptr(new Akonadi::Serializer);
0342         auto cache = Akonadi::Cache::Ptr::create(serializer, monitor);
0343         cache->setCollections(Akonadi::Collection::List() << collection1 << collection2);
0344         cache->populateCollection(collection1, Akonadi::Item::List());
0345 
0346         // WHEN
0347         monitor->addItem(item1);
0348 
0349         // THEN
0350         QVERIFY(cache->isCollectionPopulated(collection1.id()));
0351         QVERIFY(!cache->items(collection1).isEmpty());
0352         QCOMPARE(cache->items(collection1), Akonadi::Item::List() << item1);
0353         QVERIFY(!cache->isCollectionPopulated(collection2.id()));
0354         QVERIFY(cache->items(collection2).isEmpty());
0355 
0356         // WHEN
0357         monitor->addItem(item2);
0358 
0359         // THEN
0360         QVERIFY(cache->isCollectionPopulated(collection1.id()));
0361         QVERIFY(!cache->items(collection1).isEmpty());
0362         QCOMPARE(cache->items(collection1), Akonadi::Item::List() << item1);
0363         QVERIFY(!cache->isCollectionPopulated(collection2.id()));
0364         QVERIFY(cache->items(collection2).isEmpty());
0365     }
0366 
0367     void shouldHandleItemRemoves()
0368     {
0369         // GIVEN
0370         const auto collection = Akonadi::Collection(GenCollection().withRootAsParent()
0371                                                                    .withId(1)
0372                                                                    .withName("tasks")
0373                                                                    .withTaskContent());
0374         const auto items = Akonadi::Item::List() << Akonadi::Item(GenTodo().withId(1).withTitle("item1"))
0375                                                   << Akonadi::Item(GenTodo().withId(2).withTitle("item2"));
0376 
0377         auto monitor = AkonadiFakeMonitor::Ptr::create();
0378         auto cache = Akonadi::Cache::Ptr::create(Akonadi::Serializer::Ptr(new Akonadi::Serializer), monitor);
0379         cache->setCollections(Akonadi::Collection::List() << collection);
0380         cache->populateCollection(collection, items);
0381 
0382         // WHEN
0383         monitor->removeItem(items.at(0));
0384 
0385         // THEN
0386         QVERIFY(cache->isCollectionPopulated(collection.id()));
0387         QCOMPARE(cache->items(collection), Akonadi::Item::List() << items.at(1));
0388         QCOMPARE(cache->item(items.at(0).id()), Akonadi::Item());
0389         QCOMPARE(cache->item(items.at(1).id()), items.at(1));
0390     }
0391 };
0392 
0393 ZANSHIN_TEST_MAIN(AkonadiCacheTest)
0394 
0395 #include "akonadicachetest.moc"