File indexing completed on 2024-11-10 04:40:09
0001 /* 0002 SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "collectionattributetest.h" 0008 #include "collectionpathresolver.h" 0009 0010 #include "attributefactory.h" 0011 #include "collection.h" 0012 #include "collectioncreatejob.h" 0013 #include "collectiondeletejob.h" 0014 #include "collectionfetchjob.h" 0015 #include "collectionidentificationattribute.h" 0016 #include "collectionmodifyjob.h" 0017 #include "collectionrightsattribute_p.h" 0018 #include "control.h" 0019 0020 #include "qtest_akonadi.h" 0021 0022 using namespace Akonadi; 0023 0024 QTEST_AKONADIMAIN(CollectionAttributeTest) 0025 0026 class TestAttribute : public Attribute 0027 { 0028 public: 0029 TestAttribute() = default; 0030 0031 explicit TestAttribute(const QByteArray &data) 0032 : mData(data) 0033 { 0034 } 0035 TestAttribute *clone() const override 0036 { 0037 return new TestAttribute(mData); 0038 } 0039 QByteArray type() const override 0040 { 0041 return "TESTATTRIBUTE"; 0042 } 0043 QByteArray serialized() const override 0044 { 0045 return mData; 0046 } 0047 void deserialize(const QByteArray &data) override 0048 { 0049 mData = data; 0050 } 0051 0052 private: 0053 QByteArray mData; 0054 }; 0055 0056 static int parentColId = -1; 0057 0058 void CollectionAttributeTest::initTestCase() 0059 { 0060 AkonadiTest::checkTestIsIsolated(); 0061 Control::start(); 0062 AttributeFactory::registerAttribute<TestAttribute>(); 0063 0064 auto resolver = new CollectionPathResolver(QStringLiteral("res3"), this); 0065 AKVERIFYEXEC(resolver); 0066 parentColId = resolver->collection(); 0067 QVERIFY(parentColId > 0); 0068 } 0069 0070 void CollectionAttributeTest::testAttributes_data() 0071 { 0072 QTest::addColumn<QByteArray>("attr1"); 0073 QTest::addColumn<QByteArray>("attr2"); 0074 0075 QTest::newRow("basic") << QByteArray("foo") << QByteArray("bar"); 0076 QTest::newRow("empty1") << QByteArray("") << QByteArray("non-empty"); 0077 #if 0 // This one is failing on the CI with SQLite. Can't reproduce locally and 0078 // it works with other DB backends, so I have no idea what is going on... 0079 QTest::newRow("empty2") << QByteArray("non-empty") << QByteArray(""); 0080 #endif 0081 QTest::newRow("space") << QByteArray("foo bar") << QByteArray("bar foo"); 0082 QTest::newRow("newline") << QByteArray("\n") << QByteArray("no newline"); 0083 QTest::newRow("newline2") << QByteArray(" \\\n\\\nnn") << QByteArray("no newline"); 0084 QTest::newRow("cr") << QByteArray("\r") << QByteArray("\\\r\n"); 0085 QTest::newRow("quotes") << QByteArray(R"("quoted \ test")") << QByteArray("single \" quote \\"); 0086 QTest::newRow("parenthesis") << QByteArray(")") << QByteArray("("); 0087 QTest::newRow("binary") << QByteArray("\000") << QByteArray("\001"); 0088 } 0089 0090 void CollectionAttributeTest::testAttributes() 0091 { 0092 QFETCH(QByteArray, attr1); 0093 QFETCH(QByteArray, attr2); 0094 0095 struct Cleanup { 0096 explicit Cleanup(const Collection &col) 0097 : m_col(col) 0098 { 0099 } 0100 ~Cleanup() 0101 { 0102 // cleanup 0103 auto del = new CollectionDeleteJob(m_col); 0104 AKVERIFYEXEC(del); 0105 } 0106 Collection m_col; 0107 }; 0108 0109 // add a custom attribute 0110 auto attr = new TestAttribute(); 0111 attr->deserialize(attr1); 0112 Collection col; 0113 col.setName(QStringLiteral("attribute test")); 0114 col.setParentCollection(Collection(parentColId)); 0115 col.addAttribute(attr); 0116 auto create = new CollectionCreateJob(col, this); 0117 AKVERIFYEXEC(create); 0118 col = create->collection(); 0119 QVERIFY(col.isValid()); 0120 Cleanup cleanup(col); 0121 0122 attr = col.attribute<TestAttribute>(); 0123 QVERIFY(attr != nullptr); 0124 QCOMPARE(attr->serialized(), QByteArray(attr1)); 0125 0126 auto list = new CollectionFetchJob(col, CollectionFetchJob::Base, this); 0127 AKVERIFYEXEC(list); 0128 QCOMPARE(list->collections().count(), 1); 0129 col = list->collections().at(0); 0130 0131 QVERIFY(col.isValid()); 0132 attr = col.attribute<TestAttribute>(); 0133 QVERIFY(attr != nullptr); 0134 QCOMPARE(attr->serialized(), QByteArray(attr1)); 0135 0136 auto attrB = new TestAttribute(); 0137 attrB->deserialize(attr2); 0138 col.addAttribute(attrB); 0139 attrB = col.attribute<TestAttribute>(); 0140 QVERIFY(attrB != nullptr); 0141 QCOMPARE(attrB->serialized(), QByteArray(attr2)); 0142 0143 attrB->deserialize(attr1); 0144 col.addAttribute(attrB); 0145 attrB = col.attribute<TestAttribute>(); 0146 QVERIFY(attrB != nullptr); 0147 QCOMPARE(attrB->serialized(), QByteArray(attr1)); 0148 0149 // this will mark the attribute as modified in the storage, but should not create trouble further down 0150 QVERIFY(!col.attribute("does_not_exist")); 0151 0152 // modify a custom attribute 0153 col.attribute<TestAttribute>(Collection::AddIfMissing)->deserialize(attr2); 0154 auto modify = new CollectionModifyJob(col, this); 0155 AKVERIFYEXEC(modify); 0156 0157 list = new CollectionFetchJob(col, CollectionFetchJob::Base, this); 0158 AKVERIFYEXEC(list); 0159 QCOMPARE(list->collections().count(), 1); 0160 col = list->collections().at(0); 0161 0162 QVERIFY(col.isValid()); 0163 attr = col.attribute<TestAttribute>(); 0164 QVERIFY(attr != nullptr); 0165 QCOMPARE(attr->serialized(), QByteArray(attr2)); 0166 0167 // delete a custom attribute 0168 col.removeAttribute<TestAttribute>(); 0169 modify = new CollectionModifyJob(col, this); 0170 AKVERIFYEXEC(modify); 0171 0172 list = new CollectionFetchJob(col, CollectionFetchJob::Base, this); 0173 AKVERIFYEXEC(list); 0174 QCOMPARE(list->collections().count(), 1); 0175 col = list->collections().at(0); 0176 0177 QVERIFY(col.isValid()); 0178 attr = col.attribute<TestAttribute>(); 0179 QVERIFY(attr == nullptr); 0180 0181 // Give the knut resource a bit of time to modify the collection and add a remote ID (after adding) 0182 // and reparent attributes (after modifying). 0183 // Otherwise we can delete it faster than it can do that, and we end up with a confusing warning 0184 // "No such collection" from the resource's modify job. 0185 QTest::qWait(100); // ideally we'd loop over "fetch and check there's a remote id" 0186 } 0187 0188 void CollectionAttributeTest::testDefaultAttributes() 0189 { 0190 Collection col; 0191 QCOMPARE(col.attributes().count(), 0); 0192 Attribute *attr = AttributeFactory::createAttribute("TYPE"); 0193 QVERIFY(attr); 0194 attr->deserialize("VALUE"); 0195 col.addAttribute(attr); 0196 QCOMPARE(col.attributes().count(), 1); 0197 QVERIFY(col.hasAttribute("TYPE")); 0198 QCOMPARE(col.attribute("TYPE")->serialized(), QByteArray("VALUE")); 0199 } 0200 0201 void CollectionAttributeTest::testCollectionRightsAttribute() 0202 { 0203 CollectionRightsAttribute attribute; 0204 Collection::Rights rights; 0205 0206 QCOMPARE(attribute.rights(), rights); 0207 0208 for (int mask = 0; mask <= Collection::AllRights; ++mask) { 0209 rights = Collection::AllRights; 0210 rights &= mask; 0211 QCOMPARE(rights, mask); 0212 0213 attribute.setRights(rights); 0214 QCOMPARE(attribute.rights(), rights); 0215 0216 QByteArray data = attribute.serialized(); 0217 attribute.deserialize(data); 0218 QCOMPARE(attribute.rights(), rights); 0219 } 0220 } 0221 0222 void CollectionAttributeTest::testCollectionIdentificationAttribute() 0223 { 0224 QByteArray id("identifier"); 0225 QByteArray ns("namespace"); 0226 CollectionIdentificationAttribute attribute(id, ns); 0227 QCOMPARE(attribute.identifier(), id); 0228 QCOMPARE(attribute.collectionNamespace(), ns); 0229 0230 QByteArray result = attribute.serialized(); 0231 CollectionIdentificationAttribute parsed; 0232 parsed.deserialize(result); 0233 qDebug() << parsed.identifier() << parsed.collectionNamespace() << result; 0234 QCOMPARE(parsed.identifier(), id); 0235 QCOMPARE(parsed.collectionNamespace(), ns); 0236 } 0237 0238 void CollectionAttributeTest::testDetach() 0239 { 0240 // GIVEN a collection with an attribute 0241 Collection col; 0242 col.attribute<TestAttribute>(Akonadi::Collection::AddIfMissing); 0243 Collection col2 = col; // and a copy, so that non-const access detaches 0244 0245 // WHEN 0246 auto attr = col2.attribute<TestAttribute>(Akonadi::Collection::AddIfMissing); 0247 auto attr2 = col2.attribute<TestAttribute>(); 0248 0249 // THEN 0250 QCOMPARE(attr, attr2); 0251 } 0252 0253 #include "moc_collectionattributetest.cpp"