File indexing completed on 2024-04-28 03:51:40

0001 /*
0002     SPDX-FileCopyrightText: 2014 Vishesh Handa <me@vhanda.in>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-or-later
0005 */
0006 
0007 #include "filewatch.h"
0008 #include "fileindexerconfigutils.h"
0009 #include "database.h"
0010 #include "fileindexerconfig.h"
0011 #include "pendingfilequeue.h"
0012 
0013 #include <QTest>
0014 #include <QSignalSpy>
0015 #include <QTemporaryDir>
0016 #include <KFileMetaData/UserMetaData>
0017 
0018 namespace Baloo {
0019 
0020 class FileWatchTest : public QObject
0021 {
0022     Q_OBJECT
0023 private Q_SLOTS:
0024 
0025     void testFileCreation();
0026     void testConfigChange();
0027 
0028     void init()
0029     {
0030         m_tmpDir = std::make_unique<QTemporaryDir>();
0031         QVERIFY(m_tmpDir->isValid());
0032 
0033         m_dbDir = std::make_unique<QTemporaryDir>();
0034         QVERIFY(m_dbDir->isValid());
0035 
0036         m_db = std::make_unique<Baloo::Database>(m_dbDir->path());
0037     }
0038 
0039 private:
0040     std::unique_ptr<QTemporaryDir> m_dbDir;
0041     std::unique_ptr<QTemporaryDir> m_tmpDir;
0042     std::unique_ptr<Baloo::Database> m_db;
0043 };
0044 
0045 } // namespace Baloo
0046 
0047 using namespace Baloo;
0048 
0049 namespace {
0050     bool createFile(const QString& fileUrl) {
0051         QFile f1(fileUrl);
0052         f1.open(QIODevice::WriteOnly);
0053         f1.close();
0054         return QFile::exists(fileUrl);
0055     }
0056 
0057     void modifyFile(const QString& fileUrl) {
0058         QFile f1(fileUrl);
0059         f1.open(QIODevice::Append | QIODevice::Text);
0060 
0061         QTextStream stream(&f1);
0062         stream << "1";
0063     }
0064 }
0065 
0066 void FileWatchTest::testFileCreation()
0067 {
0068     m_db->open(Baloo::Database::CreateDatabase);
0069     QVERIFY(m_db->isOpen());
0070 
0071     Test::writeIndexerConfig({m_tmpDir->path()}, {});
0072     FileIndexerConfig config;
0073 
0074     FileWatch fileWatch(m_db.get(), &config);
0075     fileWatch.m_pendingFileQueue->setMaximumTimeout(0);
0076     fileWatch.m_pendingFileQueue->setMinimumTimeout(0);
0077     fileWatch.m_pendingFileQueue->setTrackingTime(0);
0078 
0079     QSignalSpy spy(&fileWatch, &FileWatch::installedWatches);
0080     QVERIFY(spy.isValid());
0081 
0082     fileWatch.updateIndexedFoldersWatches();
0083     QVERIFY(spy.wait());
0084     QCOMPARE(spy.count(), 1);
0085 
0086     QSignalSpy spyIndexNew(&fileWatch, &FileWatch::indexNewFile);
0087     QSignalSpy spyIndexModified(&fileWatch, &FileWatch::indexModifiedFile);
0088     QSignalSpy spyIndexXattr(&fileWatch, &FileWatch::indexXAttr);
0089 
0090     QVERIFY(spyIndexNew.isValid());
0091     QVERIFY(spyIndexModified.isValid());
0092     QVERIFY(spyIndexXattr.isValid());
0093 
0094     // Create a file and see if it is indexed
0095     QString fileUrl(m_tmpDir->path() + QStringLiteral("/t1"));
0096     QVERIFY(createFile(fileUrl));
0097 
0098     QVERIFY(spyIndexNew.wait());
0099     QCOMPARE(spyIndexNew.count(), 1);
0100     QCOMPARE(spyIndexModified.count(), 0);
0101     QCOMPARE(spyIndexXattr.count(), 0);
0102     QCOMPARE(spyIndexNew.takeFirst().at(0), fileUrl);
0103 
0104     // Modify the file
0105     modifyFile(fileUrl);
0106 
0107     QVERIFY(spyIndexModified.wait());
0108     QCOMPARE(spyIndexNew.count(), 0);
0109     QCOMPARE(spyIndexModified.count(), 1);
0110     QCOMPARE(spyIndexXattr.count(), 0);
0111     QCOMPARE(spyIndexModified.takeFirst().at(0), fileUrl);
0112 
0113     // Set an Xattr
0114     KFileMetaData::UserMetaData umd(fileUrl);
0115     if (!umd.isSupported()) {
0116         qWarning() << "Xattr not supported on this filesystem:" << fileUrl;
0117     } else {
0118         const QString userComment(QStringLiteral("UserComment"));
0119         QVERIFY(umd.setUserComment(userComment) == KFileMetaData::UserMetaData::NoError);
0120 
0121         QVERIFY(spyIndexXattr.wait());
0122         QCOMPARE(spyIndexNew.count(), 0);
0123         QCOMPARE(spyIndexModified.count(), 0);
0124         QCOMPARE(spyIndexXattr.count(), 1);
0125         QCOMPARE(spyIndexXattr.takeFirst().at(0), fileUrl);
0126     }
0127 
0128     // Change permisssions
0129     QFile f(fileUrl);
0130     auto permissions = f.permissions();
0131     f.setPermissions(permissions & ~QFileDevice::WriteOwner);
0132 
0133     QVERIFY(spyIndexXattr.wait());
0134     QCOMPARE(spyIndexNew.count(), 0);
0135     QCOMPARE(spyIndexModified.count(), 0);
0136     QCOMPARE(spyIndexXattr.count(), 1);
0137     QCOMPARE(spyIndexXattr.takeFirst().at(0), fileUrl);
0138 }
0139 
0140 void FileWatchTest::testConfigChange()
0141 {
0142     m_db->open(Baloo::Database::CreateDatabase);
0143 
0144     QString d1 = m_tmpDir->path() + QStringLiteral("/d1");
0145     QString d2 = m_tmpDir->path() + QStringLiteral("/d2");
0146     QString d11 = m_tmpDir->path() + QStringLiteral("/d1/d11");
0147     QString d21 = m_tmpDir->path() + QStringLiteral("/d2/d21");
0148     QString d22 = m_tmpDir->path() + QStringLiteral("/d2/d22");
0149 
0150     QDir().mkpath(d11);
0151     QDir().mkpath(d21);
0152     QDir().mkpath(d22);
0153 
0154     // parameters: includeFolders list, excludeFolders list
0155     Test::writeIndexerConfig({d1, d2}, {d11, d21});
0156     FileIndexerConfig config;
0157 
0158     FileWatch fileWatch(m_db.get(), &config);
0159     fileWatch.m_pendingFileQueue->setMaximumTimeout(0);
0160     fileWatch.m_pendingFileQueue->setMinimumTimeout(0);
0161     fileWatch.m_pendingFileQueue->setTrackingTime(0);
0162 
0163     QSignalSpy spy(&fileWatch, &FileWatch::installedWatches);
0164     QVERIFY(spy.isValid());
0165 
0166     fileWatch.updateIndexedFoldersWatches();
0167     QVERIFY(spy.wait());
0168     QCOMPARE(spy.count(), 2);
0169 
0170     QSignalSpy spyIndexNew(&fileWatch, &FileWatch::indexNewFile);
0171     QVERIFY(spyIndexNew.isValid());
0172     QVERIFY(createFile(d1 + QStringLiteral("/t1")));
0173     QVERIFY(createFile(d2 + QStringLiteral("/t2")));
0174 
0175     QVERIFY(spyIndexNew.wait());
0176     QCOMPARE(spyIndexNew.count(), 2);
0177     spyIndexNew.clear();
0178 
0179     // dir d22 is not yet excluded, so one event is expected
0180     QVERIFY(createFile(d11 + QStringLiteral("/tx1")));
0181     QVERIFY(createFile(d21 + QStringLiteral("/tx2")));
0182     QVERIFY(createFile(d22 + QStringLiteral("/tx3")));
0183 
0184     QVERIFY(spyIndexNew.wait());
0185     QCOMPARE(spyIndexNew.count(), 1);
0186     QList<QVariant> event = spyIndexNew.at(0);
0187     QCOMPARE(event.at(0).toString(), d22 + QStringLiteral("/tx3"));
0188     spyIndexNew.clear();
0189 
0190     Test::writeIndexerConfig({d2}, {d22});
0191     config.forceConfigUpdate();
0192     fileWatch.updateIndexedFoldersWatches();
0193 
0194     // dir d1 is no longer included
0195     QVERIFY(createFile(d1 + QStringLiteral("/tx1a")));
0196     QVERIFY(createFile(d2 + QStringLiteral("/tx2a")));
0197     QVERIFY(spyIndexNew.wait());
0198     QList<QString> result;
0199     for (const QList<QVariant>& event : std::as_const(spyIndexNew)) {
0200     result.append(event.at(0).toString());
0201     }
0202     QCOMPARE(result, {d2 + QStringLiteral("/tx2a")});
0203     spyIndexNew.clear();
0204     result.clear();
0205 
0206     // d11 is implicitly excluded, as d1 is no longer included
0207     // d22 is explicitly excluded now, d21 is included
0208     QVERIFY(createFile(d11 + QStringLiteral("/tx1b")));
0209     QVERIFY(createFile(d21 + QStringLiteral("/tx2b")));
0210     QVERIFY(createFile(d22 + QStringLiteral("/tx3b")));
0211 
0212     QVERIFY(spyIndexNew.wait(500));
0213     for (const QList<QVariant>& event : std::as_const(spyIndexNew)) {
0214     result.append(event.at(0).toString());
0215     }
0216     QCOMPARE(result, {d21 + QStringLiteral("/tx2b")});
0217 }
0218 
0219 QTEST_MAIN(FileWatchTest)
0220 
0221 #include "filewatchtest.moc"