File indexing completed on 2025-01-05 04:59:53
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Kevin Ottens <ervin@kde.org> 0003 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 0006 0007 #include <testlib/qtest_zanshin.h> 0008 0009 #include "utils/mockobject.h" 0010 0011 #include "testlib/akonadifakejobs.h" 0012 #include "testlib/akonadifakemonitor.h" 0013 0014 #include "akonadi/akonadiprojectrepository.h" 0015 #include "akonadi/akonadiserializerinterface.h" 0016 #include "akonadi/akonadistorageinterface.h" 0017 0018 using namespace mockitopp; 0019 0020 Q_DECLARE_METATYPE(Testlib::AkonadiFakeItemFetchJob*) 0021 0022 class AkonadiProjectRepositoryTest : public QObject 0023 { 0024 Q_OBJECT 0025 private slots: 0026 void shouldCreateProjectInDataSource() 0027 { 0028 // GIVEN 0029 0030 // A project and its corresponding item already not existing in storage 0031 Akonadi::Item item; 0032 auto project = Domain::Project::Ptr::create(); 0033 0034 // A data source and its corresponding collection existing in storage 0035 Akonadi::Collection collection(42); 0036 auto source = Domain::DataSource::Ptr::create(); 0037 0038 // A mock create job 0039 auto itemCreateJob = new FakeJob(this); 0040 0041 // Storage mock returning the create job 0042 Utils::MockObject<Akonadi::StorageInterface> storageMock; 0043 storageMock(&Akonadi::StorageInterface::createItem).when(item, collection) 0044 .thenReturn(itemCreateJob); 0045 0046 // Serializer mock 0047 Utils::MockObject<Akonadi::SerializerInterface> serializerMock; 0048 serializerMock(&Akonadi::SerializerInterface::createItemFromProject).when(project).thenReturn(item); 0049 serializerMock(&Akonadi::SerializerInterface::createCollectionFromDataSource).when(source).thenReturn(collection); 0050 0051 // WHEN 0052 QScopedPointer<Akonadi::ProjectRepository> repository(new Akonadi::ProjectRepository(storageMock.getInstance(), 0053 serializerMock.getInstance())); 0054 repository->create(project, source)->exec(); 0055 0056 // THEN 0057 QVERIFY(storageMock(&Akonadi::StorageInterface::createItem).when(item, collection).exactly(1)); 0058 } 0059 0060 void shouldUpdateExistingProject() 0061 { 0062 // GIVEN 0063 0064 // A project and its corresponding item already existing in storage 0065 Akonadi::Item item(42); 0066 Domain::Project::Ptr project(new Domain::Project); 0067 0068 // A mock modify job 0069 auto itemModifyJob = new FakeJob(this); 0070 0071 Utils::MockObject<Akonadi::StorageInterface> storageMock; 0072 Utils::MockObject<Akonadi::SerializerInterface> serializerMock; 0073 QScopedPointer<Akonadi::ProjectRepository> repository(new Akonadi::ProjectRepository(storageMock.getInstance(), 0074 serializerMock.getInstance())); 0075 0076 // Storage mock returning the create job 0077 storageMock(&Akonadi::StorageInterface::updateItem).when(item, repository.get()) 0078 .thenReturn(itemModifyJob); 0079 0080 // Serializer mock returning the item for the project 0081 serializerMock(&Akonadi::SerializerInterface::createItemFromProject).when(project).thenReturn(item); 0082 0083 // WHEN 0084 repository->update(project)->exec(); 0085 0086 // THEN 0087 QVERIFY(serializerMock(&Akonadi::SerializerInterface::createItemFromProject).when(project).exactly(1)); 0088 QVERIFY(storageMock(&Akonadi::StorageInterface::updateItem).when(item, repository.get()).exactly(1)); 0089 } 0090 0091 void shouldRemoveExistingProject() 0092 { 0093 // GIVEN 0094 0095 // A project and its corresponding item already existing in storage 0096 Akonadi::Item item(42); 0097 auto project = Domain::Project::Ptr::create(); 0098 0099 // A mock remove job 0100 auto itemRemoveJob = new FakeJob(this); 0101 0102 Utils::MockObject<Akonadi::StorageInterface> storageMock; 0103 Utils::MockObject<Akonadi::SerializerInterface> serializerMock; 0104 QScopedPointer<Akonadi::ProjectRepository> repository(new Akonadi::ProjectRepository(storageMock.getInstance(), 0105 serializerMock.getInstance())); 0106 0107 // Storage mock returning the create job 0108 storageMock(&Akonadi::StorageInterface::removeItem).when(item, repository.get()) 0109 .thenReturn(itemRemoveJob); 0110 0111 // Serializer mock returning the item for the project 0112 serializerMock(&Akonadi::SerializerInterface::createItemFromProject).when(project).thenReturn(item); 0113 0114 // WHEN 0115 repository->remove(project)->exec(); 0116 0117 // THEN 0118 QVERIFY(storageMock(&Akonadi::StorageInterface::removeItem).when(item, repository.get()).exactly(1)); 0119 } 0120 0121 void shouldAssociateATaskToAProject_data() 0122 { 0123 QTest::addColumn<Akonadi::Item>("childItem"); 0124 QTest::addColumn<Akonadi::Item>("parentItem"); 0125 QTest::addColumn<Domain::Task::Ptr>("child"); 0126 QTest::addColumn<Domain::Project::Ptr>("parent"); 0127 QTest::addColumn<Testlib::AkonadiFakeItemFetchJob*>("itemFetchJob1"); 0128 QTest::addColumn<Testlib::AkonadiFakeItemFetchJob*>("itemFetchJob2"); 0129 QTest::addColumn<Testlib::AkonadiFakeItemFetchJob*>("itemFetchJob3"); 0130 QTest::addColumn<bool>("execJob"); 0131 QTest::addColumn<bool>("execParentJob"); 0132 QTest::addColumn<Akonadi::Item::List>("list"); 0133 0134 Akonadi::Collection col(40); 0135 0136 Akonadi::Item childItem(42); 0137 childItem.setParentCollection(col); 0138 Domain::Task::Ptr childTask(new Domain::Task); 0139 0140 Akonadi::Item parentItem(41); 0141 parentItem.setParentCollection(col); 0142 auto parent = Domain::Project::Ptr::create(); 0143 0144 auto itemFetchJob1 = new Testlib::AkonadiFakeItemFetchJob(this); 0145 itemFetchJob1->setItems(Akonadi::Item::List() << childItem); 0146 auto itemFetchJob2 = new Testlib::AkonadiFakeItemFetchJob(this); 0147 itemFetchJob2->setItems(Akonadi::Item::List() << parentItem); 0148 auto itemFetchJob3 = new Testlib::AkonadiFakeItemFetchJob(this); 0149 0150 Akonadi::Item::List list; 0151 0152 QTest::newRow("nominal case (task)") << childItem << parentItem << childTask << parent << itemFetchJob1 << itemFetchJob2 << itemFetchJob3 << true << true << list; 0153 0154 itemFetchJob1 = new Testlib::AkonadiFakeItemFetchJob(this); 0155 itemFetchJob1->setExpectedError(KJob::KilledJobError); 0156 QTest::newRow("child job error with empty list") << childItem << parentItem << childTask << parent << itemFetchJob1 << itemFetchJob2 << itemFetchJob3 << false << false << list; 0157 0158 itemFetchJob1 = new Testlib::AkonadiFakeItemFetchJob(this); 0159 itemFetchJob1->setExpectedError(KJob::KilledJobError); 0160 itemFetchJob1->setItems(Akonadi::Item::List() << childItem); 0161 QTest::newRow("child job error with item (task)") << childItem << parentItem << childTask << parent << itemFetchJob1 << itemFetchJob2 << itemFetchJob3 << false << false << list; 0162 0163 itemFetchJob1 = new Testlib::AkonadiFakeItemFetchJob(this); 0164 itemFetchJob1->setItems(Akonadi::Item::List() << childItem); 0165 itemFetchJob2 = new Testlib::AkonadiFakeItemFetchJob(this); 0166 itemFetchJob2->setExpectedError(KJob::KilledJobError); 0167 QTest::newRow("parent job error with empty list (task)") << childItem << parentItem << childTask << parent << itemFetchJob1 << itemFetchJob2 << itemFetchJob3 << true << false << list; 0168 0169 itemFetchJob1 = new Testlib::AkonadiFakeItemFetchJob(this); 0170 itemFetchJob1->setItems(Akonadi::Item::List() << childItem); 0171 itemFetchJob2 = new Testlib::AkonadiFakeItemFetchJob(this); 0172 itemFetchJob2->setExpectedError(KJob::KilledJobError); 0173 itemFetchJob2->setItems(Akonadi::Item::List() << parentItem); 0174 QTest::newRow("parent job error with item (task)") << childItem << parentItem << childTask << parent << itemFetchJob1 << itemFetchJob2 << itemFetchJob3 << true << false << list; 0175 0176 itemFetchJob1 = new Testlib::AkonadiFakeItemFetchJob(this); 0177 itemFetchJob1->setItems(Akonadi::Item::List() << childItem); 0178 itemFetchJob2 = new Testlib::AkonadiFakeItemFetchJob(this); 0179 Akonadi::Collection col2(39); 0180 Akonadi::Item parentItem2(41); 0181 parentItem2.setParentCollection(col2); 0182 itemFetchJob2->setItems(Akonadi::Item::List() << parentItem2); 0183 itemFetchJob3 = new Testlib::AkonadiFakeItemFetchJob(this); 0184 QTest::newRow("update and move item (task)") << childItem << parentItem2 << childTask << parent << itemFetchJob1 << itemFetchJob2 << itemFetchJob3 << true << true << list; 0185 0186 itemFetchJob1 = new Testlib::AkonadiFakeItemFetchJob(this); 0187 itemFetchJob1->setItems(Akonadi::Item::List() << childItem); 0188 itemFetchJob2 = new Testlib::AkonadiFakeItemFetchJob(this); 0189 itemFetchJob2->setItems(Akonadi::Item::List() << parentItem2); 0190 itemFetchJob3 = new Testlib::AkonadiFakeItemFetchJob(this); 0191 Akonadi::Item childItem2(43); 0192 Akonadi::Item::List list2; 0193 list2 << childItem2; 0194 itemFetchJob3->setItems(list2); 0195 QTest::newRow("update and move item and his child (task)") << childItem << parentItem2 << childTask << parent << itemFetchJob1 << itemFetchJob2 << itemFetchJob3 << true << true << list2; 0196 } 0197 0198 void shouldAssociateATaskToAProject() 0199 { 0200 // GIVEN 0201 QFETCH(Akonadi::Item, childItem); 0202 QFETCH(Akonadi::Item, parentItem); 0203 QFETCH(Domain::Task::Ptr, child); 0204 QFETCH(Domain::Project::Ptr, parent); 0205 QFETCH(Testlib::AkonadiFakeItemFetchJob*, itemFetchJob1); 0206 QFETCH(Testlib::AkonadiFakeItemFetchJob*, itemFetchJob2); 0207 QFETCH(Testlib::AkonadiFakeItemFetchJob*, itemFetchJob3); 0208 QFETCH(bool, execJob); 0209 QFETCH(bool, execParentJob); 0210 QFETCH(Akonadi::Item::List, list); 0211 0212 // A mock create job 0213 auto itemModifyJob = new FakeJob(this); 0214 auto transactionJob = new FakeJob(this); 0215 auto itemsMoveJob = new FakeJob(this); 0216 0217 Akonadi::Item::List movedList; 0218 movedList << childItem << list; 0219 0220 Utils::MockObject<Akonadi::StorageInterface> storageMock; 0221 Utils::MockObject<Akonadi::SerializerInterface> serializerMock; 0222 QScopedPointer<Akonadi::ProjectRepository> repository(new Akonadi::ProjectRepository(storageMock.getInstance(), 0223 serializerMock.getInstance())); 0224 0225 // Storage mock returning the create job 0226 storageMock(&Akonadi::StorageInterface::fetchItem).when(childItem, repository.get()) 0227 .thenReturn(itemFetchJob1); 0228 storageMock(&Akonadi::StorageInterface::fetchItem).when(parentItem, repository.get()) 0229 .thenReturn(itemFetchJob2); 0230 if (parentItem.parentCollection().id() != childItem.parentCollection().id()) { 0231 storageMock(&Akonadi::StorageInterface::fetchItems).when(childItem.parentCollection(), repository.get()) 0232 .thenReturn(itemFetchJob3); 0233 storageMock(&Akonadi::StorageInterface::createTransaction).when(repository.get()).thenReturn(transactionJob); 0234 storageMock(&Akonadi::StorageInterface::updateItem).when(childItem, transactionJob) 0235 .thenReturn(itemModifyJob); 0236 storageMock(&Akonadi::StorageInterface::moveItems).when(movedList, parentItem.parentCollection(), transactionJob) 0237 .thenReturn(itemsMoveJob); 0238 } else { 0239 storageMock(&Akonadi::StorageInterface::updateItem).when(childItem, repository.get()) 0240 .thenReturn(itemModifyJob); 0241 } 0242 0243 // Serializer mock returning the item for the task 0244 serializerMock(&Akonadi::SerializerInterface::createItemFromTask).when(child).thenReturn(childItem); 0245 serializerMock(&Akonadi::SerializerInterface::createItemFromProject).when(parent).thenReturn(parentItem); 0246 serializerMock(&Akonadi::SerializerInterface::updateItemProject).when(childItem, parent).thenReturn(); 0247 if (execParentJob) 0248 serializerMock(&Akonadi::SerializerInterface::filterDescendantItems).when(list, childItem).thenReturn(list); 0249 0250 // WHEN 0251 auto associateJob = repository->associate(parent, child); 0252 if (execJob) 0253 associateJob->exec(); 0254 0255 // THEN 0256 QVERIFY(storageMock(&Akonadi::StorageInterface::fetchItem).when(childItem, repository.get()).exactly(1)); 0257 if (execJob) { 0258 QVERIFY(serializerMock(&Akonadi::SerializerInterface::updateItemProject).when(childItem, parent).exactly(1)); 0259 QVERIFY(serializerMock(&Akonadi::SerializerInterface::createItemFromProject).when(parent).exactly(1)); 0260 QVERIFY(storageMock(&Akonadi::StorageInterface::fetchItem).when(parentItem, repository.get()).exactly(1)); 0261 if (execParentJob) { 0262 if (parentItem.parentCollection().id() != childItem.parentCollection().id()) { 0263 QVERIFY(storageMock(&Akonadi::StorageInterface::fetchItems).when(childItem.parentCollection(), repository.get()).exactly(1)); 0264 QVERIFY(storageMock(&Akonadi::StorageInterface::createTransaction).when(repository.get()).thenReturn(transactionJob).exactly(1)); 0265 QVERIFY(storageMock(&Akonadi::StorageInterface::updateItem).when(childItem, transactionJob).exactly(1)); 0266 QVERIFY(storageMock(&Akonadi::StorageInterface::moveItems).when(movedList, parentItem.parentCollection(), transactionJob).exactly(1)); 0267 } else { 0268 QVERIFY(storageMock(&Akonadi::StorageInterface::updateItem).when(childItem, repository.get()).exactly(1)); 0269 } 0270 } 0271 } 0272 } 0273 0274 void shouldDissociateATaskFromItsProject_data() 0275 { 0276 QTest::addColumn<Domain::Task::Ptr>("child"); 0277 QTest::addColumn<Akonadi::Item>("childItem"); 0278 QTest::addColumn<Testlib::AkonadiFakeItemFetchJob*>("itemFetchJob"); 0279 QTest::addColumn<bool>("fetchJobFailed"); 0280 0281 Domain::Task::Ptr taskChild(new Domain::Task); 0282 Akonadi::Item childItem(42); 0283 0284 auto itemFetchJob = new Testlib::AkonadiFakeItemFetchJob(this); 0285 itemFetchJob->setItems(Akonadi::Item::List() << childItem); 0286 QTest::newRow("task nominal case") << taskChild << childItem << itemFetchJob << false; 0287 0288 itemFetchJob = new Testlib::AkonadiFakeItemFetchJob(this); 0289 itemFetchJob->setExpectedError(KJob::KilledJobError); 0290 QTest::newRow("task job error with empty list") << taskChild << childItem << itemFetchJob << true; 0291 0292 itemFetchJob = new Testlib::AkonadiFakeItemFetchJob(this); 0293 itemFetchJob->setExpectedError(KJob::KilledJobError); 0294 itemFetchJob->setItems(Akonadi::Item::List() << childItem); 0295 QTest::newRow("task job error with item") << taskChild << childItem << itemFetchJob << true; 0296 } 0297 0298 void shouldDissociateATaskFromItsProject() 0299 { 0300 // GIVEN 0301 QFETCH(Domain::Task::Ptr, child); 0302 QFETCH(Akonadi::Item, childItem); 0303 QFETCH(Testlib::AkonadiFakeItemFetchJob*, itemFetchJob); 0304 QFETCH(bool, fetchJobFailed); 0305 0306 auto itemModifyJob = new FakeJob(this); 0307 0308 Utils::MockObject<Akonadi::StorageInterface> storageMock; 0309 Utils::MockObject<Akonadi::SerializerInterface> serializerMock; 0310 QScopedPointer<Akonadi::ProjectRepository> repository(new Akonadi::ProjectRepository(storageMock.getInstance(), 0311 serializerMock.getInstance())); 0312 0313 // Storage mock returning the delete job 0314 storageMock(&Akonadi::StorageInterface::updateItem).when(childItem, repository.get()) 0315 .thenReturn(itemModifyJob); 0316 storageMock(&Akonadi::StorageInterface::fetchItem).when(childItem, repository.get()) 0317 .thenReturn(itemFetchJob); 0318 0319 // Serializer mock returning the item for the task 0320 serializerMock(&Akonadi::SerializerInterface::createItemFromTask).when(child).thenReturn(childItem); 0321 serializerMock(&Akonadi::SerializerInterface::removeItemParent).when(childItem).thenReturn(); 0322 0323 // WHEN 0324 repository->dissociate(child)->exec(); 0325 0326 // THEN 0327 QVERIFY(serializerMock(&Akonadi::SerializerInterface::createItemFromTask).when(child).exactly(1)); 0328 0329 QVERIFY(storageMock(&Akonadi::StorageInterface::fetchItem).when(childItem, repository.get()).exactly(1)); 0330 if (!fetchJobFailed) { 0331 QVERIFY(serializerMock(&Akonadi::SerializerInterface::removeItemParent).when(childItem).exactly(1));; 0332 QVERIFY(storageMock(&Akonadi::StorageInterface::updateItem).when(childItem, repository.get()).exactly(1)); 0333 } 0334 0335 // Give a chance to job to delete themselves 0336 // in case of an error (since they use deleteLater() internally) 0337 QTest::qWait(10); 0338 } 0339 }; 0340 0341 ZANSHIN_TEST_MAIN(AkonadiProjectRepositoryTest) 0342 0343 #include "akonadiprojectrepositorytest.moc"