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"