File indexing completed on 2024-05-12 05:10:37
0001 /* 0002 SPDX-FileCopyrightText: 2011-2013 Sérgio Martins <iamsergio@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "etmcalendartest.h" 0008 0009 #include "../src/etmcalendar.h" 0010 #include <Akonadi/CalendarUtils> 0011 #include <Akonadi/CollectionFetchJob> 0012 #include <Akonadi/CollectionFetchScope> 0013 #include <Akonadi/CollectionModifyJob> 0014 #include <Akonadi/ItemCreateJob> 0015 #include <Akonadi/ItemDeleteJob> 0016 #include <Akonadi/ItemModifyJob> 0017 #include <KCheckableProxyModel> 0018 #include <KEMailSettings> 0019 #include <akonadi/qtest_akonadi.h> 0020 0021 #include <QSignalSpy> 0022 #include <QTestEventLoop> 0023 0024 using namespace Akonadi; 0025 using namespace KCalendarCore; 0026 0027 Q_DECLARE_METATYPE(QSet<QByteArray>) 0028 0029 void ETMCalendarTest::createIncidence(const QString &uid) 0030 { 0031 Item item; 0032 item.setMimeType(Event::eventMimeType()); 0033 Incidence::Ptr incidence = Incidence::Ptr(new Event()); 0034 incidence->setUid(uid); 0035 incidence->setDtStart(QDateTime::currentDateTimeUtc()); 0036 incidence->setSummary(QStringLiteral("summary")); 0037 item.setPayload<KCalendarCore::Incidence::Ptr>(incidence); 0038 auto job = new ItemCreateJob(item, mCollection, this); 0039 AKVERIFYEXEC(job); 0040 } 0041 0042 void ETMCalendarTest::createTodo(const QString &uid, const QString &parentUid) 0043 { 0044 Item item; 0045 item.setMimeType(Todo::todoMimeType()); 0046 Todo::Ptr todo = Todo::Ptr(new Todo()); 0047 todo->setUid(uid); 0048 0049 todo->setRelatedTo(parentUid); 0050 0051 todo->setSummary(QStringLiteral("summary")); 0052 0053 item.setPayload<KCalendarCore::Incidence::Ptr>(todo); 0054 auto job = new ItemCreateJob(item, mCollection, this); 0055 mIncidencesToAdd++; 0056 mIncidencesToChange++; 0057 AKVERIFYEXEC(job); 0058 } 0059 0060 void ETMCalendarTest::deleteIncidence(const QString &uid) 0061 { 0062 auto job = new ItemDeleteJob(mCalendar->item(uid)); 0063 mIncidencesToDelete++; 0064 AKVERIFYEXEC(job); 0065 } 0066 0067 void ETMCalendarTest::fetchCollection() 0068 { 0069 auto job = new CollectionFetchJob(Collection::root(), CollectionFetchJob::Recursive, this); 0070 // Get list of collections 0071 job->fetchScope().setContentMimeTypes(QStringList() << QStringLiteral("application/x-vnd.akonadi.calendar.event")); 0072 AKVERIFYEXEC(job); 0073 0074 // Find our collection 0075 Collection::List collections = job->collections(); 0076 QVERIFY(!collections.isEmpty()); 0077 mCollection = collections.first(); 0078 0079 QVERIFY(mCollection.isValid()); 0080 } 0081 0082 void ETMCalendarTest::initTestCase() 0083 { 0084 AkonadiTest::checkTestIsIsolated(); 0085 mIncidencesToAdd = 0; 0086 mIncidencesToChange = 0; 0087 mIncidencesToDelete = 0; 0088 0089 qRegisterMetaType<QSet<QByteArray>>("QSet<QByteArray>"); 0090 fetchCollection(); 0091 0092 mCalendar = new ETMCalendar(); 0093 QVERIFY(mCalendar->isLoading()); 0094 connect(mCalendar, &ETMCalendar::collectionsAdded, this, &ETMCalendarTest::handleCollectionsAdded); 0095 0096 mCalendar->registerObserver(this); 0097 0098 // Wait for the collection 0099 QTestEventLoop::instance().enterLoop(10); 0100 QVERIFY(!QTestEventLoop::instance().timeout()); 0101 0102 KCheckableProxyModel *checkable = mCalendar->checkableProxyModel(); 0103 const QModelIndex firstIndex = checkable->index(0, 0); 0104 QVERIFY(firstIndex.isValid()); 0105 checkable->setData(firstIndex, Qt::Checked, Qt::CheckStateRole); 0106 0107 mIncidencesToAdd = 6; 0108 createIncidence(tr("a")); 0109 createIncidence(tr("b")); 0110 createIncidence(tr("c")); 0111 createIncidence(tr("d")); 0112 createIncidence(tr("e")); 0113 createIncidence(tr("f")); 0114 0115 // Wait for incidences 0116 QTestEventLoop::instance().enterLoop(10); 0117 QVERIFY(!QTestEventLoop::instance().timeout()); 0118 QVERIFY(!mCalendar->isLoading()); 0119 } 0120 0121 void ETMCalendarTest::cleanupTestCase() 0122 { 0123 delete mCalendar; 0124 } 0125 0126 void ETMCalendarTest::testCollectionChanged_data() 0127 { 0128 QTest::addColumn<Akonadi::Collection>("noRightsCollection"); 0129 Collection noRightsCollection = mCollection; 0130 noRightsCollection.setRights(Collection::Rights(Collection::CanCreateItem)); 0131 QTest::newRow("change rights") << noRightsCollection; 0132 } 0133 0134 void ETMCalendarTest::testCollectionChanged() 0135 { 0136 QFETCH(Akonadi::Collection, noRightsCollection); 0137 auto job = new CollectionModifyJob(mCollection, this); 0138 QSignalSpy spy(mCalendar, &ETMCalendar::collectionChanged); 0139 mIncidencesToChange = 6; 0140 AKVERIFYEXEC(job); 0141 QTestEventLoop::instance().enterLoop(10); 0142 QVERIFY(!QTestEventLoop::instance().timeout()); 0143 QCOMPARE(spy.count(), 1); 0144 QCOMPARE(spy.at(0).count(), 2); 0145 QCOMPARE(spy.at(0).at(0).value<Akonadi::Collection>(), mCollection); 0146 QVERIFY(spy.at(0).at(1).value<QSet<QByteArray>>().contains(QByteArray("AccessRights"))); 0147 } 0148 0149 void ETMCalendarTest::testIncidencesAdded() 0150 { 0151 // Already tested above. 0152 } 0153 0154 void ETMCalendarTest::testIncidencesModified() 0155 { 0156 const QString uid = tr("d"); 0157 Item item = mCalendar->item(uid); 0158 QVERIFY(item.isValid()); 0159 QVERIFY(item.hasPayload()); 0160 Incidence::Ptr clone = Incidence::Ptr(CalendarUtils::incidence(item)->clone()); 0161 clone->setSummary(tr("foo33")); 0162 item.setPayload(clone); 0163 auto job = new ItemModifyJob(item); 0164 mIncidencesToChange = 1; 0165 AKVERIFYEXEC(job); 0166 QTestEventLoop::instance().enterLoop(10); 0167 QVERIFY(!QTestEventLoop::instance().timeout()); 0168 QCOMPARE(mCalendar->incidence(uid)->summary(), tr("foo33")); 0169 QVERIFY(item.revision() == mCalendar->item(item.id()).revision() - 1); 0170 } 0171 0172 void ETMCalendarTest::testIncidencesDeleted() 0173 { 0174 Event::List incidences = mCalendar->events(); 0175 QCOMPARE(incidences.count(), 6); 0176 const Item item = mCalendar->item(tr("a")); 0177 QVERIFY(item.isValid()); 0178 QVERIFY(item.hasPayload()); 0179 auto job = new ItemDeleteJob(item); 0180 AKVERIFYEXEC(job); 0181 mIncidencesToDelete = 1; 0182 QTestEventLoop::instance().enterLoop(10); 0183 QVERIFY(!QTestEventLoop::instance().timeout()); 0184 QCOMPARE(mLastDeletedUid, tr("a")); 0185 QVERIFY(!mCalendar->item(tr("a")).isValid()); 0186 } 0187 0188 void ETMCalendarTest::testFilteredModel() 0189 { 0190 QVERIFY(mCalendar->model()); 0191 } 0192 0193 void ETMCalendarTest::testUnfilteredModel() 0194 { 0195 QVERIFY(mCalendar->entityTreeModel()); 0196 } 0197 0198 void ETMCalendarTest::testCheckableProxyModel() 0199 { 0200 QVERIFY(mCalendar->checkableProxyModel()); 0201 } 0202 0203 void ETMCalendarTest::testUnselectCollection() 0204 { 0205 mIncidencesToAdd = mIncidencesToDelete = mCalendar->incidences().count(); 0206 const int originalToDelete = mIncidencesToDelete; 0207 KCheckableProxyModel *checkable = mCalendar->checkableProxyModel(); 0208 const QModelIndex firstIndex = checkable->index(0, 0); 0209 QVERIFY(firstIndex.isValid()); 0210 checkable->setData(firstIndex, Qt::Unchecked, Qt::CheckStateRole); 0211 0212 if (mIncidencesToDelete > 0) { // Actually they probably where deleted already 0213 // doesn't need the event loop, but just in case 0214 QTestEventLoop::instance().enterLoop(10); 0215 0216 if (QTestEventLoop::instance().timeout()) { 0217 qDebug() << originalToDelete << mIncidencesToDelete; 0218 QVERIFY(false); 0219 } 0220 } 0221 } 0222 0223 void ETMCalendarTest::testSelectCollection() 0224 { 0225 KCheckableProxyModel *checkable = mCalendar->checkableProxyModel(); 0226 const QModelIndex firstIndex = checkable->index(0, 0); 0227 QVERIFY(firstIndex.isValid()); 0228 checkable->setData(firstIndex, Qt::Checked, Qt::CheckStateRole); 0229 0230 if (mIncidencesToDelete > 0) { 0231 QTestEventLoop::instance().enterLoop(10); 0232 QVERIFY(!QTestEventLoop::instance().timeout()); 0233 } 0234 } 0235 0236 void ETMCalendarTest::calendarIncidenceAdded(const Incidence::Ptr &incidence) 0237 { 0238 Q_ASSERT(incidence); 0239 0240 const QString id = incidence->customProperty("VOLATILE", "AKONADI-ID"); 0241 QCOMPARE(id.toLongLong(), mCalendar->item(incidence->uid()).id()); 0242 0243 QVERIFY(mIncidencesToAdd > 0); 0244 --mIncidencesToAdd; 0245 checkExitLoop(); 0246 } 0247 0248 void ETMCalendarTest::handleCollectionsAdded(const Akonadi::Collection::List &) 0249 { 0250 QVERIFY(mCalendar->isLoading()); 0251 QTestEventLoop::instance().exitLoop(); 0252 } 0253 0254 void ETMCalendarTest::calendarIncidenceChanged(const Incidence::Ptr &incidence) 0255 { 0256 const QString id = incidence->customProperty("VOLATILE", "AKONADI-ID"); 0257 0258 Akonadi::Item item = mCalendar->item(incidence->uid()); 0259 QVERIFY(item.isValid()); 0260 QVERIFY(item.hasPayload()); 0261 Incidence::Ptr i2 = CalendarUtils::incidence(item); 0262 0263 if (id.toLongLong() != item.id()) { 0264 qDebug() << "Incidence uid = " << incidence->uid() << "; internal incidence uid = " << i2->uid(); 0265 QVERIFY(false); 0266 } 0267 0268 QCOMPARE(incidence.data(), i2.data()); 0269 QCOMPARE(i2->summary(), incidence->summary()); 0270 Incidence::Ptr i3 = mCalendar->incidence(incidence->uid()); 0271 QCOMPARE(i3->summary(), incidence->summary()); 0272 0273 if (mIncidencesToChange > 0) { 0274 --mIncidencesToChange; 0275 } 0276 0277 checkExitLoop(); 0278 } 0279 0280 void ETMCalendarTest::calendarIncidenceDeleted(const Incidence::Ptr &incidence, const KCalendarCore::Calendar *cal) 0281 { 0282 Q_UNUSED(cal) 0283 const QString id = incidence->customProperty("VOLATILE", "AKONADI-ID"); 0284 QVERIFY(!id.isEmpty()); 0285 QVERIFY(mIncidencesToDelete > 0); 0286 0287 --mIncidencesToDelete; 0288 mLastDeletedUid = incidence->uid(); 0289 checkExitLoop(); 0290 } 0291 0292 void ETMCalendarTest::testSubTodos_data() 0293 { 0294 QTest::addColumn<bool>("doClone"); 0295 QTest::newRow("clone") << true; 0296 QTest::newRow("dont clone") << false; 0297 } 0298 0299 void ETMCalendarTest::testSubTodos() 0300 { 0301 QFETCH(bool, doClone); 0302 0303 mIncidencesToAdd = 0; 0304 mIncidencesToChange = 0; 0305 mIncidencesToDelete = 0; 0306 0307 createTodo(tr("ta"), QString()); 0308 createTodo(tr("tb"), QString()); 0309 createTodo(tr("tb.1"), tr("tb")); 0310 createTodo(tr("tb.1.1"), tr("tb.1")); 0311 createTodo(tr("tb.2"), tr("tb")); 0312 createTodo(tr("tb.3"), tr("tb")); 0313 waitForIt(); 0314 0315 QVERIFY(mCalendar->childIncidences(tr("ta")).isEmpty()); 0316 QCOMPARE(mCalendar->childIncidences(tr("tb")).count(), 3); 0317 QCOMPARE(mCalendar->childIncidences(tr("tb.1")).count(), 1); 0318 QVERIFY(mCalendar->childIncidences(tr("tb.1.1")).isEmpty()); 0319 QVERIFY(mCalendar->childIncidences(tr("tb.2")).isEmpty()); 0320 0321 // Kill a child 0322 deleteIncidence(tr("tb.3")); 0323 waitForIt(); 0324 0325 QCOMPARE(mCalendar->childIncidences(tr("tb")).count(), 2); 0326 QCOMPARE(mCalendar->childItems(tr("tb")).count(), 2); 0327 QVERIFY(!mCalendar->incidence(tr("tb.3"))); 0328 0329 // Move a top-level to-do to a new parent 0330 Incidence::Ptr ta = mCalendar->incidence(tr("ta")); 0331 if (doClone) { 0332 ta = Incidence::Ptr(ta->clone()); 0333 } else { 0334 mIncidencesToChange++; 0335 } 0336 QVERIFY(ta); 0337 Item ta_item = mCalendar->item(tr("ta")); 0338 ta_item.setPayload(ta); 0339 ta->setRelatedTo(tr("tb")); 0340 mIncidencesToChange++; 0341 0342 auto job = new ItemModifyJob(ta_item); 0343 AKVERIFYEXEC(job); 0344 waitForIt(); 0345 0346 QCOMPARE(mCalendar->childIncidences(tr("tb")).count(), 3); 0347 0348 // Move it to another parent now 0349 ta = mCalendar->incidence(tr("ta")); 0350 if (doClone) { 0351 ta = Incidence::Ptr(ta->clone()); 0352 } else { 0353 mIncidencesToChange++; 0354 } 0355 0356 ta_item = mCalendar->item(tr("ta")); 0357 ta->setRelatedTo(tr("tb.2")); 0358 ta_item.setPayload(ta); 0359 mIncidencesToChange++; 0360 job = new ItemModifyJob(ta_item); 0361 AKVERIFYEXEC(job); 0362 waitForIt(); 0363 0364 QCOMPARE(mCalendar->childIncidences(tr("tb")).count(), 2); 0365 QCOMPARE(mCalendar->childIncidences(tr("tb.2")).count(), 1); 0366 0367 // Now unparent it 0368 ta = mCalendar->incidence(tr("ta")); 0369 if (doClone) { 0370 ta = Incidence::Ptr(ta->clone()); 0371 } else { 0372 mIncidencesToChange++; 0373 } 0374 0375 ta_item = mCalendar->item(tr("ta")); 0376 ta->setRelatedTo(QString()); 0377 ta_item.setPayload(ta); 0378 mIncidencesToChange++; 0379 job = new ItemModifyJob(ta_item); 0380 AKVERIFYEXEC(job); 0381 waitForIt(); 0382 0383 QCOMPARE(mCalendar->childIncidences(tr("tb")).count(), 2); 0384 QVERIFY(mCalendar->childIncidences(tr("tb.2")).isEmpty()); 0385 0386 // Delete everything, so we don't have duplicate ids when the next test row runs 0387 Akonadi::Item::List itemsToDelete = mCalendar->items(); 0388 mIncidencesToDelete = itemsToDelete.count(); 0389 auto deleteJob = new ItemDeleteJob(itemsToDelete); 0390 AKVERIFYEXEC(deleteJob); 0391 waitForIt(); 0392 } 0393 0394 void ETMCalendarTest::testNotifyObserverBug() 0395 { 0396 // When an observer's calendarIncidenceChanged(Incidence) method got called 0397 // and that observer then called calendar->item(incidence->uid()) the retrieved item would still 0398 // have the old payload, because CalendarBase::updateItem() was still on the stack 0399 // and would only update after calendarIncidenceChanged() returned. 0400 // This test ensure that doesn't happen. 0401 const QLatin1StringView uid("todo-notify-bug"); 0402 createTodo(uid, QString()); 0403 waitForIt(); 0404 0405 Akonadi::Item item = mCalendar->item(uid); 0406 KCalendarCore::Incidence::Ptr incidence = KCalendarCore::Incidence::Ptr(mCalendar->incidence(uid)->clone()); 0407 QVERIFY(item.isValid()); 0408 0409 // Modify it 0410 mIncidencesToChange = 1; 0411 incidence->setSummary(QStringLiteral("new-summary")); 0412 item.setPayload(incidence); 0413 auto job = new ItemModifyJob(item); 0414 AKVERIFYEXEC(job); 0415 0416 // The test will now happen inside ETMCalendarTest::calendarIncidenceChanged() 0417 waitForIt(); 0418 } 0419 0420 void ETMCalendarTest::testUidChange() 0421 { 0422 const QLatin1StringView originalUid("original-uid"); 0423 const QLatin1StringView newUid("new-uid"); 0424 createTodo(originalUid, QString()); 0425 waitForIt(); 0426 0427 KCalendarCore::Incidence::Ptr clone = Incidence::Ptr(mCalendar->incidence(originalUid)->clone()); 0428 QCOMPARE(clone->uid(), originalUid); 0429 0430 Akonadi::Item item = mCalendar->item(originalUid); 0431 clone->setUid(newUid); 0432 QVERIFY(item.isValid()); 0433 item.setPayload(clone); 0434 mIncidencesToChange = 1; 0435 auto job = new ItemModifyJob(item); 0436 AKVERIFYEXEC(job); 0437 0438 waitForIt(); 0439 0440 // Check that stuff still works fine 0441 KCalendarCore::Incidence::Ptr incidence = mCalendar->incidence(originalUid); 0442 QVERIFY(!incidence); 0443 incidence = mCalendar->incidence(newUid); 0444 QCOMPARE(incidence->uid(), newUid); 0445 0446 item = mCalendar->item(originalUid); 0447 QVERIFY(!item.isValid()); 0448 0449 item = mCalendar->item(newUid); 0450 QVERIFY(item.isValid()); 0451 0452 // Mix the notify observer bug with an incidence that changes UID 0453 incidence = Incidence::Ptr(incidence->clone()); 0454 incidence->setSummary(QStringLiteral("new-summary2")); 0455 item = mCalendar->item(incidence->uid()); 0456 incidence->setUid(QStringLiteral("new-uid2")); 0457 item.setPayload(incidence); 0458 mIncidencesToChange = 1; 0459 job = new ItemModifyJob(item); 0460 AKVERIFYEXEC(job); 0461 waitForIt(); 0462 } 0463 0464 void ETMCalendarTest::testItem() 0465 { 0466 const QLatin1StringView uid("uid-testItem"); 0467 createTodo(uid, QString()); 0468 waitForIt(); 0469 0470 Incidence::Ptr incidence = mCalendar->incidence(uid); 0471 Akonadi::Item item = mCalendar->item(uid); 0472 Akonadi::Item item2 = mCalendar->item(item.id()); 0473 QVERIFY(incidence); 0474 QVERIFY(item.isValid()); 0475 QVERIFY(item2.isValid()); 0476 0477 Incidence::Ptr incidence1 = CalendarUtils::incidence(item); 0478 Incidence::Ptr incidence2 = CalendarUtils::incidence(item2); 0479 0480 // The pointers should be the same 0481 QCOMPARE(incidence1.data(), incidence2.data()); 0482 QCOMPARE(incidence.data(), incidence1.data()); 0483 } 0484 0485 void ETMCalendarTest::testShareETM() 0486 { 0487 createTodo(QStringLiteral("uid-123"), QString()); 0488 waitForIt(); 0489 0490 auto calendar2 = new ETMCalendar(mCalendar, this); 0491 calendar2->registerObserver(this); 0492 0493 // Uncheck our calendar 0494 KCheckableProxyModel *checkable = calendar2->checkableProxyModel(); 0495 const QModelIndex firstIndex = checkable->index(0, 0); 0496 QVERIFY(firstIndex.isValid()); 0497 mIncidencesToDelete = calendar2->incidences().count(); // number of incidence removed signals we get 0498 checkable->setData(firstIndex, Qt::Unchecked, Qt::CheckStateRole); 0499 0500 // So, mCalendar has a calendar selection, while calendar2 has all it's calendars unchecked 0501 // they are sharing the same ETM. 0502 QVERIFY(!mCalendar->incidences().isEmpty()); 0503 QVERIFY(calendar2->incidences().isEmpty()); 0504 } 0505 0506 void ETMCalendarTest::testFilterInvitations() 0507 { 0508 int anz = mCalendar->model()->rowCount(); 0509 QString uid = QStringLiteral("invite-01"); 0510 Item item; 0511 Incidence::Ptr incidence = Incidence::Ptr(new Event()); 0512 KEMailSettings emailSettings; 0513 KCalendarCore::Attendee me(QStringLiteral("me"), emailSettings.getSetting(KEMailSettings::EmailAddress)); 0514 0515 item.setMimeType(Event::eventMimeType()); 0516 incidence->setUid(uid); 0517 incidence->setDtStart(QDateTime::currentDateTimeUtc()); 0518 incidence->setSummary(QStringLiteral("summary")); 0519 0520 me.setStatus(KCalendarCore::Attendee::NeedsAction); 0521 incidence->addAttendee(me); 0522 0523 item.setPayload<KCalendarCore::Incidence::Ptr>(incidence); 0524 auto job = new ItemCreateJob(item, mCollection, this); 0525 AKVERIFYEXEC(job); 0526 waitForIt(); 0527 // incidence do not pop up in model 0528 QCOMPARE(mCalendar->model()->rowCount(), anz); 0529 0530 qDebug() << "first invite ended"; 0531 } 0532 0533 void ETMCalendarTest::testFilterInvitationsChanged() 0534 { 0535 int anz = mCalendar->model()->rowCount(); 0536 0537 KEMailSettings emailSettings; 0538 KCalendarCore::Attendee me(QStringLiteral("me"), emailSettings.getSetting(KEMailSettings::EmailAddress)); 0539 0540 QString uid = QStringLiteral("invite-02"); 0541 mIncidencesToAdd = 1; 0542 createIncidence(uid); 0543 waitForIt(); 0544 QCOMPARE(mCalendar->model()->rowCount(), anz + 1); 0545 0546 Incidence::Ptr incidence = mCalendar->incidence(uid); 0547 Item item = mCalendar->item(uid); 0548 0549 incidence->addAttendee(me); 0550 incidence->setRevision(1); 0551 item.setPayload<KCalendarCore::Incidence::Ptr>(incidence); 0552 0553 mIncidencesToDelete = 1; 0554 auto modifyJob = new ItemModifyJob(item, this); 0555 AKVERIFYEXEC(modifyJob); 0556 waitForIt(); 0557 QCOMPARE(mCalendar->model()->rowCount(), anz); 0558 0559 me.setStatus(KCalendarCore::Attendee::Accepted); 0560 incidence->clearAttendees(); 0561 incidence->addAttendee(me); 0562 0563 incidence->setRevision(2); 0564 0565 item.setPayload<KCalendarCore::Incidence::Ptr>(incidence); 0566 item.setRevision(2); 0567 mIncidencesToAdd = 1; 0568 modifyJob = new ItemModifyJob(item, this); 0569 AKVERIFYEXEC(modifyJob); 0570 waitForIt(); 0571 QCOMPARE(mCalendar->model()->rowCount(), anz + 1); 0572 } 0573 0574 void ETMCalendarTest::waitForIt() 0575 { 0576 QTestEventLoop::instance().enterLoop(10); 0577 QVERIFY(!QTestEventLoop::instance().timeout()); 0578 } 0579 0580 void ETMCalendarTest::checkExitLoop() 0581 { 0582 // qDebug() << "checkExitLoop: current state: " << mIncidencesToDelete << mIncidencesToAdd << mIncidencesToChange; 0583 if (mIncidencesToDelete == 0 && mIncidencesToAdd == 0 && mIncidencesToChange == 0) { 0584 QTestEventLoop::instance().exitLoop(); 0585 } 0586 } 0587 0588 QTEST_AKONADIMAIN(ETMCalendarTest) 0589 0590 #include "moc_etmcalendartest.cpp"