diff --git a/examples/caldavresource/tests/caldavtest.cpp b/examples/caldavresource/tests/caldavtest.cpp index 232bd67e..17447646 100644 --- a/examples/caldavresource/tests/caldavtest.cpp +++ b/examples/caldavresource/tests/caldavtest.cpp @@ -1,504 +1,504 @@ #include #include #include #include #include #include #include #include #include #include #include "../caldavresource.h" #include "common/resourcecontrol.h" #include "common/secretstore.h" #include "common/store.h" #include "common/test.h" #include "common/query.h" #include "tests/testutils.h" #include using namespace Sink; using Sink::ApplicationDomain::Calendar; using Sink::ApplicationDomain::DummyResource; using Sink::ApplicationDomain::Event; using Sink::ApplicationDomain::Todo; using Sink::ApplicationDomain::SinkResource; class CalDavTest : public QObject { Q_OBJECT // This test assumes a calendar "personal". const QString baseUrl = "http://localhost/dav/calendars/user/doe"; const QString username = "doe"; const QString password = "doe"; SinkResource createResource() { auto resource = Sink::ApplicationDomain::CalDavResource::create("account1"); - resource.setProperty("server", baseUrl); + resource.setProperty("server", "http://localhost"); resource.setProperty("username", username); Sink::SecretStore::instance().insert(resource.identifier(), password); return resource; } QByteArray mResourceInstanceIdentifier; QByteArray createEvent(const QString &subject, const QString &collectionName) { QUrl mainUrl{"http://localhost/dav/calendars/user/doe"}; mainUrl.setUserName(QStringLiteral("doe")); mainUrl.setPassword(QStringLiteral("doe")); KDAV2::DavUrl davUrl(mainUrl, KDAV2::CalDav); auto *job = new KDAV2::DavCollectionsFetchJob(davUrl); job->exec(); const auto collectionUrl = [&] { for (const auto &col : job->collections()) { // qWarning() << "Looking for " << collectionName << col.displayName(); if (col.displayName() == collectionName) { return col.url().url(); } } return QUrl{}; }(); QUrl url{collectionUrl.toString() + subject + ".ical"}; url.setUserInfo(mainUrl.userInfo()); KDAV2::DavUrl testItemUrl(url, KDAV2::CardDav); auto event = QSharedPointer::create(); event->setSummary(subject); event->setDtStart(QDateTime::currentDateTime()); event->setDtEnd(QDateTime::currentDateTime().addSecs(3600)); event->setCreated(QDateTime::currentDateTime()); event->setUid(subject); auto data = KCalCore::ICalFormat().toICalString(event).toUtf8(); KDAV2::DavItem item(testItemUrl, QStringLiteral("text/calendar"), data, QString()); auto createJob = new KDAV2::DavItemCreateJob(item); createJob->exec(); if (createJob->error()) { qWarning() << createJob->errorString(); } return event->uid().toUtf8(); } void createCollection(const QString &name) { QUrl mainUrl(QStringLiteral("http://localhost/dav/calendars/user/doe/") + name); mainUrl.setUserName(QStringLiteral("doe")); mainUrl.setPassword(QStringLiteral("doe")); KDAV2::DavUrl davUrl(mainUrl, KDAV2::CalDav); KDAV2::DavCollection collection{davUrl, name, KDAV2::DavCollection::Events}; auto createJob = new KDAV2::DavCollectionCreateJob(collection); createJob->exec(); if (createJob->error()) { qWarning() << createJob->errorString(); } } void removeCollection(const QString &collectionName) { QUrl mainUrl{"http://localhost/dav/calendars/user/doe"}; mainUrl.setUserName(QStringLiteral("doe")); mainUrl.setPassword(QStringLiteral("doe")); KDAV2::DavUrl davUrl(mainUrl, KDAV2::CalDav); auto *job = new KDAV2::DavCollectionsFetchJob(davUrl); job->exec(); const auto collectionUrl = [&] { for (const auto &col : job->collections()) { // qWarning() << "Looking for " << collectionName << col.displayName(); if (col.displayName() == collectionName) { return col.url(); } } return KDAV2::DavUrl{}; }(); auto deleteJob = new KDAV2::DavCollectionDeleteJob(collectionUrl); deleteJob->exec(); if (deleteJob->error()) { qWarning() << deleteJob->errorString(); } } void resetTestEnvironment() { system("resetcalendar.sh"); } private slots: void initTestCase() { Sink::Test::initTest(); resetTestEnvironment(); auto resource = createResource(); QVERIFY(!resource.identifier().isEmpty()); VERIFYEXEC(Sink::Store::create(resource)); mResourceInstanceIdentifier = resource.identifier(); } void cleanup() { VERIFYEXEC(Sink::Store::removeDataFromDisk(mResourceInstanceIdentifier)); } void init() { VERIFYEXEC(Sink::ResourceControl::start(mResourceInstanceIdentifier)); } void testSyncCalEmpty() { VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); QCOMPARE(Sink::Store::read({}).size(), 0); QCOMPARE(Sink::Store::read({}).size(), 0); const auto calendars = Sink::Store::read(Sink::Query().request()); QCOMPARE(calendars.size(), 1); QCOMPARE(calendars.first().getName(), {"personal"}); } void testSyncCalendars() { createCollection("calendar2"); Sink::SyncScope scope; scope.setType(); scope.resourceFilter(mResourceInstanceIdentifier); VERIFYEXEC(Sink::Store::synchronize(scope)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); const auto calendars = Sink::Store::read(Sink::Query().resourceFilter(mResourceInstanceIdentifier)); QCOMPARE(calendars.size(), 2); } void testSyncEvents() { createEvent("event1", "personal"); createEvent("event2", "personal"); createEvent("event3", "calendar2"); //Get the calendars first because we rely on them for the next query. { Sink::SyncScope scope; scope.setType(); scope.resourceFilter(mResourceInstanceIdentifier); VERIFYEXEC(Sink::Store::synchronize(scope)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); } //We explicitly set an empty calendar filter to override the default query for enabled calendars only Sink::SyncScope scope; scope.setType(); Sink::Query q; q.setType(); scope.filter(ApplicationDomain::getTypeName(), {QVariant::fromValue(q)}); scope.resourceFilter(mResourceInstanceIdentifier); VERIFYEXEC(Sink::Store::synchronize(scope)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); const auto events = Sink::Store::read(Sink::Query().resourceFilter(mResourceInstanceIdentifier)); QCOMPARE(events.size(), 3); //Ensure a resync works { VERIFYEXEC(Sink::Store::synchronize(scope)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); const auto events = Sink::Store::read(Sink::Query().resourceFilter(mResourceInstanceIdentifier)); QCOMPARE(events.size(), 3); for (const auto &event : events) { const auto calendars = Sink::Store::read(Sink::Query().resourceFilter(mResourceInstanceIdentifier).filter(event.getCalendar())); QCOMPARE(calendars.size(), 1); } } //Ensure a resync after another creation works createEvent("event4", "calendar2"); { VERIFYEXEC(Sink::Store::synchronize(scope)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); const auto events = Sink::Store::read(Sink::Query().resourceFilter(mResourceInstanceIdentifier)); QCOMPARE(events.size(), 4); } } void testCreateModifyDeleteEvent() { VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); auto calendar = Sink::Store::readOne(Sink::Query{}.filter("personal")); auto event = QSharedPointer::create(); event->setSummary("Hello"); event->setDtStart(QDateTime::currentDateTime()); event->setDtEnd(QDateTime::currentDateTime().addSecs(3600)); event->setCreated(QDateTime::currentDateTime()); auto addedEventUid = QUuid::createUuid().toString(); event->setUid(addedEventUid); auto ical = KCalCore::ICalFormat().toICalString(event); Event sinkEvent(mResourceInstanceIdentifier); sinkEvent.setIcal(ical.toUtf8()); sinkEvent.setCalendar(calendar); VERIFYEXEC(Sink::Store::create(sinkEvent)); VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier)); auto events = Sink::Store::read(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid))); QCOMPARE(events.size(), 1); QCOMPARE(events.first().getSummary(), {"Hello"}); QCOMPARE(events.first().getCalendar(), calendar.identifier()); //Modify { auto event = events.first(); auto incidence = KCalCore::ICalFormat().readIncidence(event.getIcal()); auto calevent = incidence.dynamicCast(); QVERIFY2(calevent, "Cannot convert to KCalCore event"); calevent->setSummary("Hello World!"); auto dummy = QSharedPointer(calevent); auto newical = KCalCore::ICalFormat().toICalString(dummy); event.setIcal(newical.toUtf8()); VERIFYEXEC(Sink::Store::modify(event)); VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); auto events = Sink::Store::read(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid))); QCOMPARE(events.size(), 1); QCOMPARE(events.first().getSummary(), {"Hello World!"}); } //Delete { auto event = events.first(); VERIFYEXEC(Sink::Store::remove(event)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier)); auto events = Sink::Store::read(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid))); QCOMPARE(events.size(), 0); } } void testCreateModifyDeleteTodo() { VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); auto calendar = Sink::Store::readOne(Sink::Query{}.filter("personal")); auto todo = QSharedPointer::create(); todo->setSummary("Hello"); todo->setDtStart(QDateTime::currentDateTime()); todo->setCreated(QDateTime::currentDateTime()); auto addedTodoUid = QUuid::createUuid().toString(); todo->setUid(addedTodoUid); auto ical = KCalCore::ICalFormat().toICalString(todo); Todo sinkTodo(mResourceInstanceIdentifier); sinkTodo.setIcal(ical.toUtf8()); sinkTodo.setCalendar(calendar); VERIFYEXEC(Sink::Store::create(sinkTodo)); VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier)); auto todos = Sink::Store::read(Sink::Query().filter("uid", Sink::Query::Comparator(addedTodoUid))); QCOMPARE(todos.size(), 1); QCOMPARE(todos.first().getSummary(), {"Hello"}); //Modify { auto todo = todos.first(); auto incidence = KCalCore::ICalFormat().readIncidence(todo.getIcal()); auto caltodo = incidence.dynamicCast(); QVERIFY2(caltodo, "Cannot convert to KCalCore todo"); caltodo->setSummary("Hello World!"); auto dummy = QSharedPointer(caltodo); auto newical = KCalCore::ICalFormat().toICalString(dummy); todo.setIcal(newical.toUtf8()); VERIFYEXEC(Sink::Store::modify(todo)); VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); auto todos = Sink::Store::read(Sink::Query().filter("uid", Sink::Query::Comparator(addedTodoUid))); QCOMPARE(todos.size(), 1); QCOMPARE(todos.first().getSummary(), {"Hello World!"}); } //Delete { auto todo = todos.first(); VERIFYEXEC(Sink::Store::remove(todo)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier)); auto todos = Sink::Store::read(Sink::Query().filter("uid", Sink::Query::Comparator(addedTodoUid))); QCOMPARE(todos.size(), 0); } } void testModificationConflict() { VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); auto calendar = Sink::Store::readOne(Sink::Query{}.filter("personal")); auto event = QSharedPointer::create(); event->setSummary("Hello"); event->setDtStart(QDateTime::currentDateTime()); event->setDtEnd(QDateTime::currentDateTime().addSecs(3600)); event->setCreated(QDateTime::currentDateTime()); auto addedEventUid = QUuid::createUuid().toString(); event->setUid(addedEventUid); auto ical = KCalCore::ICalFormat().toICalString(event); Event sinkEvent(mResourceInstanceIdentifier); sinkEvent.setIcal(ical.toUtf8()); sinkEvent.setCalendar(calendar); VERIFYEXEC(Sink::Store::create(sinkEvent)); VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier)); // Change the item without sink's knowledge { auto collection = [&]() -> KDAV2::DavCollection { QUrl url(baseUrl); url.setUserName(username); url.setPassword(password); KDAV2::DavUrl davurl(url, KDAV2::CalDav); auto collectionsJob = new KDAV2::DavCollectionsFetchJob(davurl); collectionsJob->exec(); Q_ASSERT(collectionsJob->error() == 0); for (const auto &col : collectionsJob->collections()) { if (col.displayName() == "personal") { return col; } } return {}; }(); auto itemList = ([&collection]() -> KDAV2::DavItem::List { auto itemsListJob = new KDAV2::DavItemsListJob(collection.url()); itemsListJob->exec(); Q_ASSERT(itemsListJob->error() == 0); return itemsListJob->items(); })(); auto hollowDavItemIt = std::find_if(itemList.begin(), itemList.end(), [&](const KDAV2::DavItem &item) { return item.url().url().path().contains(addedEventUid); }); QVERIFY(hollowDavItemIt != itemList.end()); auto davitem = ([&]() -> KDAV2::DavItem { auto itemFetchJob = new KDAV2::DavItemFetchJob (*hollowDavItemIt); itemFetchJob->exec(); Q_ASSERT(itemFetchJob->error() == 0); return itemFetchJob->item(); })(); auto incidence = KCalCore::ICalFormat().readIncidence(davitem.data()); auto calevent = incidence.dynamicCast(); QVERIFY2(calevent, "Cannot convert to KCalCore event"); calevent->setSummary("Manual Hello World!"); auto newical = KCalCore::ICalFormat().toICalString(calevent); davitem.setData(newical.toUtf8()); auto itemModifyJob = new KDAV2::DavItemModifyJob(davitem); itemModifyJob->exec(); QVERIFY2(itemModifyJob->error() == 0, "Cannot modify item"); } //Change the item with sink as well { auto event = Sink::Store::readOne(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid))); auto calevent = KCalCore::ICalFormat().readIncidence(event.getIcal()).dynamicCast(); QVERIFY(calevent); calevent->setSummary("Sink Hello World!"); event.setIcal(KCalCore::ICalFormat().toICalString(calevent).toUtf8()); // TODO: this produced a conflict, but we're not dealing with it in any way VERIFYEXEC(Sink::Store::modify(event)); VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier)); } } void testSyncRemoveFullCalendar() { createCollection("calendar3"); createEvent("eventToRemove", "calendar3"); //Get the calendars first because we rely on them for the next query. { Sink::SyncScope scope; scope.setType(); scope.resourceFilter(mResourceInstanceIdentifier); VERIFYEXEC(Sink::Store::synchronize(scope)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); } //We explicitly set an empty calendar filter to override the default query for enabled calendars only Sink::SyncScope scope; scope.setType(); Sink::Query q; q.setType(); scope.filter(ApplicationDomain::getTypeName(), {QVariant::fromValue(q)}); scope.resourceFilter(mResourceInstanceIdentifier); VERIFYEXEC(Sink::Store::synchronize(scope)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); QCOMPARE(Sink::Store::read(Sink::Query{}.filter("calendar3")).size(), 1); QCOMPARE(Sink::Store::read(Sink::Query{}.filter("eventToRemove")).size(), 1); removeCollection("calendar3"); { Sink::SyncScope scope; scope.setType(); scope.resourceFilter(mResourceInstanceIdentifier); VERIFYEXEC(Sink::Store::synchronize(scope)); } VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); QCOMPARE(Sink::Store::read(Sink::Query{}.filter("calendar3")).size(), 0); QCOMPARE(Sink::Store::read(Sink::Query{}.filter("eventToRemove")).size(), 0); } }; QTEST_MAIN(CalDavTest) #include "caldavtest.moc" diff --git a/examples/carddavresource/tests/carddavtest.cpp b/examples/carddavresource/tests/carddavtest.cpp index 5b88973f..ab297c2e 100644 --- a/examples/carddavresource/tests/carddavtest.cpp +++ b/examples/carddavresource/tests/carddavtest.cpp @@ -1,223 +1,223 @@ #include #include "common/resourcecontrol.h" #include "common/secretstore.h" #include "common/store.h" #include "common/test.h" #include "tests/testutils.h" #include #include #include #include #include #include #include #include using Sink::ApplicationDomain::Addressbook; using Sink::ApplicationDomain::Contact; using Sink::ApplicationDomain::SinkResource; class CardDavTest : public QObject { Q_OBJECT SinkResource createResource() { auto resource = Sink::ApplicationDomain::CardDavResource::create("account1"); - resource.setProperty("server", "http://localhost/dav/addressbooks/user/doe"); + resource.setProperty("server", "http://localhost"); resource.setProperty("username", "doe"); Sink::SecretStore::instance().insert(resource.identifier(), "doe"); return resource; } QByteArray mResourceInstanceIdentifier; void createContact(const QString &firstname, const QString &lastname, const QString &collectionName) { QUrl mainUrl(QStringLiteral("http://localhost/dav/addressbooks/user/doe")); mainUrl.setUserName(QStringLiteral("doe")); mainUrl.setPassword(QStringLiteral("doe")); KDAV2::DavUrl davUrl(mainUrl, KDAV2::CardDav); auto *job = new KDAV2::DavCollectionsFetchJob(davUrl); job->exec(); const auto collectionUrl = [&] { for (const auto &col : job->collections()) { if (col.displayName() == collectionName) { return col.url().url(); } } return QUrl{}; }(); QUrl url{collectionUrl.toString() + firstname + lastname + ".vcf"}; url.setUserInfo(mainUrl.userInfo()); KDAV2::DavUrl testItemUrl(url, KDAV2::CardDav); QByteArray data = QString("BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Kolab//iRony DAV Server 0.3.1//Sabre//Sabre VObject 2.1.7//EN\r\nUID:12345678-1234-1234-%1-%2\r\nFN:%1 %2\r\nN:%2;%1;;;\r\nEMAIL;TYPE=INTERNET;TYPE=HOME:%1.%2@example.com\r\nREV;VALUE=DATE-TIME:20161221T145611Z\r\nEND:VCARD\r\n").arg(firstname).arg(lastname).toUtf8(); KDAV2::DavItem item(testItemUrl, QStringLiteral("text/vcard"), data, QString()); auto createJob = new KDAV2::DavItemCreateJob(item); createJob->exec(); if (createJob->error()) { qWarning() << createJob->errorString(); } } void createCollection(const QString &name) { QUrl mainUrl(QStringLiteral("http://localhost/dav/addressbooks/user/doe/") + name); mainUrl.setUserName(QStringLiteral("doe")); mainUrl.setPassword(QStringLiteral("doe")); KDAV2::DavUrl davUrl(mainUrl, KDAV2::CardDav); KDAV2::DavCollection collection{davUrl, name, KDAV2::DavCollection::Contacts}; auto createJob = new KDAV2::DavCollectionCreateJob(collection); createJob->exec(); if (createJob->error()) { qWarning() << createJob->errorString(); } } void resetTestEnvironment() { system("resetmailbox.sh"); } private slots: void initTestCase() { Sink::Test::initTest(); resetTestEnvironment(); auto resource = createResource(); QVERIFY(!resource.identifier().isEmpty()); VERIFYEXEC(Sink::Store::create(resource)); mResourceInstanceIdentifier = resource.identifier(); } void cleanup() { VERIFYEXEC(Sink::Store::removeDataFromDisk(mResourceInstanceIdentifier)); } void init() { VERIFYEXEC(Sink::ResourceControl::start(mResourceInstanceIdentifier)); } void testSyncAddressbooks() { createCollection("addressbook2"); Sink::SyncScope scope; scope.setType(); scope.resourceFilter(mResourceInstanceIdentifier); VERIFYEXEC(Sink::Store::synchronize(scope)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); const auto addressbooks = Sink::Store::read(Sink::Query().resourceFilter(mResourceInstanceIdentifier)); QCOMPARE(addressbooks.size(), 2); } void testSyncContacts() { createContact("john", "doe", "personal"); createContact("jane", "doe", "personal"); createContact("fred", "durst", "addressbook2"); Sink::SyncScope scope; scope.resourceFilter(mResourceInstanceIdentifier); VERIFYEXEC(Sink::Store::synchronize(scope)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); const auto contacts = Sink::Store::read(Sink::Query().resourceFilter(mResourceInstanceIdentifier)); QCOMPARE(contacts.size(), 3); //Ensure a resync works { VERIFYEXEC(Sink::Store::synchronize(scope)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); const auto contacts = Sink::Store::read(Sink::Query().resourceFilter(mResourceInstanceIdentifier)); QCOMPARE(contacts.size(), 3); } //Ensure a resync after another creation works createContact("alf", "alf", "addressbook2"); { VERIFYEXEC(Sink::Store::synchronize(scope)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); const auto contacts = Sink::Store::read(Sink::Query().resourceFilter(mResourceInstanceIdentifier)); QCOMPARE(contacts.size(), 4); } } void testAddModifyRemoveContact() { auto createVCard = [] (const QString &firstname, const QString &uid) { KContacts::Addressee addressee; addressee.setGivenName(firstname); addressee.setFamilyName("Doe"); addressee.setFormattedName("John Doe"); addressee.setUid(uid); return KContacts::VCardConverter{}.createVCard(addressee, KContacts::VCardConverter::v3_0); }; Sink::SyncScope scope; scope.setType(); scope.resourceFilter(mResourceInstanceIdentifier); VERIFYEXEC(Sink::Store::synchronize(scope)); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); auto addressbooks = Sink::Store::read(Sink::Query().resourceFilter(mResourceInstanceIdentifier)); QVERIFY(!addressbooks.isEmpty()); auto addedUid = QUuid::createUuid().toString(); auto contact = Sink::ApplicationDomain::ApplicationDomainType::createEntity(mResourceInstanceIdentifier); contact.setVcard(createVCard("John", addedUid)); contact.setAddressbook(addressbooks.first()); { VERIFYEXEC(Sink::Store::create(contact)); VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier)); auto contacts = Sink::Store::read(Sink::Query().filter("uid", Sink::Query::Comparator(addedUid))); QCOMPARE(contacts.size(), 1); QCOMPARE(contacts.first().getFirstname(), {"John"}); } { contact.setVcard(createVCard("Jane", addedUid)); VERIFYEXEC(Sink::Store::modify(contact)); VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier)); VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); auto contacts = Sink::Store::read(Sink::Query().filter("uid", Sink::Query::Comparator(addedUid))); QCOMPARE(contacts.size(), 1); QCOMPARE(contacts.first().getFirstname(), {"Jane"}); } { VERIFYEXEC(Sink::Store::remove(contact)); VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier)); VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); auto contacts = Sink::Store::read(Sink::Query().filter("uid", Sink::Query::Comparator(addedUid))); QCOMPARE(contacts.size(), 0); } } }; QTEST_MAIN(CardDavTest) #include "carddavtest.moc"