File indexing completed on 2024-06-16 05:11:11

0001 /*
0002     SPDX-FileCopyrightText: 2022 Fushan Wen <qydwhotmail@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include <QSignalSpy>
0008 #include <QStandardPaths>
0009 #include <QTest>
0010 
0011 #include "../slidefiltermodel.h"
0012 #include "../slidemodel.h"
0013 #include "commontestdata.h"
0014 
0015 #include <array>
0016 
0017 class SlideFilterModelTest : public QObject
0018 {
0019     Q_OBJECT
0020 
0021 private Q_SLOTS:
0022     void initTestCase();
0023     void init();
0024     void cleanup();
0025     void cleanupTestCase();
0026 
0027     void testSlideFilterModelSortingOrder_data();
0028     void testSlideFilterModelSortingOrder();
0029     void testSlideFilterModelSortingRandomOrder();
0030     /**
0031      * When a wallpaper file is added/removed, the random order list (m_randomOrder) should be
0032      * able to provide a correct updated list.
0033      * @see https://bugs.kde.org/show_bug.cgi?id=473088
0034      */
0035     void testSlideFilterModelSortingRandomOrderWithFileAddedRemoved_data();
0036     void testSlideFilterModelSortingRandomOrderWithFileAddedRemoved();
0037     void testSlideFilterModelUncheckedSlides();
0038 
0039 private:
0040     QPointer<SlideModel> m_model = nullptr;
0041     QPointer<SlideFilterModel> m_filterModel = nullptr;
0042 
0043     QDir m_dataDir;
0044     QString m_wallpaperPath;
0045     QString m_standardPath;
0046     QString m_pathA, m_pathB, m_pathC;
0047     QProperty<QSize> m_targetSize;
0048     QProperty<bool> m_usedInConfig{false};
0049     QProperty<SortingMode::Mode> m_sortingMode{SortingMode::Random};
0050     QProperty<bool> m_sortingFoldersFirst{false};
0051 };
0052 
0053 void SlideFilterModelTest::initTestCase()
0054 {
0055     m_dataDir = QDir(QFINDTESTDATA("testdata/default"));
0056     QVERIFY(!m_dataDir.isEmpty());
0057 
0058     m_wallpaperPath = m_dataDir.absoluteFilePath(ImageBackendTestData::defaultImageFileName1);
0059 
0060     m_targetSize = QSize(1920, 1080);
0061 
0062     QStandardPaths::setTestModeEnabled(true);
0063 
0064     m_standardPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/wallpapers/");
0065     QDir imageDir(m_standardPath);
0066 
0067     QVERIFY(imageDir.mkpath(m_standardPath + QStringLiteral("a/")));
0068     QVERIFY(imageDir.mkpath(m_standardPath + QStringLiteral("d/")));
0069 
0070     QFile imageFile(m_wallpaperPath);
0071 
0072     m_pathB = imageDir.absoluteFilePath(QStringLiteral("d/b.jpg"));
0073     QVERIFY(imageFile.copy(m_pathB));
0074 
0075     // Explicitly wait 1s
0076     QThread::sleep(1);
0077 
0078     m_pathA = imageDir.absoluteFilePath(QStringLiteral("d/a.jpg"));
0079     QVERIFY(imageFile.copy(m_pathA));
0080 
0081     QThread::sleep(1);
0082 
0083     m_pathC = imageDir.absoluteFilePath(QStringLiteral("a/c.jpg"));
0084     QVERIFY(imageFile.copy(m_pathC));
0085 }
0086 
0087 void SlideFilterModelTest::init()
0088 {
0089     m_model = new SlideModel(QBindable<QSize>(&m_targetSize), QBindable<bool>(&m_usedInConfig), this);
0090     m_filterModel = new SlideFilterModel(QBindable<bool>(&m_usedInConfig), //
0091                                          QBindable<SortingMode::Mode>(&m_sortingMode), //
0092                                          QBindable<bool>(&m_sortingFoldersFirst), //
0093                                          this);
0094 
0095     // Test loading data
0096     m_model->setSlidePaths({m_standardPath});
0097     QSignalSpy doneSpy(m_model, &SlideModel::done);
0098 
0099     QVERIFY(doneSpy.wait(10 * 1000));
0100     QCOMPARE(doneSpy.size(), 1);
0101     m_filterModel->setSourceModel(m_model);
0102 }
0103 
0104 void SlideFilterModelTest::cleanup()
0105 {
0106     m_model->deleteLater();
0107     m_filterModel->deleteLater();
0108 }
0109 
0110 void SlideFilterModelTest::cleanupTestCase()
0111 {
0112     QDir(m_standardPath).removeRecursively();
0113 }
0114 
0115 void SlideFilterModelTest::testSlideFilterModelSortingOrder_data()
0116 {
0117     QTest::addColumn<SortingMode::Mode>("order");
0118     QTest::addColumn<bool>("folderFirst");
0119     QTest::addColumn<QStringList>("expected");
0120 
0121     QTest::newRow("Alphabetical 0") << SortingMode::Alphabetical << false << QStringList{m_pathA, m_pathB, m_pathC};
0122     QTest::newRow("Alphabetical 1") << SortingMode::Alphabetical << true << QStringList{m_pathC, m_pathA, m_pathB};
0123 
0124     QTest::newRow("AlphabeticalReversed 0") << SortingMode::AlphabeticalReversed << false << QStringList{m_pathC, m_pathB, m_pathA};
0125     QTest::newRow("AlphabeticalReversed 1") << SortingMode::AlphabeticalReversed << true << QStringList{m_pathB, m_pathA, m_pathC};
0126 
0127     // Oldest first
0128     QTest::newRow("Modified 0") << SortingMode::Modified << false << QStringList{m_pathB, m_pathA, m_pathC};
0129     QTest::newRow("Modified 1") << SortingMode::Modified << true << QStringList{m_pathB, m_pathA, m_pathC};
0130 
0131     // Newest first
0132     QTest::newRow("ModifiedReversed 0") << SortingMode::ModifiedReversed << false << QStringList{m_pathC, m_pathA, m_pathB};
0133     QTest::newRow("ModifiedReversed 1") << SortingMode::ModifiedReversed << true << QStringList{m_pathC, m_pathA, m_pathB};
0134 }
0135 
0136 void SlideFilterModelTest::testSlideFilterModelSortingOrder()
0137 {
0138     QFETCH(SortingMode::Mode, order);
0139     QFETCH(bool, folderFirst);
0140     QFETCH(QStringList, expected);
0141 
0142     m_sortingMode = order;
0143     m_sortingFoldersFirst = folderFirst;
0144     QCOMPARE(m_filterModel->rowCount(), 3);
0145 
0146     for (int i = 0; i < expected.size(); i++) {
0147         QCOMPARE(m_filterModel->index(i, 0).data(ImageRoles::PackageNameRole).toString(), expected.at(i));
0148     }
0149 }
0150 
0151 void SlideFilterModelTest::testSlideFilterModelSortingRandomOrder()
0152 {
0153     std::array<int, 3> counts{0, 0, 0};
0154     QCOMPARE(m_filterModel->rowCount(), counts.size());
0155 
0156     // Monte Carlo
0157     m_sortingMode = SortingMode::Random;
0158     m_sortingFoldersFirst = false;
0159     for (int i = 0; i < 1000; i++) {
0160         m_filterModel->invalidate();
0161         const QString firstElement = m_filterModel->index(0, 0).data(ImageRoles::PackageNameRole).toString();
0162 
0163         if (firstElement == m_pathA) {
0164             counts[0]++;
0165         } else if (firstElement == m_pathB) {
0166             counts[1]++;
0167         } else if (firstElement == m_pathC) {
0168             counts[2]++;
0169         }
0170     }
0171 
0172     qDebug() << counts[0] << counts[1] << counts[2];
0173     for (int c : std::as_const(counts)) {
0174         QVERIFY(std::clamp(c, 200, 400) == c);
0175     }
0176 }
0177 
0178 void SlideFilterModelTest::testSlideFilterModelSortingRandomOrderWithFileAddedRemoved_data()
0179 {
0180     QTest::addColumn<bool>("usedInConfig");
0181 
0182     QTest::newRow("usedInConfig: false") << false;
0183     QTest::newRow("usedInConfig: true") << true;
0184 }
0185 
0186 void SlideFilterModelTest::testSlideFilterModelSortingRandomOrderWithFileAddedRemoved()
0187 {
0188     QFETCH(bool, usedInConfig);
0189     m_usedInConfig = usedInConfig;
0190 
0191     m_sortingMode = SortingMode::Random;
0192     m_sortingFoldersFirst = false;
0193     int oldRowCount = m_filterModel->rowCount();
0194 
0195     qDebug() << "Before adding a new wallpaper";
0196     QStringList oldPaths;
0197     for (int i = 0, count = m_filterModel->rowCount(); i < count; ++i) {
0198         qDebug() << i << oldPaths.emplace_back(m_filterModel->index(i, 0).data(ImageRoles::PackageNameRole).toString());
0199     }
0200     qDebug() << "Before adding a new wallpaper";
0201 
0202     QSignalSpy rowsInsertedSpy(m_filterModel, &QAbstractItemModel::rowsInserted);
0203     QDir imageDir(m_standardPath);
0204     const QString newImagePath = imageDir.absoluteFilePath(QStringLiteral("THIS_IS_THE_LAST_WALLPAPER_BUG473088.jpg"));
0205     QVERIFY(QFile(m_wallpaperPath).copy(newImagePath));
0206 
0207     if (m_filterModel->rowCount() == oldRowCount) {
0208         QVERIFY(rowsInsertedSpy.wait());
0209     } else {
0210         QVERIFY(!rowsInsertedSpy.empty()); // Otherwise the random order is not updated
0211     }
0212     QCOMPARE(m_filterModel->rowCount(), oldRowCount + 1);
0213 
0214     qDebug() << "After adding a new wallpaper";
0215     for (int i = 0, count = oldPaths.size(); i < count; ++i) {
0216         // Make sure the old order is not changed
0217         qDebug() << i << m_filterModel->index(i, 0).data(ImageRoles::PackageNameRole).toString();
0218         QCOMPARE(oldPaths[i], m_filterModel->index(i + (usedInConfig ? 1 : 0), 0).data(ImageRoles::PackageNameRole).toString());
0219     }
0220     qDebug() << "After adding a new wallpaper";
0221 
0222     if (usedInConfig) {
0223         QCOMPARE(m_filterModel->index(0, 0).data(ImageRoles::PackageNameRole).toString(), newImagePath);
0224     } else {
0225         QCOMPARE(m_filterModel->index(m_filterModel->rowCount() - 1, 0).data(ImageRoles::PackageNameRole).toString(), newImagePath);
0226     }
0227 
0228     // Now remove the wallpaper
0229     oldRowCount = m_filterModel->rowCount();
0230     QSignalSpy rowsRemovedSpy(m_filterModel, &QAbstractItemModel::rowsRemoved);
0231     QVERIFY(QFile::remove(newImagePath));
0232     if (m_filterModel->rowCount() == oldRowCount) {
0233         QVERIFY(rowsRemovedSpy.wait());
0234     } else {
0235         QVERIFY(!rowsRemovedSpy.empty()); // Otherwise the random order is not updated
0236     }
0237     QCOMPARE(m_filterModel->rowCount(), oldRowCount - 1);
0238     qDebug() << "After deleting a wallpaper";
0239     for (int i = 0, count = oldPaths.size(); i < count; ++i) {
0240         // Make sure the old order is not changed
0241         qDebug() << i << m_filterModel->index(i, 0).data(ImageRoles::PackageNameRole).toString();
0242         QCOMPARE(oldPaths[i], m_filterModel->index(i, 0).data(ImageRoles::PackageNameRole).toString());
0243     }
0244     qDebug() << "After deleting a wallpaper";
0245 }
0246 
0247 void SlideFilterModelTest::testSlideFilterModelUncheckedSlides()
0248 {
0249     m_model->setUncheckedSlides({m_pathA});
0250 
0251     m_usedInConfig = true;
0252     QCOMPARE(m_filterModel->rowCount(), 3);
0253 
0254     m_usedInConfig = false;
0255     QCOMPARE(m_filterModel->rowCount(), 2);
0256 }
0257 
0258 QTEST_MAIN(SlideFilterModelTest)
0259 
0260 #include "test_slidefiltermodel.moc"