File indexing completed on 2024-11-10 05:02:43

0001 /*
0002     SPDX-FileCopyrightText: 2022 Fushan Wen <qydwhotmail@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include <QDebug>
0008 #include <QSignalSpy>
0009 #include <QStandardPaths>
0010 #include <QTest>
0011 
0012 #include <KIO/CopyJob>
0013 
0014 #include "../model/imagelistmodel.h"
0015 #include "../model/imageproxymodel.h"
0016 #include "../model/packagelistmodel.h"
0017 #include "commontestdata.h"
0018 
0019 class ImageProxyModelTest : public QObject
0020 {
0021     Q_OBJECT
0022 
0023 private Q_SLOTS:
0024     void initTestCase();
0025     void init();
0026     void cleanup();
0027     void cleanupTestCase();
0028 
0029     void testImageProxyModelIndexOf();
0030     void testImageProxyModelReload();
0031     void testImageProxyModelAddBackground();
0032     void testImageProxyModelRemoveBackground();
0033     void testImageProxyModelDirWatch();
0034 
0035 private:
0036     QPointer<ImageProxyModel> m_model = nullptr;
0037     QPointer<QSignalSpy> m_countSpy = nullptr;
0038     QPointer<QSignalSpy> m_dataSpy = nullptr;
0039 
0040     QDir m_dataDir;
0041     QDir m_alternateDir;
0042     QStringList m_wallpaperPaths;
0043     QString m_dummyWallpaperPath;
0044     QStringList m_packagePaths;
0045     QString m_dummyPackagePath;
0046     int m_modelNum = 0;
0047     QProperty<QSize> m_targetSize;
0048     QProperty<bool> m_usedInConfig{false};
0049 };
0050 
0051 void ImageProxyModelTest::initTestCase()
0052 {
0053     m_dataDir = QDir(QFINDTESTDATA("testdata/default"));
0054     m_alternateDir = QDir(QFINDTESTDATA("testdata/alternate"));
0055     QVERIFY(!m_dataDir.isEmpty());
0056     QVERIFY(!m_alternateDir.isEmpty());
0057     renameBizarreFile(m_dataDir);
0058 
0059     m_wallpaperPaths << m_dataDir.absoluteFilePath(ImageBackendTestData::defaultImageFileName1);
0060     m_wallpaperPaths << m_dataDir.absoluteFilePath(ImageBackendTestData::defaultImageFileName2);
0061     m_wallpaperPaths << m_dataDir.absoluteFilePath(ImageBackendTestData::defaultImageFileName3);
0062     m_wallpaperPaths << m_dataDir.absoluteFilePath(ImageBackendTestData::defaultImageFileName4);
0063     m_wallpaperPaths << m_dataDir.absoluteFilePath(ImageBackendTestData::defaultImageFileName5);
0064     m_dummyWallpaperPath = m_alternateDir.absoluteFilePath(ImageBackendTestData::alternateImageFileName1);
0065 
0066     m_packagePaths << m_dataDir.absoluteFilePath(ImageBackendTestData::defaultPackageFolderName1);
0067     m_packagePaths << m_dataDir.absoluteFilePath(ImageBackendTestData::defaultPackageFolderName2);
0068     m_dummyPackagePath = m_alternateDir.absoluteFilePath(ImageBackendTestData::alternatePackageFolderName1);
0069 
0070     m_modelNum = 2;
0071     m_targetSize = QSize(1920, 1080);
0072 
0073     QStandardPaths::setTestModeEnabled(true);
0074 }
0075 
0076 void ImageProxyModelTest::init()
0077 {
0078     m_model = new ImageProxyModel({m_dataDir.absolutePath()}, QBindable<QSize>(&m_targetSize), QBindable<bool>(&m_usedInConfig), this);
0079     m_countSpy = new QSignalSpy(m_model, &ImageProxyModel::countChanged);
0080     m_dataSpy = new QSignalSpy(m_model, &ImageProxyModel::dataChanged);
0081 
0082     QVERIFY(m_model->loading().value());
0083 
0084     // Test loading data
0085     for (int i = 0; i < m_modelNum; i++) {
0086         m_countSpy->wait(5 * 1000);
0087 
0088         if (m_countSpy->size() == m_modelNum) {
0089             break;
0090         }
0091     }
0092     QCOMPARE(m_countSpy->size(), m_modelNum);
0093     m_countSpy->clear();
0094     QCOMPARE(m_model->sourceModels().size(), m_modelNum);
0095 
0096     QVERIFY(!m_model->loading().value());
0097 
0098     QCOMPARE(m_model->rowCount(), ImageBackendTestData::defaultTotalCount);
0099     QCOMPARE(m_model->count(), m_model->rowCount());
0100 
0101     QCOMPARE(m_model->m_imageModel->count(), ImageBackendTestData::defaultImageCount);
0102     QCOMPARE(m_model->m_packageModel->count(), ImageBackendTestData::defaultPackageCount);
0103 }
0104 
0105 void ImageProxyModelTest::cleanup()
0106 {
0107     m_model->deleteLater();
0108     m_countSpy->deleteLater();
0109     m_dataSpy->deleteLater();
0110 }
0111 
0112 void ImageProxyModelTest::cleanupTestCase()
0113 {
0114     const QString standardPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/wallpapers/");
0115 
0116     QDir(standardPath).removeRecursively();
0117 
0118     restoreBizarreFile(m_dataDir);
0119 }
0120 
0121 void ImageProxyModelTest::testImageProxyModelIndexOf()
0122 {
0123     QVERIFY(m_model->indexOf(m_wallpaperPaths.at(0)) >= 0);
0124     QVERIFY(m_model->indexOf(m_wallpaperPaths.at(1)) >= 0);
0125     QVERIFY(m_model->indexOf(m_wallpaperPaths.at(2)) >= 0);
0126     QVERIFY(m_model->indexOf(m_wallpaperPaths.at(3)) >= 0);
0127     QVERIFY(m_model->indexOf(m_wallpaperPaths.at(4)) >= 0);
0128     QVERIFY(m_model->indexOf(m_packagePaths.at(0)) >= 0);
0129     QVERIFY(m_model->indexOf(m_packagePaths.at(1)) >= 0);
0130     QVERIFY(m_model->indexOf(m_packagePaths.at(0) + QDir::separator()) >= 0);
0131     QVERIFY(m_model->indexOf(m_packagePaths.at(1) + QDir::separator()) >= 0);
0132     QCOMPARE(m_model->indexOf(m_dataDir.absoluteFilePath(QStringLiteral("brokenpackage") + QDir::separator())), -1);
0133 }
0134 
0135 void ImageProxyModelTest::testImageProxyModelReload()
0136 {
0137     m_model->reload();
0138 
0139     for (int i = 0; i < m_modelNum; i++) {
0140         m_countSpy->wait(5 * 1000);
0141     }
0142     QCOMPARE(m_countSpy->size(), m_modelNum);
0143     m_countSpy->clear();
0144 
0145     QCOMPARE(m_model->rowCount(), ImageBackendTestData::defaultTotalCount);
0146     QCOMPARE(m_model->m_imageModel->rowCount(), ImageBackendTestData::defaultImageCount);
0147     QCOMPARE(m_model->m_packageModel->rowCount(), ImageBackendTestData::defaultPackageCount);
0148 }
0149 
0150 void ImageProxyModelTest::testImageProxyModelAddBackground()
0151 {
0152     int count = m_model->count();
0153 
0154     // Case 1: add an existing wallpaper
0155     auto results = m_model->addBackground(m_wallpaperPaths.at(0));
0156     QCOMPARE(m_countSpy->size(), 0);
0157     QCOMPARE(results.size(), 0);
0158 
0159     // Case 2: add an existing package
0160     results = m_model->addBackground(m_packagePaths.at(0));
0161     QCOMPARE(results.size(), 0);
0162     results = m_model->addBackground(m_packagePaths.at(1));
0163     QCOMPARE(results.size(), 0);
0164     QCOMPARE(m_countSpy->size(), 0);
0165 
0166     // Case 3: add a new wallpaper
0167     results = m_model->addBackground(QUrl::fromLocalFile(m_dummyWallpaperPath).toString());
0168     QCOMPARE(m_countSpy->size(), 1);
0169     m_countSpy->clear();
0170     QCOMPARE(results.size(), 1);
0171     QCOMPARE(m_model->count(), ++count);
0172     QCOMPARE(m_model->m_imageModel->count(), ImageBackendTestData::defaultImageCount + 1);
0173     QCOMPARE(m_model->m_packageModel->count(), ImageBackendTestData::defaultPackageCount);
0174 
0175     // Case 4: add a new package
0176     results = m_model->addBackground(m_dummyPackagePath);
0177     QCOMPARE(m_countSpy->size(), 1);
0178     m_countSpy->clear();
0179     QCOMPARE(results.size(), 1);
0180     QCOMPARE(m_model->count(), ++count);
0181     QCOMPARE(m_model->m_imageModel->count(), ImageBackendTestData::defaultImageCount + 1);
0182     QCOMPARE(m_model->m_packageModel->count(), ImageBackendTestData::defaultPackageCount + 1);
0183 
0184     // Test KDirWatch
0185     QVERIFY(m_model->m_dirWatch.contains(m_dummyWallpaperPath));
0186     QVERIFY(m_model->m_dirWatch.contains(m_dummyPackagePath));
0187 
0188     QCOMPARE(m_model->m_pendingAddition.size(), 2);
0189 }
0190 
0191 void ImageProxyModelTest::testImageProxyModelRemoveBackground()
0192 {
0193     auto results = m_model->addBackground(m_dummyWallpaperPath);
0194     QCOMPARE(results.size(), 1);
0195 
0196     results = m_model->addBackground(m_dummyPackagePath);
0197     QCOMPARE(results.size(), 1);
0198     QCOMPARE(m_model->m_pendingAddition.size(), 2);
0199     m_countSpy->clear();
0200 
0201     int count = m_model->count();
0202 
0203     // Case 1: remove an existing wallpaper
0204     m_model->removeBackground(QUrl::fromLocalFile(m_dummyWallpaperPath).toString());
0205     QCOMPARE(m_countSpy->size(), 1);
0206     m_countSpy->clear();
0207     QCOMPARE(m_model->m_imageModel->count(), ImageBackendTestData::defaultImageCount);
0208     QCOMPARE(m_model->m_packageModel->count(), ImageBackendTestData::defaultPackageCount + 1);
0209     QCOMPARE(m_model->count(), --count);
0210     QVERIFY(!m_model->m_dirWatch.contains(m_dummyWallpaperPath));
0211 
0212     m_model->removeBackground(m_dummyPackagePath);
0213     QCOMPARE(m_countSpy->size(), 1);
0214     m_countSpy->clear();
0215     QCOMPARE(m_model->m_imageModel->count(), ImageBackendTestData::defaultImageCount);
0216     QCOMPARE(m_model->m_packageModel->count(), ImageBackendTestData::defaultPackageCount);
0217     QCOMPARE(m_model->count(), --count);
0218     QVERIFY(!m_model->m_dirWatch.contains(m_dummyPackagePath));
0219 
0220     QCOMPARE(m_model->m_pendingAddition.size(), 0);
0221 
0222     // Case 2: remove an unexisting wallpaper
0223     m_model->removeBackground(m_dummyWallpaperPath);
0224     QCOMPARE(m_countSpy->size(), 0);
0225     QCOMPARE(m_model->count(), count);
0226 }
0227 
0228 void ImageProxyModelTest::testImageProxyModelDirWatch()
0229 {
0230     QVERIFY(m_model->m_dirWatch.contains(m_dataDir.absolutePath()));
0231     // Duplicate watched items as their parent folder is already in KDirWatch
0232     for (const QString &path : std::as_const(m_wallpaperPaths)) {
0233         QVERIFY2(!m_model->m_dirWatch.contains(path), path.toLatin1());
0234     }
0235     for (const QString &path : std::as_const(m_packagePaths)) {
0236         QFileInfo info(path);
0237         while (info.absoluteFilePath() != m_dataDir.absolutePath()) {
0238             // Because of KDirWatch::WatchSubDirs, some folders will still be added to KDirWatch
0239             QVERIFY2(m_model->m_dirWatch.contains(info.absoluteFilePath()), info.absoluteFilePath().toLatin1());
0240             info = QFileInfo(info.absolutePath()); // Parent folder
0241         }
0242     }
0243 
0244     m_model->deleteLater();
0245     m_countSpy->deleteLater();
0246     m_dataSpy->deleteLater();
0247 
0248     // Move to local wallpaper folder
0249     const QString standardPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/wallpapers/");
0250     QVERIFY(QDir(standardPath).mkpath(standardPath));
0251 
0252     m_model = new ImageProxyModel({standardPath}, QBindable<QSize>(&m_targetSize), QBindable<bool>(&m_usedInConfig), this);
0253     m_countSpy = new QSignalSpy(m_model, &ImageProxyModel::countChanged);
0254     m_dataSpy = new QSignalSpy(m_model, &ImageProxyModel::dataChanged);
0255 
0256     QVERIFY(!m_countSpy->wait(1000));
0257     QCOMPARE(m_countSpy->size(), 0);
0258     QCOMPARE(m_model->sourceModels().size(), m_modelNum);
0259     QCOMPARE(m_model->rowCount(), 0);
0260     QVERIFY(m_model->m_dirWatch.contains(standardPath));
0261 
0262     // Copy an image to the folder
0263     QFile imageFile(m_wallpaperPaths.at(0));
0264     QVERIFY(imageFile.copy(standardPath + QStringLiteral("image.jpg")));
0265     m_countSpy->wait();
0266     QCOMPARE(m_countSpy->size(), 1);
0267     m_countSpy->clear();
0268 
0269     QCOMPARE(m_model->count(), 1);
0270     QCOMPARE(m_model->m_imageModel->count(), 1);
0271     QCOMPARE(m_model->m_packageModel->count(), 0);
0272     QVERIFY(m_model->m_dirWatch.contains(standardPath));
0273     // KDirWatch already monitors the parent folder
0274     QVERIFY(!m_model->m_dirWatch.contains(standardPath + QStringLiteral("image.jpg")));
0275 
0276     // Copy a package to the folder
0277     auto job = KIO::copy(QUrl::fromLocalFile(m_dummyPackagePath),
0278                          QUrl::fromLocalFile(standardPath + QStringLiteral("dummy") + QDir::separator()),
0279                          KIO::HideProgressInfo | KIO::Overwrite);
0280     job->start();
0281 
0282     if (m_countSpy->empty()) {
0283         QVERIFY(m_countSpy->wait());
0284     }
0285     QCOMPARE(m_countSpy->size(), 1);
0286     m_countSpy->clear();
0287 
0288     QCOMPARE(m_model->count(), 2);
0289     QCOMPARE(m_model->m_imageModel->count(), 1);
0290     QCOMPARE(m_model->m_packageModel->count(), 1);
0291     QVERIFY(m_model->m_dirWatch.contains(standardPath));
0292     // WatchSubDirs
0293     QVERIFY(m_model->m_dirWatch.contains(standardPath + QStringLiteral("dummy")));
0294 
0295     // Test delete a file
0296     QFile newImageFile(standardPath + QStringLiteral("image.jpg"));
0297     QVERIFY(newImageFile.remove());
0298     m_countSpy->wait();
0299     QCOMPARE(m_countSpy->size(), 1);
0300     m_countSpy->clear();
0301 
0302     QCOMPARE(m_model->count(), 1);
0303     QCOMPARE(m_model->m_imageModel->count(), 0);
0304     QCOMPARE(m_model->m_packageModel->count(), 1);
0305     // Don't remove the file if its parent folder is in KDirWatch, otherwise KDirWatchPrivate::removeEntry will also remove the parent folder
0306     QVERIFY(m_model->m_dirWatch.contains(standardPath));
0307     QVERIFY(!m_model->m_dirWatch.contains(standardPath + QStringLiteral("image.jpg")));
0308 
0309     // Test delete a folder
0310     QVERIFY(QDir(standardPath + QStringLiteral("dummy")).removeRecursively());
0311     m_countSpy->wait();
0312     QCOMPARE(m_countSpy->size(), 1);
0313     m_countSpy->clear();
0314 
0315     QCOMPARE(m_model->count(), 0);
0316     QCOMPARE(m_model->m_imageModel->count(), 0);
0317     QCOMPARE(m_model->m_packageModel->count(), 0);
0318     QVERIFY(m_model->m_dirWatch.contains(standardPath));
0319     QVERIFY(!m_model->m_dirWatch.contains(standardPath + QStringLiteral("dummy")));
0320 }
0321 
0322 QTEST_MAIN(ImageProxyModelTest)
0323 
0324 #include "test_imageproxymodel.moc"