File indexing completed on 2025-02-16 04:50:15

0001 /*
0002    SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
0003    SPDX-FileContributor: Kevin Ottens <kevin@kdab.com>
0004 
0005    SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "imaptestbase.h"
0009 
0010 #include "changecollectiontask.h"
0011 
0012 #include "imapaclattribute.h"
0013 #include <Akonadi/CollectionAnnotationsAttribute>
0014 #include <QTest>
0015 Q_DECLARE_METATYPE(QSet<QByteArray>)
0016 
0017 class TestChangeCollectionTask : public ImapTestBase
0018 {
0019     Q_OBJECT
0020 
0021 private Q_SLOTS:
0022     void shouldUpdateMetadataAclAndName_data()
0023     {
0024         QTest::addColumn<Akonadi::Collection>("collection");
0025         QTest::addColumn<QSet<QByteArray>>("parts");
0026         QTest::addColumn<QList<QByteArray>>("scenario");
0027         QTest::addColumn<QStringList>("callNames");
0028         QTest::addColumn<QString>("collectionName");
0029         QTest::addColumn<QStringList>("caps");
0030 
0031         Akonadi::Collection collection;
0032         QSet<QByteArray> parts;
0033         QList<QByteArray> scenario;
0034         QStringList callNames;
0035         QStringList caps;
0036 
0037         collection = createCollectionChain(QStringLiteral("/Foo"));
0038         collection.setName(QStringLiteral("Bar"));
0039         collection.setRights(Akonadi::Collection::AllRights);
0040 
0041         auto acls = new Akonadi::ImapAclAttribute;
0042         QMap<QByteArray, KIMAP::Acl::Rights> rights;
0043         // Old rights
0044         rights["test@kdab.com"] = KIMAP::Acl::rightsFromString("lrswipckxtda");
0045         rights["foo@kde.org"] = KIMAP::Acl::rightsFromString("lrswipcda");
0046         acls->setRights(rights);
0047 
0048         // New rights
0049         rights["test@kdab.com"] = KIMAP::Acl::rightsFromString("lrswipckxtda");
0050         rights["foo@kde.org"] = KIMAP::Acl::rightsFromString("lrswipcda");
0051         acls->setRights(rights);
0052         collection.addAttribute(acls);
0053 
0054         auto annotationsAttr = new Akonadi::CollectionAnnotationsAttribute;
0055         QMap<QByteArray, QByteArray> annotations;
0056         annotations["/vendor/kolab/folder-test"] = "false";
0057         annotations["/vendor/kolab/folder-test2"] = "true";
0058         annotationsAttr->setAnnotations(annotations);
0059         collection.addAttribute(annotationsAttr);
0060 
0061         parts << "NAME"
0062               << "AccessRights"
0063               << "imapacl"
0064               << "collectionannotations";
0065 
0066         caps << QStringLiteral("ACL") << QStringLiteral("ANNOTATEMORE");
0067 
0068         scenario.clear();
0069         scenario << defaultPoolConnectionScenario() << R"(C: A000003 SETACL "Foo" "test@kdab.com" "lrswipckxtda")"
0070                  << "S: A000003 OK acl changed"
0071                  << R"(C: A000004 SETANNOTATION "Foo" "/vendor/kolab/folder-test" ("value.shared" "false"))"
0072                  << "S: A000004 OK annotations changed"
0073                  << R"(C: A000005 SETANNOTATION "Foo" "/vendor/kolab/folder-test2" ("value.shared" "true"))"
0074                  << "S: A000005 OK annotations changed"
0075                  << R"(C: A000006 SETACL "Foo" "foo@kde.org" "lrswipcda")"
0076                  << "S: A000006 OK acl changed"
0077                  << R"(C: A000007 SETACL "Foo" "test@kdab.com" "lrswipckxtda")"
0078                  << "S: A000007 OK acl changed"
0079                  << R"(C: A000008 RENAME "Foo" "Bar")"
0080                  << "S: A000008 OK rename done"
0081                  << "C: A000009 SUBSCRIBE \"Bar\""
0082                  << "S: A000009 OK mailbox subscribed";
0083 
0084         callNames.clear();
0085         callNames << QStringLiteral("collectionChangeCommitted");
0086 
0087         QTest::newRow("complete case") << collection << parts << scenario << callNames << collection.name() << caps;
0088 
0089         caps.clear();
0090         caps << QStringLiteral("ACL");
0091         scenario.clear();
0092         scenario << defaultPoolConnectionScenario() << R"(C: A000003 SETACL "Foo" "test@kdab.com" "lrswipckxtda")"
0093                  << "S: A000003 OK acl changed"
0094                  << R"(C: A000004 SETACL "Foo" "foo@kde.org" "lrswipcda")"
0095                  << "S: A000004 OK acl changed"
0096                  << R"(C: A000005 SETACL "Foo" "test@kdab.com" "lrswipckxtda")"
0097                  << "S: A000005 OK acl changed"
0098                  << R"(C: A000006 RENAME "Foo" "Bar")"
0099                  << "S: A000006 OK rename done"
0100                  << "C: A000007 SUBSCRIBE \"Bar\""
0101                  << "S: A000007 OK mailbox subscribed";
0102         QTest::newRow("no ANNOTATEMORE support") << collection << parts << scenario << callNames << collection.name() << caps;
0103 
0104         collection = createCollectionChain(QStringLiteral("/Foo"));
0105         collection.setName(QStringLiteral("Bar/Baz"));
0106         caps.clear();
0107         caps << QStringLiteral("ACL") << QStringLiteral("ANNOTATEMORE");
0108         scenario.clear();
0109         scenario << defaultPoolConnectionScenario() << R"(C: A000003 RENAME "Foo" "BarBaz")"
0110                  << "S: A000003 OK rename done"
0111                  << "C: A000004 SUBSCRIBE \"BarBaz\""
0112                  << "S: A000004 OK mailbox subscribed";
0113         parts.clear();
0114         parts << "NAME";
0115         callNames.clear();
0116         callNames << QStringLiteral("collectionChangeCommitted");
0117         QTest::newRow("rename with invalid separator") << collection << parts << scenario << callNames << "BarBaz" << caps;
0118 
0119         collection = createCollectionChain(QStringLiteral(".INBOX.Foo"));
0120         collection.setName(QStringLiteral("Bar"));
0121         scenario.clear();
0122         scenario << defaultPoolConnectionScenario() << R"(C: A000003 RENAME "INBOX.Foo" "INBOX.Bar")"
0123                  << "S: A000003 OK rename done"
0124                  << "C: A000004 SUBSCRIBE \"INBOX.Bar\""
0125                  << "S: A000004 OK mailbox subscribed";
0126         QTest::newRow("rename with non-standard separator") << collection << parts << scenario << callNames << "Bar" << caps;
0127 
0128         collection = createCollectionChain(QStringLiteral("/Foo"));
0129         collection.setName(QStringLiteral("Bar"));
0130         collection.setRights(Akonadi::Collection::AllRights);
0131 
0132         acls = new Akonadi::ImapAclAttribute;
0133         // Old rights
0134         rights["test@kdab.com"] = KIMAP::Acl::rightsFromString("lrswipckxtda");
0135         rights["foo@kde.org"] = KIMAP::Acl::rightsFromString("lrswipcda");
0136         acls->setRights(rights);
0137 
0138         // New rights
0139         rights["test@kdab.com"] = KIMAP::Acl::rightsFromString("lrswipckxtda");
0140         rights["foo@kde.org"] = KIMAP::Acl::rightsFromString("lrswipcda");
0141         acls->setRights(rights);
0142         collection.addAttribute(acls);
0143 
0144         annotationsAttr = new Akonadi::CollectionAnnotationsAttribute;
0145         annotations["/vendor/kolab/folder-test"] = "false";
0146         annotations["/vendor/kolab/folder-test2"] = "true";
0147         annotationsAttr->setAnnotations(annotations);
0148         collection.addAttribute(annotationsAttr);
0149 
0150         parts << "NAME"
0151               << "AccessRights"
0152               << "imapacl"
0153               << "collectionannotations";
0154 
0155         caps << QStringLiteral("ACL") << QStringLiteral("METADATA");
0156 
0157         scenario.clear();
0158         scenario << defaultPoolConnectionScenario() << R"(C: A000003 SETACL "Foo" "test@kdab.com" "lrswipckxtda")"
0159                  << "S: A000003 OK acl changed"
0160                  << R"(C: A000004 SETMETADATA "Foo" ("/shared/vendor/kolab/folder-test" "false"))"
0161                  << "S: A000004 OK SETMETADATA complete"
0162                  << R"(C: A000005 SETMETADATA "Foo" ("/shared/vendor/kolab/folder-test2" "true"))"
0163                  << "S: A000005 OK SETMETADATA complete"
0164                  << R"(C: A000006 SETACL "Foo" "foo@kde.org" "lrswipcda")"
0165                  << "S: A000006 OK acl changed"
0166                  << R"(C: A000007 SETACL "Foo" "test@kdab.com" "lrswipckxtda")"
0167                  << "S: A000007 OK acl changed"
0168                  << R"(C: A000008 RENAME "Foo" "Bar")"
0169                  << "S: A000008 OK rename done"
0170                  << "C: A000009 SUBSCRIBE \"Bar\""
0171                  << "S: A000009 OK mailbox subscribed";
0172         QTest::newRow("complete case METADATA") << collection << parts << scenario << callNames << collection.name() << caps;
0173     }
0174 
0175     void shouldUpdateMetadataAclAndName()
0176     {
0177         QFETCH(Akonadi::Collection, collection);
0178         QFETCH(QSet<QByteArray>, parts);
0179         QFETCH(QList<QByteArray>, scenario);
0180         QFETCH(QStringList, callNames);
0181         QFETCH(QString, collectionName);
0182         QFETCH(QStringList, caps);
0183 
0184         FakeServer server;
0185         server.setScenario(scenario);
0186         server.startAndWait();
0187 
0188         SessionPool pool(1);
0189 
0190         pool.setPasswordRequester(createDefaultRequester());
0191         QVERIFY(pool.connect(createDefaultAccount()));
0192         QVERIFY(waitForSignal(&pool, SIGNAL(connectDone(int, QString))));
0193 
0194         DummyResourceState::Ptr state = DummyResourceState::Ptr(new DummyResourceState);
0195         state->setUserName(defaultUserName());
0196         state->setServerCapabilities(caps);
0197         state->setCollection(collection);
0198         state->setParts(parts);
0199         auto task = new ChangeCollectionTask(state);
0200         task->start(&pool);
0201 
0202         QTRY_COMPARE(state->calls().count(), callNames.size());
0203         for (int i = 0; i < callNames.size(); i++) {
0204             QString command = QString::fromUtf8(state->calls().at(i).first);
0205             QVariant parameter = state->calls().at(i).second;
0206 
0207             if (command == QLatin1StringView("cancelTask") && callNames[i] != QLatin1StringView("cancelTask")) {
0208                 qDebug() << "Got a cancel:" << parameter.toString();
0209             }
0210 
0211             QCOMPARE(command, callNames[i]);
0212 
0213             if (command == QLatin1StringView("cancelTask")) {
0214                 QVERIFY(!parameter.toString().isEmpty());
0215             }
0216             if (command == QLatin1StringView("collectionChangeCommitted")) {
0217                 QCOMPARE(parameter.value<Akonadi::Collection>().name(), collectionName);
0218                 QCOMPARE(parameter.value<Akonadi::Collection>().remoteId().right(collectionName.length()), collectionName);
0219             }
0220         }
0221 
0222         QVERIFY(server.isAllScenarioDone());
0223 
0224         server.quit();
0225     }
0226 };
0227 
0228 QTEST_GUILESS_MAIN(TestChangeCollectionTask)
0229 
0230 #include "testchangecollectiontask.moc"