1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2009-12-11
7  * Description : test cases for the various album models
8  *
9  * Copyright (C) 2009 by Johannes Wienke <languitar at semipol dot de>
10  *
11  * This program is free software; you can redistribute it
12  * and/or modify it under the terms of the GNU General
13  * Public License as published by the Free Software Foundation;
14  * either version 2, or (at your option)
15  * any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * ============================================================ */
23 
24 #include "albummodel_utest.h"
25 
26 // Qt includes
27 
28 #include <QDir>
29 #include <QTest>
30 #include <QUrl>
31 
32 // Local includes
33 
34 #include "digikam_debug.h"
35 #include "albumfiltermodel.h"
36 #include "albummanager.h"
37 #include "albummodel.h"
38 #include "applicationsettings.h"
39 #include "albumthumbnailloader.h"
40 #include "collectionlocation.h"
41 #include "collectionmanager.h"
42 #include "loadingcacheinterface.h"
43 #include "scancontroller.h"
44 #include "thumbnailloadthread.h"
45 #include "modeltest.h"
46 
47 using namespace Digikam;
48 
49 const QString IMAGE_PATH(QFINDTESTDATA("data/"));
50 
QTEST_MAIN(AlbumModelTest)51 QTEST_MAIN(AlbumModelTest)
52 
53 AlbumModelTest::AlbumModelTest(QObject* const parent)
54     : QObject(parent),
55       albumCategory(QLatin1String("DummyCategory")),
56       palbumRoot0(nullptr),
57       palbumRoot1(nullptr),
58       palbumRoot2(nullptr),
59       palbumChild0Root0(nullptr),
60       palbumChild1Root0(nullptr),
61       palbumChild2Root0(nullptr),
62       palbumChild0Root1(nullptr),
63       rootTag(nullptr),
64       talbumRoot0(nullptr),
65       talbumRoot1(nullptr),
66       talbumChild0Root0(nullptr),
67       talbumChild1Root0(nullptr),
68       talbumChild0Child1Root0(nullptr),
69       talbumChild0Root1(nullptr),
70       startModel(nullptr)
71 {
72 }
73 
~AlbumModelTest()74 AlbumModelTest::~AlbumModelTest()
75 {
76 }
77 
initTestCase()78 void AlbumModelTest::initTestCase()
79 {
80     tempSuffix = QLatin1String("albummodeltest-") + QTime::currentTime().toString();
81     dbPath     = QDir::temp().absolutePath() + QLatin1Char('/') + tempSuffix;
82 
83     if (QDir::temp().exists(tempSuffix))
84     {
85         QString msg = QLatin1String("Error creating temp path") + dbPath;
86         QVERIFY2(false, msg.toLatin1().constData());
87     }
88 
89     QDir::temp().mkdir(tempSuffix);
90 
91     qCDebug(DIGIKAM_TESTS_LOG) << "Using database path for test: " << dbPath;
92 
93     ApplicationSettings::instance()->setShowFolderTreeViewItemsCount(true);
94 
95     // use a testing database
96 
97     AlbumManager::instance();
98 
99     // catch palbum counts for waiting
100 
101     connect(AlbumManager::instance(), SIGNAL(signalPAlbumsDirty(QMap<int,int>)),
102             this, SLOT(setLastPAlbumCountMap(QMap<int,int>)));
103 
104     AlbumManager::checkDatabaseDirsAfterFirstRun(QDir::temp().absoluteFilePath(
105                                                  tempSuffix), QDir::temp().absoluteFilePath(tempSuffix));
106     DbEngineParameters params(QLatin1String("QSQLITE"), QDir::temp().absoluteFilePath(tempSuffix + QLatin1String("/digikam4.db")),
107                               QString(), QString(), -1, false, QString(), QString());
108     bool dbChangeGood = AlbumManager::instance()->setDatabase(params, false,
109                         QDir::temp().absoluteFilePath(tempSuffix));
110     QVERIFY2(dbChangeGood, "Could not set temp album db");
111     QList<CollectionLocation> locs = CollectionManager::instance()->allAvailableLocations();
112     QVERIFY2(locs.size(), "Failed to auto-create one collection in setDatabase");
113 
114     ScanController::instance()->completeCollectionScan();
115     AlbumManager::instance()->startScan();
116 
117     AlbumList all = AlbumManager::instance()->allPAlbums();
118     qCDebug(DIGIKAM_TESTS_LOG) << "PAlbum registered : " << all.size();
119 
120     foreach (Album* const a, all)
121     {
122         if (a)
123         {
124             qCDebug(DIGIKAM_TESTS_LOG) << " ==> Id : " << a->id() << " , is root : " << a->isRoot() << " , title : " << a->title();
125         }
126     }
127 
128     QVERIFY2( all.size() == 3, "Failed to scan empty directory. We must have one root album, one album, and one trash.");
129 }
130 
cleanupTestCase()131 void AlbumModelTest::cleanupTestCase()
132 {
133     qCDebug(DIGIKAM_TESTS_LOG) << "Start AlbumModelTest::cleanupTestCase()";
134 
135     ScanController::instance()->shutDown();
136     AlbumManager::instance()->cleanUp();
137     ThumbnailLoadThread::cleanUp();
138     AlbumThumbnailLoader::instance()->cleanUp();
139     LoadingCacheInterface::cleanUp();
140 
141     QDir dir(dbPath);
142     dir.removeRecursively();
143 
144     qCDebug(DIGIKAM_TESTS_LOG) << "deleted test folder " << dbPath;
145 }
146 
147 // Qt test doesn't use exceptions, so using assertion macros in methods called
148 // from a test slot doesn't stop the test method and may result in inconsistent
149 // data or segfaults. Therefore use macros for these functions.
150 
151 #define safeCreatePAlbum(parent, name, result) \
152 { \
153     QString error3; \
154     result = AlbumManager::instance()->createPAlbum(parent, name, name, \
155                     QDate::currentDate(), albumCategory, error3); \
156     QVERIFY2(result, QString::fromUtf8("Error creating PAlbum for test: %1").arg(error3).toLatin1().constData()); \
157 }
158 
159 #define safeCreateTAlbum(parent, name, result) \
160 { \
161     QString error2; \
162     result = AlbumManager::instance()->createTAlbum(parent, name, QLatin1String(""), error2); \
163     QVERIFY2(result, QString::fromUtf8("Error creating TAlbum for test: %1").arg(error2).toLatin1().constData()); \
164 }
165 
init()166 void AlbumModelTest::init()
167 {
168     qCDebug(DIGIKAM_TESTS_LOG) << "Start AlbumModelTest::init()";
169 
170     palbumCountMap.clear();
171 
172     // create a model to check that model work is done correctly while scanning
173 
174     addedIds.clear();
175     startModel = new AlbumModel;
176     startModel->setShowCount(true);
177 
178     connect(startModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
179             this, SLOT(slotStartModelRowsInserted(QModelIndex,int,int)));
180 
181     connect(startModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
182             this, SLOT(slotStartModelDataChanged(QModelIndex,QModelIndex)));
183 
184     qCDebug(DIGIKAM_TESTS_LOG) << "Created startModel" << startModel;
185 
186     // ensure that this model is empty in the beginning except for the root
187     // album and the collection that include trash
188 
189     QCOMPARE(startModel->rowCount(), 1);
190     QModelIndex rootIndex = startModel->index(0, 0);
191     QCOMPARE(startModel->rowCount(rootIndex), 1);
192     QModelIndex collectionIndex = startModel->index(0, 0, rootIndex);
193     QCOMPARE(startModel->rowCount(collectionIndex), 1);
194 
195     // insert some test data
196 
197     // physical albums
198 
199     // create two of them by creating directories and scanning
200 
201     QDir dir(dbPath);
202     dir.mkdir(QLatin1String("root0"));
203     dir.mkdir(QLatin1String("root1"));
204 
205     ScanController::instance()->completeCollectionScan();
206     AlbumManager::instance()->refresh();
207 
208     QCOMPARE(AlbumManager::instance()->allPAlbums().size(), 5);
209 
210     QString error1;
211     palbumRoot0 = AlbumManager::instance()->findPAlbum(QUrl::fromLocalFile(dbPath + QLatin1String("/root0")));
212     QVERIFY2(palbumRoot0, "Error having PAlbum root0 in AlbumManager");
213     palbumRoot1 = AlbumManager::instance()->findPAlbum(QUrl::fromLocalFile(dbPath + QLatin1String("/root1")));
214     QVERIFY2(palbumRoot1, "Error having PAlbum root1 in AlbumManager");
215 
216     // Create some more through AlbumManager
217 
218     palbumRoot2 = AlbumManager::instance()->createPAlbum(dbPath, QLatin1String("root2"),
219                   QLatin1String("root album 2"), QDate::currentDate(), albumCategory, error1);
220     QVERIFY2(palbumRoot2, QString::fromUtf8("Error creating PAlbum for test: %1").arg(error1).toLatin1().constData());
221 
222     safeCreatePAlbum(palbumRoot0, QLatin1String("root0child0"), palbumChild0Root0);
223     safeCreatePAlbum(palbumRoot0, QLatin1String("root0child1"), palbumChild1Root0);
224     const QString sameName = QLatin1String("sameName Album");
225     safeCreatePAlbum(palbumRoot0, sameName, palbumChild2Root0);
226 
227     safeCreatePAlbum(palbumRoot1, sameName, palbumChild0Root1);
228 
229     qCDebug(DIGIKAM_TESTS_LOG) << "AlbumManager now knows these PAlbums:";
230 
231     foreach (Album* const a, AlbumManager::instance()->allPAlbums())
232     {
233         qCDebug(DIGIKAM_TESTS_LOG) << "\t" << a->title();
234     }
235 
236     // tags
237 
238     rootTag = AlbumManager::instance()->findTAlbum(0);
239     QVERIFY(rootTag);
240 
241     safeCreateTAlbum(rootTag, QLatin1String("root0"), talbumRoot0);
242     safeCreateTAlbum(rootTag, QLatin1String("root1"), talbumRoot1);
243 
244     safeCreateTAlbum(talbumRoot0, QLatin1String("child0 root 0"), talbumChild0Root0);
245     safeCreateTAlbum(talbumRoot0, QLatin1String("child1 root 0"), talbumChild1Root0);
246 
247     safeCreateTAlbum(talbumChild1Root0, sameName, talbumChild0Child1Root0);
248 
249     safeCreateTAlbum(talbumRoot1, sameName, talbumChild0Root1);
250 
251     qCDebug(DIGIKAM_TESTS_LOG) << "created tags";
252 
253     // add some images for having date albums
254 
255     QDir imageDir(IMAGE_PATH);
256     imageDir.setNameFilters(QStringList() << QLatin1String("*.jpg"));
257     QStringList imageFiles = imageDir.entryList();
258 
259     qCDebug(DIGIKAM_TESTS_LOG) << "copying images " << imageFiles << " to "
260              << palbumChild0Root0->fileUrl();
261 
262     foreach (const QString& imageFile, imageFiles)
263     {
264         QString src = IMAGE_PATH + QLatin1Char('/') + imageFile;
265         QString dst = palbumChild0Root0->fileUrl().toLocalFile() + QLatin1Char('/') + imageFile;
266         bool copied = QFile::copy(src, dst);
267         QVERIFY2(copied, "Test images must be copied");
268     }
269 
270     ScanController::instance()->completeCollectionScan();
271 
272     if (AlbumManager::instance()->allDAlbums().count() <= 1)
273     {
274         ensureItemCounts();
275     }
276 
277     qCDebug(DIGIKAM_TESTS_LOG) << "date albums: " << AlbumManager::instance()->allDAlbums();
278 
279     // root + 2 years + 2 and 3 months per year + (1997 as test year for date ordering with 12 months) = 21
280 
281     QCOMPARE(AlbumManager::instance()->allDAlbums().size(), 21);
282 
283     // ensure that there is a root date album
284 
285     DAlbum* const rootFromAlbumManager = AlbumManager::instance()->findDAlbum(0);
286     QVERIFY(rootFromAlbumManager);
287     DAlbum* rootFromList               = nullptr;
288 
289     foreach (Album* const album, AlbumManager::instance()->allDAlbums())
290     {
291         DAlbum* const dAlbum = dynamic_cast<DAlbum*> (album);
292         QVERIFY(dAlbum);
293 
294         if (dAlbum->isRoot())
295         {
296             rootFromList = dAlbum;
297         }
298     }
299 
300     QVERIFY(rootFromList);
301     QVERIFY(rootFromList == rootFromAlbumManager);
302 }
303 
testStartAlbumModel()304 void AlbumModelTest::testStartAlbumModel()
305 {
306     qCDebug(DIGIKAM_TESTS_LOG) << "Start AlbumModelTest::testStartAlbumModel()";
307 
308     // verify that the start album model got all these changes
309 
310     // one root
311 
312     QCOMPARE(startModel->rowCount(), 1);
313 
314     // one collection
315 
316     QModelIndex rootIndex = startModel->index(0, 0);
317     QCOMPARE(startModel->rowCount(rootIndex), 1);
318 
319     // two albums in the collection
320 
321     QModelIndex collectionIndex = startModel->index(0, 0, rootIndex);
322     QCOMPARE(startModel->rowCount(collectionIndex), 3);
323 
324     // this is should be enough for now
325 
326     // We must have received an added notation for everything except album root
327     // and collection
328 
329     QCOMPARE(addedIds.size(), 7);
330 }
331 
ensureItemCounts()332 void AlbumModelTest::ensureItemCounts()
333 {
334     // trigger listing job
335 
336     QEventLoop dAlbumLoop;
337 
338     connect(AlbumManager::instance(), SIGNAL(signalAllDAlbumsLoaded()),
339             &dAlbumLoop, SLOT(quit()));
340 
341     AlbumManager::instance()->prepareItemCounts();
342     qCDebug(DIGIKAM_TESTS_LOG) << "Waiting for AlbumManager to create DAlbums...";
343     dAlbumLoop.exec();
344     qCDebug(DIGIKAM_TESTS_LOG) << "DAlbums were created";
345 
346     while (palbumCountMap.size() < 8)
347     {
348         QEventLoop pAlbumLoop;
349 
350         connect(AlbumManager::instance(), SIGNAL(signalPAlbumsDirty(QMap<int,int>)),
351                 &pAlbumLoop, SLOT(quit()));
352 
353         qCDebug(DIGIKAM_TESTS_LOG) << "Waiting for first PAlbum count map";
354         pAlbumLoop.exec();
355         qCDebug(DIGIKAM_TESTS_LOG) << "Got new PAlbum count map";
356     }
357 }
358 
slotStartModelRowsInserted(const QModelIndex & parent,int start,int end)359 void AlbumModelTest::slotStartModelRowsInserted(const QModelIndex& parent, int start, int end)
360 {
361     qCDebug(DIGIKAM_TESTS_LOG) << "called, parent:" << parent << ", start:" << start << ", end:" << end;
362 
363     for (int row = start ; row <= end ; ++row)
364     {
365         QModelIndex child = startModel->index(row, 0, parent);
366         QVERIFY(child.isValid());
367         Album* album      = startModel->albumForIndex(child);
368         const int id      = child.data(AbstractAlbumModel::AlbumIdRole).toInt();
369         QVERIFY(album);
370         qCDebug(DIGIKAM_TESTS_LOG) << "added album with id"
371                  << id
372                  << "and name" << album->title();
373         addedIds << id;
374     }
375 }
376 
slotStartModelDataChanged(const QModelIndex & topLeft,const QModelIndex & bottomRight)377 void AlbumModelTest::slotStartModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
378 {
379     for (int row = topLeft.row() ; row <= bottomRight.row() ; ++row)
380     {
381         QModelIndex index = startModel->index(row, topLeft.column(), topLeft.parent());
382 
383         if (!index.isValid())
384         {
385             qCDebug(DIGIKAM_TESTS_LOG) << "Illegal index received";
386             continue;
387         }
388 
389         int albumId = index.data(AbstractAlbumModel::AlbumIdRole).toInt();
390 
391         if (!addedIds.contains(albumId))
392         {
393             QString message = QLatin1String("Album id ") + QString::number(albumId) +
394                               QLatin1String(" was changed before adding signal was received");
395             QFAIL(message.toLatin1().constData());
396             qCDebug(DIGIKAM_TESTS_LOG) << message;
397         }
398     }
399 }
400 
deletePAlbum(PAlbum * album)401 void AlbumModelTest::deletePAlbum(PAlbum* album)
402 {
403     QDir dir(album->folderPath());
404     dir.removeRecursively();
405 }
406 
setLastPAlbumCountMap(const QMap<int,int> & map)407 void AlbumModelTest::setLastPAlbumCountMap(const QMap<int, int> &map)
408 {
409     qCDebug(DIGIKAM_TESTS_LOG) << "Receiving new count map "<< map;
410     palbumCountMap = map;
411 }
412 
cleanup()413 void AlbumModelTest::cleanup()
414 {
415     if (startModel)
416     {
417         disconnect(startModel);
418     }
419 
420     delete startModel;
421     addedIds.clear();
422 
423     // remove all test data
424 
425     AlbumManager::instance()->refresh();
426 
427     // remove all palbums' directories
428 
429     deletePAlbum(palbumRoot0);
430     deletePAlbum(palbumRoot1);
431     deletePAlbum(palbumRoot2);
432 
433     // take over changes to database
434 
435     ScanController::instance()->completeCollectionScan();
436 
437     // reread from database
438 
439     AlbumManager::instance()->refresh();
440 
441     // root + one collection
442 
443     QCOMPARE(AlbumManager::instance()->allPAlbums().size(), 2);
444 
445     // remove all tags
446 
447     QString error;
448     bool removed = AlbumManager::instance()->deleteTAlbum(talbumRoot0, error, false);
449     QVERIFY2(removed, QString::fromUtf8("Error removing a tag: %1").arg(error).toLatin1().constData());
450     removed      = AlbumManager::instance()->deleteTAlbum(talbumRoot1, error, false);
451     QVERIFY2(removed, QString::fromUtf8("Error removing a tag: %1").arg(error).toLatin1().constData());
452 
453     QCOMPARE(AlbumManager::instance()->allTAlbums().size(), 1);
454 }
455 
testPAlbumModel()456 void AlbumModelTest::testPAlbumModel()
457 {
458     qCDebug(DIGIKAM_TESTS_LOG) << "Start AlbumModelTest::testPAlbumModel()";
459 
460     AlbumModel* albumModel = new AlbumModel();
461     ModelTest* test        = new ModelTest(albumModel, nullptr);
462     delete test;
463     delete albumModel;
464 
465     albumModel = new AlbumModel(AbstractAlbumModel::IgnoreRootAlbum);
466     test       = new ModelTest(albumModel, nullptr);
467     delete test;
468     delete albumModel;
469 }
470 
testDisablePAlbumCount()471 void AlbumModelTest::testDisablePAlbumCount()
472 {
473     qCDebug(DIGIKAM_TESTS_LOG) << "Start AlbumModelTest::testDisablePAlbumCount()";
474 
475     AlbumModel albumModel;
476     albumModel.setCountMap(palbumCountMap);
477     albumModel.setShowCount(true);
478 
479     QRegExp countRegEx(QLatin1String(".+ \\(\\d+\\)"));
480     countRegEx.setMinimal(true);
481     QVERIFY(countRegEx.exactMatch(QLatin1String("test (10)")));
482     QVERIFY(countRegEx.exactMatch(QLatin1String("te st (10)")));
483     QVERIFY(countRegEx.exactMatch(QLatin1String("te st (0)")));
484     QVERIFY(!countRegEx.exactMatch(QLatin1String("te st ()")));
485     QVERIFY(!countRegEx.exactMatch(QLatin1String("te st")));
486     QVERIFY(!countRegEx.exactMatch(QLatin1String("te st (10) bla")));
487 
488     // ensure that all albums except the root album have a count attached
489 
490     QModelIndex rootIndex = albumModel.index(0, 0, QModelIndex());
491     QString rootTitle     = albumModel.data(rootIndex, Qt::DisplayRole).toString();
492     QVERIFY(!countRegEx.exactMatch(rootTitle));
493 
494     for (int collectionRow = 0; collectionRow < albumModel.rowCount(rootIndex); ++collectionRow)
495     {
496         QModelIndex collectionIndex = albumModel.index(collectionRow, 0, rootIndex);
497         QString collectionTitle = albumModel.data(collectionIndex, Qt::DisplayRole).toString();
498         QVERIFY2(countRegEx.exactMatch(collectionTitle), QString::fromUtf8("%1 matching error").arg(collectionTitle).toLatin1().constData());
499 
500         for (int albumRow = 0; albumRow < albumModel.rowCount(collectionIndex); ++albumRow)
501         {
502             QModelIndex albumIndex = albumModel.index(albumRow, 0, collectionIndex);
503             QString albumTitle     = albumModel.data(albumIndex, Qt::DisplayRole).toString();
504             QVERIFY2(countRegEx.exactMatch(albumTitle), QString::fromUtf8("%1 matching error").arg(albumTitle).toLatin1().constData());
505         }
506 
507     }
508 
509     // now disable showing the count
510 
511     albumModel.setShowCount(false);
512 
513     // ensure that no album has a count attached
514 
515     rootTitle = albumModel.data(rootIndex, Qt::DisplayRole).toString();
516     QVERIFY(!countRegEx.exactMatch(rootTitle));
517 
518     for (int collectionRow = 0; collectionRow < albumModel.rowCount(rootIndex); ++collectionRow)
519     {
520         QModelIndex collectionIndex = albumModel.index(collectionRow, 0, rootIndex);
521         QString collectionTitle     = albumModel.data(collectionIndex, Qt::DisplayRole).toString();
522         QVERIFY2(!countRegEx.exactMatch(collectionTitle), QString::fromUtf8("%1 matching error").arg(collectionTitle).toLatin1().constData());
523 
524         for (int albumRow = 0; albumRow < albumModel.rowCount(collectionIndex); ++albumRow)
525         {
526             QModelIndex albumIndex = albumModel.index(albumRow, 0, collectionIndex);
527             QString albumTitle     = albumModel.data(albumIndex, Qt::DisplayRole).toString();
528             QVERIFY2(!countRegEx.exactMatch(albumTitle), QString::fromUtf8("%1 matching error").arg(albumTitle).toLatin1().constData());
529         }
530     }
531 }
532 
testDAlbumModel()533 void AlbumModelTest::testDAlbumModel()
534 {
535     qCDebug(DIGIKAM_TESTS_LOG) << "Start AlbumModelTest::testDAlbumModel()";
536 
537     DateAlbumModel* const albumModel = new DateAlbumModel();
538     ensureItemCounts();
539     ModelTest* const test            = new ModelTest(albumModel, nullptr);
540     delete test;
541     delete albumModel;
542 }
543 
testDAlbumContainsAlbums()544 void AlbumModelTest::testDAlbumContainsAlbums()
545 {
546     qCDebug(DIGIKAM_TESTS_LOG) << "Start AlbumModelTest::testDAlbumContainsAlbums()";
547 
548     DateAlbumModel* const albumModel = new DateAlbumModel();
549     ensureItemCounts();
550 
551     QVERIFY(albumModel->rootAlbum());
552 
553     foreach (Album* const album, AlbumManager::instance()->allDAlbums())
554     {
555         DAlbum* const dAlbum = dynamic_cast<DAlbum*> (album);
556         QVERIFY(dAlbum);
557 
558         qCDebug(DIGIKAM_TESTS_LOG) << "checking album for date " << dAlbum->date() << ", range = " << dAlbum->range();
559 
560         QModelIndex index = albumModel->indexForAlbum(dAlbum);
561 
562         if (!dAlbum->isRoot())
563         {
564             QVERIFY(index.isValid());
565         }
566 
567         if (dAlbum->isRoot())
568         {
569             // root album
570 
571             QVERIFY(dAlbum->isRoot());
572             QCOMPARE(albumModel->rowCount(index), 3);
573             QCOMPARE(index, albumModel->rootAlbumIndex());
574         }
575         else if (dAlbum->range() == DAlbum::Year && dAlbum->date().year() == 2007)
576         {
577             QCOMPARE(albumModel->rowCount(index), 2);
578         }
579         else if (dAlbum->range() == DAlbum::Year && dAlbum->date().year() == 2009)
580         {
581             QCOMPARE(albumModel->rowCount(index), 3);
582         }
583         else if (dAlbum->range() == DAlbum::Month && dAlbum->date().year() == 2007 && dAlbum->date().month() == 3)
584         {
585             QCOMPARE(albumModel->rowCount(index), 0);
586         }
587         else if (dAlbum->range() == DAlbum::Month && dAlbum->date().year() == 2007 && dAlbum->date().month() == 4)
588         {
589             QCOMPARE(albumModel->rowCount(index), 0);
590         }
591         else if (dAlbum->range() == DAlbum::Month && dAlbum->date().year() == 2009 && dAlbum->date().month() == 3)
592         {
593             QCOMPARE(albumModel->rowCount(index), 0);
594         }
595         else if (dAlbum->range() == DAlbum::Month && dAlbum->date().year() == 2009 && dAlbum->date().month() == 4)
596         {
597             QCOMPARE(albumModel->rowCount(index), 0);
598         }
599         else if (dAlbum->range() == DAlbum::Month && dAlbum->date().year() == 2009 && dAlbum->date().month() == 5)
600         {
601             QCOMPARE(albumModel->rowCount(index), 0);
602         }
603         else if (dAlbum->date().year() == 1997)
604         {
605             // Ignore these albums for order testing
606         }
607         else
608         {
609             qCDebug(DIGIKAM_TESTS_LOG) << "Unexpected album: " << dAlbum->title();
610             QFAIL("Unexpected album returned from model");
611         }
612     }
613 
614     delete albumModel;
615 }
616 
testDAlbumSorting()617 void AlbumModelTest::testDAlbumSorting()
618 {
619     qCDebug(DIGIKAM_TESTS_LOG) << "Start AlbumModelTest::testDAlbumSorting()";
620 
621     DateAlbumModel dateAlbumModel;
622     AlbumFilterModel albumModel;
623     albumModel.setSourceAlbumModel(&dateAlbumModel);
624 
625     // first check ascending order
626 
627     albumModel.sort(0, Qt::AscendingOrder);
628     int previousYear = 0;
629 
630     for (int yearRow = 0; yearRow < albumModel.rowCount(); ++yearRow)
631     {
632         QModelIndex yearIndex   = albumModel.index(yearRow, 0);
633         DAlbum* const yearAlbum = dynamic_cast<DAlbum*> (albumModel.albumForIndex(yearIndex));
634         QVERIFY(yearAlbum);
635 
636         QVERIFY(yearAlbum->date().year() > previousYear);
637         previousYear = yearAlbum->date().year();
638 
639         int previousMonth = 0;
640 
641         for (int monthRow = 0; monthRow < albumModel.rowCount(yearIndex); ++monthRow)
642         {
643             QModelIndex monthIndex   = albumModel.index(monthRow, 0, yearIndex);
644             DAlbum* const monthAlbum = dynamic_cast<DAlbum*> (albumModel.albumForIndex(monthIndex));
645             QVERIFY(monthAlbum);
646 
647             QVERIFY(monthAlbum->date().month() > previousMonth);
648             previousMonth = monthAlbum->date().month();
649         }
650     }
651 
652     // then check descending order
653 
654     albumModel.sort(0, Qt::DescendingOrder);
655     previousYear = 1000000;
656 
657     for (int yearRow = 0; yearRow < albumModel.rowCount(); ++yearRow)
658     {
659         QModelIndex yearIndex   = albumModel.index(yearRow, 0);
660         DAlbum* const yearAlbum = dynamic_cast<DAlbum*> (albumModel.albumForIndex(yearIndex));
661         QVERIFY(yearAlbum);
662 
663         QVERIFY(yearAlbum->date().year() < previousYear);
664         previousYear          = yearAlbum->date().year();
665 
666         int previousMonth     = 13;
667 
668         for (int monthRow = 0; monthRow < albumModel.rowCount(yearIndex); ++monthRow)
669         {
670             QModelIndex monthIndex   = albumModel.index(monthRow, 0, yearIndex);
671             DAlbum* const monthAlbum = dynamic_cast<DAlbum*> (albumModel.albumForIndex(monthIndex));
672             QVERIFY(monthAlbum);
673 
674             QVERIFY(monthAlbum->date().month() < previousMonth);
675             previousMonth          = monthAlbum->date().month();
676         }
677     }
678 }
679 
testDAlbumCount()680 void AlbumModelTest::testDAlbumCount()
681 {
682     qCDebug(DIGIKAM_TESTS_LOG) << "Start AlbumModelTest::testDAlbumCount()";
683 
684     DateAlbumModel* const albumModel = new DateAlbumModel();
685     albumModel->setShowCount(true);
686     ensureItemCounts();
687 
688     qCDebug(DIGIKAM_TESTS_LOG) << "iterating over root indices";
689 
690     // check year albums
691 
692     for (int yearRow = 0; yearRow < albumModel->rowCount(albumModel->rootAlbumIndex()); ++yearRow)
693     {
694         QModelIndex yearIndex    = albumModel->index(yearRow, 0);
695         DAlbum* const yearDAlbum = albumModel->albumForIndex(yearIndex);
696         QVERIFY(yearDAlbum);
697 
698         QVERIFY(yearDAlbum->range() == DAlbum::Year);
699 
700         if (yearDAlbum->date().year() == 2007)
701         {
702             const int imagesInYear = 7;
703             albumModel->includeChildrenCount(yearIndex);
704             QCOMPARE(albumModel->albumCount(yearDAlbum), imagesInYear);
705             albumModel->excludeChildrenCount(yearIndex);
706             QCOMPARE(albumModel->albumCount(yearDAlbum), 0);
707             albumModel->includeChildrenCount(yearIndex);
708             QCOMPARE(albumModel->albumCount(yearDAlbum), imagesInYear);
709 
710             for (int monthRow = 0; monthRow < albumModel->rowCount(yearIndex); ++monthRow)
711             {
712                 QModelIndex monthIndex = albumModel->index(monthRow, 0, yearIndex);
713                 DAlbum* monthDAlbum    = albumModel->albumForIndex(monthIndex);
714                 QVERIFY(monthDAlbum);
715 
716                 QVERIFY(monthDAlbum->range() == DAlbum::Month);
717                 QVERIFY(monthDAlbum->date().year() == 2007);
718 
719                 if (monthDAlbum->date().month() == 3)
720                 {
721                     const int imagesInMonth = 3;
722                     albumModel->includeChildrenCount(monthIndex);
723                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
724                     albumModel->excludeChildrenCount(monthIndex);
725                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
726                     albumModel->includeChildrenCount(monthIndex);
727                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
728                 }
729                 else if (monthDAlbum->date().month() == 4)
730                 {
731                     const int imagesInMonth = 4;
732                     albumModel->includeChildrenCount(monthIndex);
733                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
734                     albumModel->excludeChildrenCount(monthIndex);
735                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
736                     albumModel->includeChildrenCount(monthIndex);
737                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
738                 }
739                 else
740                 {
741                     QFAIL("unexpected month album in 2007");
742                 }
743             }
744         }
745         else if (yearDAlbum->date().year() == 2009)
746         {
747             const int imagesInYear = 5;
748             albumModel->includeChildrenCount(yearIndex);
749             QCOMPARE(albumModel->albumCount(yearDAlbum), imagesInYear);
750             albumModel->excludeChildrenCount(yearIndex);
751             QCOMPARE(albumModel->albumCount(yearDAlbum), 0);
752             albumModel->includeChildrenCount(yearIndex);
753             QCOMPARE(albumModel->albumCount(yearDAlbum), imagesInYear);
754 
755             for (int monthRow = 0; monthRow < albumModel->rowCount(yearIndex); ++monthRow)
756             {
757                 QModelIndex monthIndex = albumModel->index(monthRow, 0, yearIndex);
758                 DAlbum* monthDAlbum    = albumModel->albumForIndex(monthIndex);
759                 QVERIFY(monthDAlbum);
760 
761                 QVERIFY(monthDAlbum->range() == DAlbum::Month);
762                 QVERIFY(monthDAlbum->date().year() == 2009);
763 
764                 if (monthDAlbum->date().month() == 3)
765                 {
766                     const int imagesInMonth = 2;
767                     albumModel->includeChildrenCount(monthIndex);
768                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
769                     albumModel->excludeChildrenCount(monthIndex);
770                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
771                     albumModel->includeChildrenCount(monthIndex);
772                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
773                 }
774                 else if (monthDAlbum->date().month() == 4)
775                 {
776                     const int imagesInMonth = 2;
777                     albumModel->includeChildrenCount(monthIndex);
778                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
779                     albumModel->excludeChildrenCount(monthIndex);
780                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
781                     albumModel->includeChildrenCount(monthIndex);
782                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
783                 }
784                 else if (monthDAlbum->date().month() == 5)
785                 {
786                     const int imagesInMonth = 1;
787                     albumModel->includeChildrenCount(monthIndex);
788                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
789                     albumModel->excludeChildrenCount(monthIndex);
790                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
791                     albumModel->includeChildrenCount(monthIndex);
792                     QCOMPARE(albumModel->albumCount(monthDAlbum), imagesInMonth);
793                 }
794                 else
795                 {
796                     QFAIL("unexpected month album in 2009");
797                 }
798             }
799         }
800         else if (yearDAlbum->date().year() == 1997)
801         {
802             // Nothing to do here, ignore the albums for ordering tests
803         }
804         else
805         {
806             QFAIL("Received unexpected album from model");
807         }
808     }
809 
810     delete albumModel;
811 }
812 
testTAlbumModel()813 void AlbumModelTest::testTAlbumModel()
814 {
815     qCDebug(DIGIKAM_TESTS_LOG) << "Start AlbumModelTest::testTAlbumModel()";
816 
817     TagModel* albumModel = new TagModel();
818     ModelTest* test      = new ModelTest(albumModel, nullptr);
819     delete test;
820     delete albumModel;
821 
822     albumModel = new TagModel(AbstractAlbumModel::IgnoreRootAlbum);
823     test       = new ModelTest(albumModel, nullptr);
824     delete test;
825     delete albumModel;
826 }
827 
testSAlbumModel()828 void AlbumModelTest::testSAlbumModel()
829 {
830     qCDebug(DIGIKAM_TESTS_LOG) << "Start AlbumModelTest::testSAlbumModel()";
831 
832     SearchModel* const albumModel = new SearchModel();
833     ModelTest* const test         = new ModelTest(albumModel, nullptr);
834     delete test;
835     delete albumModel;
836 }
837