File indexing completed on 2025-01-05 04:58:36

0001 #include <QTest>
0002 
0003 #include <KDAV2/DavCollectionsFetchJob>
0004 #include <KDAV2/DavCollectionCreateJob>
0005 #include <KDAV2/DavCollectionDeleteJob>
0006 #include <KDAV2/DavItemFetchJob>
0007 #include <KDAV2/DavItemModifyJob>
0008 #include <KDAV2/DavItemCreateJob>
0009 #include <KDAV2/DavItemsListJob>
0010 
0011 #include <KCalendarCore/Event>
0012 #include <KCalendarCore/ICalFormat>
0013 
0014 #include "../caldavresource.h"
0015 
0016 #include "common/resourcecontrol.h"
0017 #include "common/secretstore.h"
0018 #include "common/store.h"
0019 #include "common/test.h"
0020 #include "common/query.h"
0021 
0022 #include <algorithm>
0023 
0024 using namespace Sink;
0025 using Sink::ApplicationDomain::Calendar;
0026 using Sink::ApplicationDomain::DummyResource;
0027 using Sink::ApplicationDomain::Event;
0028 using Sink::ApplicationDomain::Todo;
0029 using Sink::ApplicationDomain::SinkResource;
0030 
0031 class CalDavTest : public QObject
0032 {
0033     Q_OBJECT
0034 
0035     // This test assumes a calendar "personal".
0036 
0037     const QString baseUrl = "http://localhost/dav/calendars/user/doe";
0038     const QString username = "doe";
0039     const QString password = "doe";
0040 
0041     SinkResource createResource()
0042     {
0043         auto resource = Sink::ApplicationDomain::CalDavResource::create("account1");
0044         resource.setProperty("server", "http://localhost");
0045         resource.setProperty("username", username);
0046         Sink::SecretStore::instance().insert(resource.identifier(), password);
0047         return resource;
0048     }
0049 
0050     QByteArray mResourceInstanceIdentifier;
0051 
0052     QByteArray createEvent(const QString &subject, const QString &collectionName)
0053     {
0054         const auto collectionUrl = findCollection(collectionName);
0055 
0056         QUrl url{collectionUrl.url().toString() + subject + ".ical"};
0057         url.setUserName(QStringLiteral("doe"));
0058         url.setPassword(QStringLiteral("doe"));
0059 
0060         KDAV2::DavUrl testItemUrl(url, KDAV2::CardDav);
0061 
0062         auto event = QSharedPointer<KCalendarCore::Event>::create();
0063         event->setSummary(subject);
0064         event->setDtStart(QDateTime::currentDateTime());
0065         event->setDtEnd(QDateTime::currentDateTime().addSecs(3600));
0066         event->setCreated(QDateTime::currentDateTime());
0067         event->setUid(subject);
0068 
0069         auto data = KCalendarCore::ICalFormat().toICalString(event).toUtf8();
0070 
0071         KDAV2::DavItem item(testItemUrl, QStringLiteral("text/calendar"), data, QString());
0072         auto createJob = new KDAV2::DavItemCreateJob(item);
0073         createJob->exec();
0074         if (createJob->error()) {
0075             qWarning() << createJob->errorString();
0076         }
0077         return event->uid().toUtf8();
0078     }
0079 
0080     void createCollection(const QString &name)
0081     {
0082         QUrl mainUrl(QStringLiteral("http://localhost/dav/calendars/user/doe/") + name);
0083         mainUrl.setUserName(QStringLiteral("doe"));
0084         mainUrl.setPassword(QStringLiteral("doe"));
0085 
0086         KDAV2::DavUrl davUrl(mainUrl, KDAV2::CalDav);
0087         KDAV2::DavCollection collection{davUrl, name, KDAV2::DavCollection::Events};
0088 
0089         auto createJob = new KDAV2::DavCollectionCreateJob(collection);
0090         createJob->exec();
0091         if (createJob->error()) {
0092             qWarning() << createJob->errorString();
0093         }
0094     }
0095 
0096     KDAV2::DavUrl findCollection(const QString &collectionName)
0097     {
0098         QUrl mainUrl{"http://localhost/dav/calendars/user/doe"};
0099         mainUrl.setUserName(QStringLiteral("doe"));
0100         mainUrl.setPassword(QStringLiteral("doe"));
0101 
0102         KDAV2::DavUrl davUrl(mainUrl, KDAV2::CalDav);
0103 
0104         auto *job = new KDAV2::DavCollectionsFetchJob(davUrl);
0105         job->exec();
0106 
0107         const auto collectionUrl = [&] {
0108             for (const auto &col : job->collections()) {
0109                 // qWarning() << "Looking for " << collectionName << col.displayName();
0110                 if (col.displayName() == collectionName) {
0111                     return col.url();
0112                 }
0113             }
0114             return KDAV2::DavUrl{};
0115         }();
0116         return collectionUrl;
0117     }
0118 
0119     void removeCollection(const QString &collectionName)
0120     {
0121         auto deleteJob = new KDAV2::DavCollectionDeleteJob(findCollection(collectionName));
0122         deleteJob->exec();
0123         if (deleteJob->error()) {
0124             qWarning() << deleteJob->errorString();
0125         }
0126     }
0127 
0128     int modifyEvent(const QString &eventUid, const QString &newSummary)
0129     {
0130         auto collection = [&]() -> KDAV2::DavCollection {
0131             QUrl url(baseUrl);
0132             url.setUserName(username);
0133             url.setPassword(password);
0134             KDAV2::DavUrl davurl(url, KDAV2::CalDav);
0135             auto collectionsJob = new KDAV2::DavCollectionsFetchJob(davurl);
0136             collectionsJob->exec();
0137             Q_ASSERT(collectionsJob->error() == 0);
0138             for (const auto &col : collectionsJob->collections()) {
0139                 if (col.displayName() == "personal") {
0140                     return col;
0141                 }
0142             }
0143             return {};
0144         }();
0145 
0146         auto itemList = ([&collection]() -> KDAV2::DavItem::List {
0147             auto itemsListJob = new KDAV2::DavItemsListJob(collection.url());
0148             itemsListJob->exec();
0149             Q_ASSERT(itemsListJob->error() == 0);
0150             return itemsListJob->items();
0151         })();
0152         auto hollowDavItemIt =
0153             std::find_if(itemList.begin(), itemList.end(), [&](const KDAV2::DavItem &item) {
0154                 return item.url().url().path().contains(eventUid);
0155             });
0156         Q_ASSERT(hollowDavItemIt != itemList.end());
0157 
0158         auto davitem = ([&]() -> KDAV2::DavItem {
0159             auto itemFetchJob = new KDAV2::DavItemFetchJob(*hollowDavItemIt);
0160             itemFetchJob->exec();
0161             Q_ASSERT(itemFetchJob->error() == 0);
0162             return itemFetchJob->item();
0163         })();
0164 
0165         auto incidence = KCalendarCore::ICalFormat().readIncidence(davitem.data());
0166         auto calevent = incidence.dynamicCast<KCalendarCore::Event>();
0167         Q_ASSERT(calevent);
0168 
0169         calevent->setSummary(newSummary);
0170         auto newical = KCalendarCore::ICalFormat().toICalString(calevent);
0171 
0172         davitem.setData(newical.toUtf8());
0173         auto itemModifyJob = new KDAV2::DavItemModifyJob(davitem);
0174         itemModifyJob->exec();
0175         return itemModifyJob->error();
0176     }
0177 
0178     void resetTestEnvironment()
0179     {
0180         system("resetcalendar.sh");
0181     }
0182 
0183 private slots:
0184 
0185     void initTestCase()
0186     {
0187         Sink::Test::initTest();
0188         resetTestEnvironment();
0189         auto resource = createResource();
0190         QVERIFY(!resource.identifier().isEmpty());
0191         VERIFYEXEC(Sink::Store::create(resource));
0192         mResourceInstanceIdentifier = resource.identifier();
0193     }
0194 
0195     void cleanup()
0196     {
0197         VERIFYEXEC(Sink::Store::removeDataFromDisk(mResourceInstanceIdentifier));
0198     }
0199 
0200     void init()
0201     {
0202         VERIFYEXEC(Sink::ResourceControl::start(mResourceInstanceIdentifier));
0203     }
0204 
0205     void testSyncCalEmpty()
0206     {
0207         VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
0208         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0209 
0210         QCOMPARE(Sink::Store::read<Event>({}).size(), 0);
0211         QCOMPARE(Sink::Store::read<Todo>({}).size(), 0);
0212 
0213         const auto calendars = Sink::Store::read<Calendar>(Sink::Query().request<Calendar::Name>());
0214         QCOMPARE(calendars.size(), 1);
0215         QCOMPARE(calendars.first().getName(), QLatin1String{"personal"});
0216     }
0217 
0218     void testSyncCalendars()
0219     {
0220         createCollection("calendar2");
0221 
0222         Sink::SyncScope scope;
0223         scope.setType<Calendar>();
0224         scope.resourceFilter(mResourceInstanceIdentifier);
0225 
0226         VERIFYEXEC(Sink::Store::synchronize(scope));
0227         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0228         const auto calendars = Sink::Store::read<Calendar>(Sink::Query().resourceFilter(mResourceInstanceIdentifier));
0229         QCOMPARE(calendars.size(), 2);
0230     }
0231 
0232     void testSyncEvents()
0233     {
0234         createEvent("event1", "personal");
0235         createEvent("event2", "personal");
0236         createEvent("event3", "calendar2");
0237 
0238         //Get the calendars first because we rely on them for the next query.
0239         {
0240             Sink::SyncScope scope;
0241             scope.setType<Calendar>();
0242             scope.resourceFilter(mResourceInstanceIdentifier);
0243             VERIFYEXEC(Sink::Store::synchronize(scope));
0244             VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0245         }
0246 
0247         //We explicitly set an empty calendar filter to override the default query for enabled calendars only
0248         Sink::SyncScope scope;
0249         scope.setType<Event>();
0250         Sink::Query q;
0251         q.setType<Calendar>();
0252         scope.filter(ApplicationDomain::getTypeName<Calendar>(), {QVariant::fromValue(q)});
0253         scope.resourceFilter(mResourceInstanceIdentifier);
0254 
0255         VERIFYEXEC(Sink::Store::synchronize(scope));
0256         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0257         const auto events = Sink::Store::read<Event>(Sink::Query().resourceFilter(mResourceInstanceIdentifier));
0258         QCOMPARE(events.size(), 3);
0259 
0260         //Ensure a resync works
0261         {
0262             VERIFYEXEC(Sink::Store::synchronize(scope));
0263             VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0264             const auto events = Sink::Store::read<Event>(Sink::Query().resourceFilter(mResourceInstanceIdentifier));
0265             QCOMPARE(events.size(), 3);
0266             for (const auto &event : events) {
0267                 const auto calendars = Sink::Store::read<Calendar>(Sink::Query().resourceFilter(mResourceInstanceIdentifier).filter(event.getCalendar()));
0268                 QCOMPARE(calendars.size(), 1);
0269             }
0270         }
0271 
0272         //Ensure a resync after another creation works
0273         createEvent("event4", "calendar2");
0274         {
0275             VERIFYEXEC(Sink::Store::synchronize(scope));
0276             VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0277             const auto events = Sink::Store::read<Event>(Sink::Query().resourceFilter(mResourceInstanceIdentifier));
0278             QCOMPARE(events.size(), 4);
0279         }
0280     }
0281 
0282     void testCreateModifyDeleteEvent()
0283     {
0284         VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
0285         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0286 
0287         auto calendar = Sink::Store::readOne<Calendar>(Sink::Query{}.filter<Calendar::Name>("personal"));
0288 
0289         auto event = QSharedPointer<KCalendarCore::Event>::create();
0290         event->setSummary("Hello");
0291         event->setDtStart(QDateTime::currentDateTime());
0292         event->setDtEnd(QDateTime::currentDateTime().addSecs(3600));
0293         event->setCreated(QDateTime::currentDateTime());
0294         auto addedEventUid = QUuid::createUuid().toString();
0295         event->setUid(addedEventUid);
0296 
0297         auto ical = KCalendarCore::ICalFormat().toICalString(event);
0298         Event sinkEvent(mResourceInstanceIdentifier);
0299         sinkEvent.setIcal(ical.toUtf8());
0300         sinkEvent.setCalendar(calendar);
0301 
0302         VERIFYEXEC(Sink::Store::create(sinkEvent));
0303         VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
0304 
0305         auto events = Sink::Store::read<Event>(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)));
0306         QCOMPARE(events.size(), 1);
0307         QCOMPARE(events.first().getSummary(), QLatin1String{"Hello"});
0308         QCOMPARE(events.first().getCalendar(), calendar.identifier());
0309 
0310         //Modify
0311         {
0312             auto event = events.first();
0313             auto incidence = KCalendarCore::ICalFormat().readIncidence(event.getIcal());
0314             auto calevent = incidence.dynamicCast<KCalendarCore::Event>();
0315             QVERIFY2(calevent, "Cannot convert to KCalendarCore event");
0316 
0317             calevent->setSummary("Hello World!");
0318             auto dummy = QSharedPointer<KCalendarCore::Event>(calevent);
0319             auto newical = KCalendarCore::ICalFormat().toICalString(dummy);
0320 
0321             event.setIcal(newical.toUtf8());
0322 
0323             VERIFYEXEC(Sink::Store::modify(event));
0324 
0325             VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
0326             VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0327 
0328             auto events = Sink::Store::read<Event>(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)));
0329             QCOMPARE(events.size(), 1);
0330             QCOMPARE(events.first().getSummary(), QLatin1String{"Hello World!"});
0331         }
0332         //Delete
0333         {
0334             auto event = events.first();
0335 
0336             VERIFYEXEC(Sink::Store::remove(event));
0337             VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0338             VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
0339 
0340             auto events = Sink::Store::read<Event>(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)));
0341             QCOMPARE(events.size(), 0);
0342         }
0343     }
0344 
0345     void testCreateModifyDeleteTodo()
0346     {
0347         VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
0348         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0349 
0350         auto calendar = Sink::Store::readOne<Calendar>(Sink::Query{}.filter<Calendar::Name>("personal"));
0351 
0352         auto todo = QSharedPointer<KCalendarCore::Todo>::create();
0353         todo->setSummary("Hello");
0354         todo->setDtStart(QDateTime::currentDateTime());
0355         todo->setCreated(QDateTime::currentDateTime());
0356         auto addedTodoUid = QUuid::createUuid().toString();
0357         todo->setUid(addedTodoUid);
0358 
0359         auto ical = KCalendarCore::ICalFormat().toICalString(todo);
0360         Todo sinkTodo(mResourceInstanceIdentifier);
0361         sinkTodo.setIcal(ical.toUtf8());
0362         sinkTodo.setCalendar(calendar);
0363 
0364         VERIFYEXEC(Sink::Store::create(sinkTodo));
0365         VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
0366 
0367         auto todos = Sink::Store::read<Todo>(Sink::Query().filter("uid", Sink::Query::Comparator(addedTodoUid)));
0368         QCOMPARE(todos.size(), 1);
0369         QCOMPARE(todos.first().getSummary(), QLatin1String{"Hello"});
0370 
0371         //Modify
0372         {
0373             auto todo = todos.first();
0374             auto incidence = KCalendarCore::ICalFormat().readIncidence(todo.getIcal());
0375             auto caltodo = incidence.dynamicCast<KCalendarCore::Todo>();
0376             QVERIFY2(caltodo, "Cannot convert to KCalendarCore todo");
0377 
0378             caltodo->setSummary("Hello World!");
0379             auto dummy = QSharedPointer<KCalendarCore::Todo>(caltodo);
0380             auto newical = KCalendarCore::ICalFormat().toICalString(dummy);
0381 
0382             todo.setIcal(newical.toUtf8());
0383 
0384             VERIFYEXEC(Sink::Store::modify(todo));
0385 
0386             VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
0387             VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0388 
0389             auto todos = Sink::Store::read<Todo>(Sink::Query().filter("uid", Sink::Query::Comparator(addedTodoUid)));
0390             QCOMPARE(todos.size(), 1);
0391             QCOMPARE(todos.first().getSummary(), QLatin1String{"Hello World!"});
0392         }
0393         //Delete
0394         {
0395             auto todo = todos.first();
0396 
0397             VERIFYEXEC(Sink::Store::remove(todo));
0398             VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0399             VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
0400 
0401             auto todos = Sink::Store::read<Todo>(Sink::Query().filter("uid", Sink::Query::Comparator(addedTodoUid)));
0402             QCOMPARE(todos.size(), 0);
0403         }
0404     }
0405 
0406     void testModificationConflict()
0407     {
0408         VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
0409         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0410 
0411         auto calendar = Sink::Store::readOne<Calendar>(Sink::Query{}.filter<Calendar::Name>("personal"));
0412 
0413         auto event = QSharedPointer<KCalendarCore::Event>::create();
0414         event->setSummary("Hello");
0415         event->setDtStart(QDateTime::currentDateTime());
0416         event->setDtEnd(QDateTime::currentDateTime().addSecs(3600));
0417         event->setCreated(QDateTime::currentDateTime());
0418         auto addedEventUid = QUuid::createUuid().toString();
0419         event->setUid(addedEventUid);
0420 
0421         auto ical = KCalendarCore::ICalFormat().toICalString(event);
0422         Event sinkEvent(mResourceInstanceIdentifier);
0423         sinkEvent.setIcal(ical.toUtf8());
0424         sinkEvent.setCalendar(calendar);
0425 
0426         VERIFYEXEC(Sink::Store::create(sinkEvent));
0427         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0428         VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
0429 
0430         // Change the item without sink's knowledge
0431         QVERIFY2(modifyEvent(addedEventUid, "Manual Hello World!") == 0, "Cannot modify item");
0432 
0433         //Change the item with sink as well, this will create a conflict
0434         {
0435             auto event = Sink::Store::readOne<Event>(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)));
0436             auto calevent = KCalendarCore::ICalFormat().readIncidence(event.getIcal()).dynamicCast<KCalendarCore::Event>();
0437             QVERIFY(calevent);
0438 
0439             calevent->setSummary("Sink Hello World!");
0440             event.setIcal(KCalendarCore::ICalFormat().toICalString(calevent).toUtf8());
0441 
0442             VERIFYEXEC(Sink::Store::modify(event));
0443             VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
0444             VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0445 
0446             {
0447                 auto event = Sink::Store::readOne<Event>(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)));
0448                 QCOMPARE(event.getSummary(), QLatin1String{"Sink Hello World!"});
0449             }
0450         }
0451 
0452         // Change the item without sink's knowledge again
0453         QVERIFY2(modifyEvent(addedEventUid, "Manual Hello World2!") == 0, "Cannot modify item");
0454 
0455         //Try to synchronize the modification, the conflict should be resolved by now.
0456         Sink::SyncScope scope;
0457         scope.setType<Event>();
0458         Sink::Query q;
0459         q.setType<Calendar>();
0460         scope.filter(ApplicationDomain::getTypeName<Calendar>(), {QVariant::fromValue(q)});
0461         scope.resourceFilter(mResourceInstanceIdentifier);
0462         VERIFYEXEC(Sink::Store::synchronize(scope));
0463         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0464 
0465         {
0466             auto event = Sink::Store::readOne<Event>(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)));
0467             QCOMPARE(event.getSummary(), QLatin1String{"Manual Hello World2!"});
0468         }
0469     }
0470 
0471 
0472     void testSyncRemoveFullCalendar()
0473     {
0474         createCollection("calendar3");
0475         createEvent("eventToRemove", "calendar3");
0476 
0477         //Get the calendars first because we rely on them for the next query.
0478         {
0479             Sink::SyncScope scope;
0480             scope.setType<Calendar>();
0481             scope.resourceFilter(mResourceInstanceIdentifier);
0482             VERIFYEXEC(Sink::Store::synchronize(scope));
0483             VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0484         }
0485 
0486         //We explicitly set an empty calendar filter to override the default query for enabled calendars only
0487         Sink::SyncScope scope;
0488         scope.setType<Event>();
0489         Sink::Query q;
0490         q.setType<Calendar>();
0491         scope.filter(ApplicationDomain::getTypeName<Calendar>(), {QVariant::fromValue(q)});
0492         scope.resourceFilter(mResourceInstanceIdentifier);
0493 
0494 
0495         VERIFYEXEC(Sink::Store::synchronize(scope));
0496         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0497         QCOMPARE(Sink::Store::read<Calendar>(Sink::Query{}.filter<Calendar::Name>("calendar3")).size(), 1);
0498         QCOMPARE(Sink::Store::read<Event>(Sink::Query{}.filter<Event::Summary>("eventToRemove")).size(), 1);
0499 
0500 
0501         removeCollection("calendar3");
0502 
0503         {
0504             Sink::SyncScope scope;
0505             scope.setType<Calendar>();
0506             scope.resourceFilter(mResourceInstanceIdentifier);
0507             VERIFYEXEC(Sink::Store::synchronize(scope));
0508         }
0509         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0510         QCOMPARE(Sink::Store::read<Calendar>(Sink::Query{}.filter<Calendar::Name>("calendar3")).size(), 0);
0511         QCOMPARE(Sink::Store::read<Event>(Sink::Query{}.filter<Event::Summary>("eventToRemove")).size(), 0);
0512     }
0513 
0514     void testSyncRemoveCalendar()
0515     {
0516         createCollection("calendar4");
0517         createEvent("eventToRemove", "calendar4");
0518 
0519         //Get the calendars first because we rely on them for the next query.
0520         {
0521             Sink::SyncScope scope;
0522             scope.setType<Calendar>();
0523             scope.resourceFilter(mResourceInstanceIdentifier);
0524             VERIFYEXEC(Sink::Store::synchronize(scope));
0525             VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0526         }
0527 
0528         //We explicitly set an empty calendar filter to override the default query for enabled calendars only
0529         Sink::SyncScope scope;
0530         scope.setType<Event>();
0531         Sink::Query q;
0532         q.setType<Calendar>();
0533         scope.filter(ApplicationDomain::getTypeName<Calendar>(), {QVariant::fromValue(q)});
0534         scope.resourceFilter(mResourceInstanceIdentifier);
0535 
0536 
0537         VERIFYEXEC(Sink::Store::synchronize(scope));
0538         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0539         const auto list = Sink::Store::read<Calendar>(Sink::Query{}.filter<Calendar::Name>("calendar4"));
0540         QCOMPARE(list.size(), 1);
0541         QCOMPARE(Sink::Store::read<Event>(Sink::Query{}.filter<Event::Summary>("eventToRemove")).size(), 1);
0542 
0543         VERIFYEXEC(Sink::Store::remove(list.first()));
0544         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0545         VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
0546 
0547         QCOMPARE(Sink::Store::read<Calendar>(Sink::Query{}.filter<Calendar::Name>("calendar4")).size(), 0);
0548         QCOMPARE(Sink::Store::read<Event>(Sink::Query{}.filter<Event::Summary>("eventToRemove")).size(), 0);
0549     }
0550 
0551     void testCreateRemoveCalendar()
0552     {
0553         auto calendar = Sink::ApplicationDomain::ApplicationDomainType::createEntity<Sink::ApplicationDomain::Calendar>(mResourceInstanceIdentifier);
0554         calendar.setName("calendar5");
0555         VERIFYEXEC(Sink::Store::create(calendar));
0556 
0557         auto event = QSharedPointer<KCalendarCore::Event>::create();
0558         event->setSummary("eventToRemove");
0559         event->setDtStart(QDateTime::currentDateTime());
0560         event->setCreated(QDateTime::currentDateTime());
0561         event->setUid("eventToRemove");
0562 
0563         auto ical = KCalendarCore::ICalFormat().toICalString(event);
0564         Event sinkEvent(mResourceInstanceIdentifier);
0565         sinkEvent.setIcal(ical.toUtf8());
0566         sinkEvent.setCalendar(calendar);
0567 
0568         VERIFYEXEC(Sink::Store::create(sinkEvent));
0569 
0570         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0571         VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
0572 
0573         QVERIFY(findCollection("calendar5").url().isValid());
0574 
0575         const auto list = Sink::Store::read<Calendar>(Sink::Query{}.filter<Calendar::Name>("calendar5"));
0576         QCOMPARE(list.size(), 1);
0577         QCOMPARE(Sink::Store::read<Event>(Sink::Query{}.filter<Event::Summary>("eventToRemove")).size(), 1);
0578 
0579         VERIFYEXEC(Sink::Store::remove(list.first()));
0580         VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
0581         VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
0582 
0583         QCOMPARE(Sink::Store::read<Calendar>(Sink::Query{}.filter<Calendar::Name>("calendar5")).size(), 0);
0584         QCOMPARE(Sink::Store::read<Event>(Sink::Query{}.filter<Event::Summary>("eventToRemove")).size(), 0);
0585 
0586 
0587         QVERIFY(!findCollection("calendar5").url().isValid());
0588     }
0589 };
0590 
0591 QTEST_MAIN(CalDavTest)
0592 
0593 #include "caldavtest.moc"