File indexing completed on 2024-11-10 04:40:10
0001 /* 0002 SPDX-FileCopyrightText: 2013 Christian Mollekopf <mollekopf@kolabsys.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include <QObject> 0008 0009 #include "changerecorder_p.h" 0010 #include "collectioncreatejob.h" 0011 #include "collectiondeletejob.h" 0012 #include "control.h" 0013 #include "entitytreemodel.h" 0014 #include "entitytreemodel_p.h" 0015 #include "itemcreatejob.h" 0016 #include "monitor_p.h" 0017 #include "qtest_akonadi.h" 0018 0019 using namespace Akonadi; 0020 0021 class ModelSignalSpy : public QObject 0022 { 0023 Q_OBJECT 0024 public: 0025 explicit ModelSignalSpy(QAbstractItemModel &model) 0026 { 0027 connect(&model, &QAbstractItemModel::rowsInserted, this, &ModelSignalSpy::onRowsInserted); 0028 connect(&model, &QAbstractItemModel::rowsRemoved, this, &ModelSignalSpy::onRowsRemoved); 0029 connect(&model, &QAbstractItemModel::rowsMoved, this, &ModelSignalSpy::onRowsMoved); 0030 connect(&model, &QAbstractItemModel::dataChanged, this, &ModelSignalSpy::onDataChanged); 0031 connect(&model, &QAbstractItemModel::layoutChanged, this, &ModelSignalSpy::onLayoutChanged); 0032 connect(&model, &QAbstractItemModel::modelReset, this, &ModelSignalSpy::onModelReset); 0033 } 0034 0035 QStringList mSignals; 0036 QModelIndex parent; 0037 int start; 0038 int end; 0039 0040 public Q_SLOTS: 0041 void onRowsInserted(const QModelIndex &p, int s, int e) 0042 { 0043 qDebug() << "rowsInserted( parent =" << p << ", start = " << s << ", end = " << e << ", data = " << p.data().toString() << ")"; 0044 mSignals << QStringLiteral("rowsInserted"); 0045 parent = p; 0046 start = s; 0047 end = e; 0048 } 0049 void onRowsRemoved(const QModelIndex &p, int s, int e) 0050 { 0051 qDebug() << "rowsRemoved( parent = " << p << ", start = " << s << ", end = " << e << ")"; 0052 mSignals << QStringLiteral("rowsRemoved"); 0053 parent = p; 0054 start = s; 0055 end = e; 0056 } 0057 void onRowsMoved(const QModelIndex & /*unused*/, int /*unused*/, int /*unused*/, const QModelIndex & /*unused*/, int /*unused*/) 0058 { 0059 mSignals << QStringLiteral("rowsMoved"); 0060 } 0061 void onDataChanged(const QModelIndex &tl, const QModelIndex &br) 0062 { 0063 qDebug() << "dataChanged( topLeft =" << tl << "(" << tl.data().toString() << "), bottomRight =" << br << "(" << br.data().toString() << ") )"; 0064 mSignals << QStringLiteral("dataChanged"); 0065 } 0066 void onLayoutChanged() 0067 { 0068 mSignals << QStringLiteral("layoutChanged"); 0069 } 0070 void onModelReset() 0071 { 0072 mSignals << QStringLiteral("modelReset"); 0073 } 0074 }; 0075 0076 class InspectableETM : public EntityTreeModel 0077 { 0078 public: 0079 explicit InspectableETM(ChangeRecorder *monitor, QObject *parent = nullptr) 0080 : EntityTreeModel(monitor, parent) 0081 { 0082 } 0083 EntityTreeModelPrivate *etmPrivate() 0084 { 0085 return d_ptr.get(); 0086 } 0087 }; 0088 0089 QModelIndex getIndex(const QString &string, EntityTreeModel *model) 0090 { 0091 QModelIndexList list = model->match(model->index(0, 0), Qt::DisplayRole, string, 1, Qt::MatchRecursive); 0092 if (list.isEmpty()) { 0093 return QModelIndex(); 0094 } 0095 return list.first(); 0096 } 0097 0098 Akonadi::Collection createCollection(const QString &name, const Akonadi::Collection &parent, bool enabled = true, const QStringList &mimeTypes = QStringList()) 0099 { 0100 Akonadi::Collection col; 0101 col.setParentCollection(parent); 0102 col.setName(name); 0103 col.setEnabled(enabled); 0104 col.setContentMimeTypes(mimeTypes); 0105 0106 auto create = new CollectionCreateJob(col); 0107 create->exec(); 0108 if (create->error()) { 0109 qWarning() << create->errorString(); 0110 } 0111 return create->collection(); 0112 } 0113 0114 /** 0115 * This is a test for the initial population of the ETM. 0116 */ 0117 class EtmPopulationTest : public QObject 0118 { 0119 Q_OBJECT 0120 0121 private Q_SLOTS: 0122 void initTestCase(); 0123 void testMonitoringCollectionsPreset(); 0124 void testMonitoringCollections(); 0125 void testFullPopulation(); 0126 void testAddMonitoringCollections(); 0127 void testRemoveMonitoringCollections(); 0128 void testDisplayFilter(); 0129 void testLoadingOfHiddenCollection(); 0130 0131 private: 0132 Collection res; 0133 QString mainCollectionName; 0134 Collection monitorCol; 0135 Collection col1; 0136 Collection col2; 0137 Collection col3; 0138 Collection col4; 0139 }; 0140 0141 void EtmPopulationTest::initTestCase() 0142 { 0143 qRegisterMetaType<Akonadi::Collection::Id>("Akonadi::Collection::Id"); 0144 AkonadiTest::checkTestIsIsolated(); 0145 AkonadiTest::setAllResourcesOffline(); 0146 0147 res = Collection(AkonadiTest::collectionIdFromPath(QStringLiteral("res3"))); 0148 0149 mainCollectionName = QStringLiteral("main"); 0150 monitorCol = createCollection(mainCollectionName, res); 0151 QVERIFY(monitorCol.isValid()); 0152 col1 = createCollection(QStringLiteral("col1"), monitorCol); 0153 QVERIFY(col1.isValid()); 0154 col2 = createCollection(QStringLiteral("col2"), monitorCol); 0155 QVERIFY(col2.isValid()); 0156 col3 = createCollection(QStringLiteral("col3"), monitorCol); 0157 QVERIFY(col3.isValid()); 0158 col4 = createCollection(QStringLiteral("col4"), col2); 0159 QVERIFY(col4.isValid()); 0160 } 0161 0162 void EtmPopulationTest::testMonitoringCollectionsPreset() 0163 { 0164 auto changeRecorder = new ChangeRecorder(this); 0165 changeRecorder->setCollectionMonitored(col1, true); 0166 changeRecorder->setCollectionMonitored(col2, true); 0167 AkonadiTest::akWaitForSignal(changeRecorder, &Monitor::monitorReady); 0168 auto model = new InspectableETM(changeRecorder, this); 0169 model->setItemPopulationStrategy(EntityTreeModel::ImmediatePopulation); 0170 model->setCollectionFetchStrategy(EntityTreeModel::FetchCollectionsRecursive); 0171 0172 QTRY_VERIFY(model->isCollectionTreeFetched()); 0173 QTRY_VERIFY(getIndex(QStringLiteral("col1"), model).isValid()); 0174 QTRY_VERIFY(getIndex(QStringLiteral("col2"), model).isValid()); 0175 QTRY_VERIFY(getIndex(mainCollectionName, model).isValid()); 0176 QVERIFY(!getIndex(QStringLiteral("col3"), model).isValid()); 0177 QVERIFY(getIndex(QStringLiteral("col4"), model).isValid()); 0178 0179 QTRY_VERIFY(getIndex(QStringLiteral("col1"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0180 QTRY_VERIFY(getIndex(QStringLiteral("col2"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0181 QTRY_VERIFY(!getIndex(mainCollectionName, model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0182 QTRY_VERIFY(getIndex(QStringLiteral("col4"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0183 } 0184 0185 void EtmPopulationTest::testMonitoringCollections() 0186 { 0187 auto changeRecorder = new ChangeRecorder(this); 0188 AkonadiTest::akWaitForSignal(changeRecorder, &Monitor::monitorReady); 0189 auto model = new InspectableETM(changeRecorder, this); 0190 model->setItemPopulationStrategy(EntityTreeModel::ImmediatePopulation); 0191 model->setCollectionFetchStrategy(EntityTreeModel::FetchCollectionsRecursive); 0192 Akonadi::Collection::List monitored; 0193 monitored << col1 << col2; 0194 model->setCollectionsMonitored(monitored); 0195 0196 QTRY_VERIFY(model->isCollectionTreeFetched()); 0197 QVERIFY(getIndex(QStringLiteral("col1"), model).isValid()); 0198 QVERIFY(getIndex(QStringLiteral("col2"), model).isValid()); 0199 QTRY_VERIFY(getIndex(mainCollectionName, model).isValid()); 0200 QVERIFY(!getIndex(QStringLiteral("col3"), model).isValid()); 0201 QVERIFY(getIndex(QStringLiteral("col4"), model).isValid()); 0202 0203 QTRY_VERIFY(getIndex(QStringLiteral("col1"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0204 QTRY_VERIFY(getIndex(QStringLiteral("col2"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0205 QTRY_VERIFY(!getIndex(mainCollectionName, model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0206 QTRY_VERIFY(getIndex(QStringLiteral("col4"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0207 } 0208 0209 void EtmPopulationTest::testFullPopulation() 0210 { 0211 auto changeRecorder = new ChangeRecorder(this); 0212 // changeRecorder->setCollectionMonitored(Akonadi::Collection::root()); 0213 changeRecorder->setAllMonitored(true); 0214 AkonadiTest::akWaitForSignal(changeRecorder, &Monitor::monitorReady); 0215 auto model = new InspectableETM(changeRecorder, this); 0216 model->setItemPopulationStrategy(EntityTreeModel::ImmediatePopulation); 0217 model->setCollectionFetchStrategy(EntityTreeModel::FetchCollectionsRecursive); 0218 0219 QTRY_VERIFY(model->isCollectionTreeFetched()); 0220 QVERIFY(getIndex(QStringLiteral("col1"), model).isValid()); 0221 QVERIFY(getIndex(QStringLiteral("col2"), model).isValid()); 0222 QVERIFY(getIndex(mainCollectionName, model).isValid()); 0223 QVERIFY(getIndex(QStringLiteral("col3"), model).isValid()); 0224 QVERIFY(getIndex(QStringLiteral("col4"), model).isValid()); 0225 0226 QTRY_VERIFY(getIndex(QStringLiteral("col1"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0227 QTRY_VERIFY(getIndex(QStringLiteral("col2"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0228 QTRY_VERIFY(getIndex(mainCollectionName, model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0229 QTRY_VERIFY(getIndex(QStringLiteral("col4"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0230 } 0231 0232 void EtmPopulationTest::testAddMonitoringCollections() 0233 { 0234 auto changeRecorder = new ChangeRecorder(this); 0235 changeRecorder->setCollectionMonitored(col1, true); 0236 changeRecorder->setCollectionMonitored(col2, true); 0237 AkonadiTest::akWaitForSignal(changeRecorder, &Monitor::monitorReady); 0238 auto model = new InspectableETM(changeRecorder, this); 0239 model->setItemPopulationStrategy(EntityTreeModel::ImmediatePopulation); 0240 model->setCollectionFetchStrategy(EntityTreeModel::FetchCollectionsRecursive); 0241 0242 QTRY_VERIFY(model->isCollectionTreeFetched()); 0243 // The main collection may be loaded a little later since it is in the fetchAncestors path 0244 QTRY_VERIFY(getIndex(mainCollectionName, model).isValid()); 0245 0246 model->setCollectionMonitored(col3, true); 0247 0248 QVERIFY(getIndex(QStringLiteral("col1"), model).isValid()); 0249 QVERIFY(getIndex(QStringLiteral("col2"), model).isValid()); 0250 QTRY_VERIFY(getIndex(QStringLiteral("col3"), model).isValid()); 0251 QVERIFY(getIndex(QStringLiteral("col4"), model).isValid()); 0252 QVERIFY(getIndex(mainCollectionName, model).isValid()); 0253 0254 QTRY_VERIFY(getIndex(QStringLiteral("col1"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0255 QTRY_VERIFY(getIndex(QStringLiteral("col2"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0256 QTRY_VERIFY(getIndex(QStringLiteral("col3"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0257 QTRY_VERIFY(!getIndex(mainCollectionName, model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0258 QTRY_VERIFY(getIndex(QStringLiteral("col4"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0259 } 0260 0261 void EtmPopulationTest::testRemoveMonitoringCollections() 0262 { 0263 auto changeRecorder = new ChangeRecorder(this); 0264 changeRecorder->setCollectionMonitored(col1, true); 0265 changeRecorder->setCollectionMonitored(col2, true); 0266 AkonadiTest::akWaitForSignal(changeRecorder, &Monitor::monitorReady); 0267 auto model = new InspectableETM(changeRecorder, this); 0268 model->setItemPopulationStrategy(EntityTreeModel::ImmediatePopulation); 0269 model->setCollectionFetchStrategy(EntityTreeModel::FetchCollectionsRecursive); 0270 0271 QTRY_VERIFY(model->isCollectionTreeFetched()); 0272 // The main collection may be loaded a little later since it is in the fetchAncestors path 0273 QTRY_VERIFY(getIndex(mainCollectionName, model).isValid()); 0274 0275 model->setCollectionMonitored(col2, false); 0276 0277 QVERIFY(getIndex(QStringLiteral("col1"), model).isValid()); 0278 QVERIFY(!getIndex(QStringLiteral("col2"), model).isValid()); 0279 QVERIFY(getIndex(mainCollectionName, model).isValid()); 0280 QVERIFY(!getIndex(QStringLiteral("col3"), model).isValid()); 0281 QVERIFY(!getIndex(QStringLiteral("col4"), model).isValid()); 0282 0283 QTRY_VERIFY(getIndex(QStringLiteral("col1"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0284 QTRY_VERIFY(!getIndex(QStringLiteral("col2"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0285 QTRY_VERIFY(!getIndex(mainCollectionName, model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0286 QTRY_VERIFY(!getIndex(QStringLiteral("col4"), model).data(Akonadi::EntityTreeModel::IsPopulatedRole).toBool()); 0287 } 0288 0289 void EtmPopulationTest::testDisplayFilter() 0290 { 0291 Collection col5 = createCollection(QStringLiteral("col5"), monitorCol, false); 0292 QVERIFY(col5.isValid()); 0293 0294 auto changeRecorder = new ChangeRecorder(this); 0295 auto model = new InspectableETM(changeRecorder, this); 0296 AkonadiTest::akWaitForSignal(changeRecorder, &Monitor::monitorReady); 0297 model->setItemPopulationStrategy(EntityTreeModel::ImmediatePopulation); 0298 model->setCollectionFetchStrategy(EntityTreeModel::FetchCollectionsRecursive); 0299 model->setListFilter(Akonadi::CollectionFetchScope::Display); 0300 0301 QTRY_VERIFY(model->isCollectionTreeFetched()); 0302 QVERIFY(getIndex(mainCollectionName, model).isValid()); 0303 QVERIFY(getIndex(QStringLiteral("col1"), model).isValid()); 0304 QVERIFY(getIndex(QStringLiteral("col2"), model).isValid()); 0305 QVERIFY(getIndex(QStringLiteral("col3"), model).isValid()); 0306 QVERIFY(getIndex(QStringLiteral("col4"), model).isValid()); 0307 QVERIFY(!getIndex(QStringLiteral("col5"), model).isValid()); 0308 0309 auto deleteJob = new Akonadi::CollectionDeleteJob(col5); 0310 AKVERIFYEXEC(deleteJob); 0311 } 0312 0313 /* 0314 * Col5 and it's ancestors should be included although the ancestors don't match the mimetype filter. 0315 */ 0316 void EtmPopulationTest::testLoadingOfHiddenCollection() 0317 { 0318 Collection col5 = createCollection(QStringLiteral("col5"), monitorCol, false, QStringList() << QStringLiteral("application/test")); 0319 QVERIFY(col5.isValid()); 0320 0321 auto changeRecorder = new ChangeRecorder(this); 0322 changeRecorder->setMimeTypeMonitored(QStringLiteral("application/test"), true); 0323 AkonadiTest::akWaitForSignal(changeRecorder, &Monitor::monitorReady); 0324 auto model = new InspectableETM(changeRecorder, this); 0325 model->setItemPopulationStrategy(EntityTreeModel::ImmediatePopulation); 0326 model->setCollectionFetchStrategy(EntityTreeModel::FetchCollectionsRecursive); 0327 0328 QTRY_VERIFY(model->isCollectionTreeFetched()); 0329 QVERIFY(getIndex(QStringLiteral("col5"), model).isValid()); 0330 0331 auto deleteJob = new Akonadi::CollectionDeleteJob(col5); 0332 AKVERIFYEXEC(deleteJob); 0333 } 0334 0335 #include "etmpopulationtest.moc" 0336 0337 QTEST_AKONADIMAIN(EtmPopulationTest)