File indexing completed on 2024-04-21 03:53:39
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2019 David Hallas <david@davidhallas.dk> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "klistopenfilesjobtest_unix.h" 0009 #include "klistopenfilesjob.h" 0010 #include <QCoreApplication> 0011 #include <QStandardPaths> 0012 #include <QStringLiteral> 0013 #include <QTemporaryDir> 0014 #include <QTest> 0015 #include <algorithm> 0016 0017 #ifdef Q_OS_FREEBSD 0018 // See implementation note in testOpenFiles() 0019 #include <QProcess> 0020 #endif 0021 0022 QTEST_MAIN(KListOpenFilesJobTest) 0023 void initLocale() 0024 { 0025 qputenv("LC_ALL", "en_US.utf-8"); 0026 } 0027 0028 Q_CONSTRUCTOR_FUNCTION(initLocale) 0029 0030 namespace 0031 { 0032 bool hasLsofInstalled() 0033 { 0034 return !QStandardPaths::findExecutable(QStringLiteral("lsof")).isEmpty(); 0035 } 0036 0037 } 0038 0039 void KListOpenFilesJobTest::testOpenFiles() 0040 { 0041 if (!hasLsofInstalled()) { 0042 QSKIP("lsof is not installed - skipping test"); 0043 } 0044 0045 // Create a file and hold it open, so that lsof must report us 0046 QTemporaryDir tempDir; 0047 QFile tempFile(tempDir.path() + QStringLiteral("/file")); 0048 QVERIFY(tempFile.open(QIODevice::WriteOnly)); 0049 bool xfail_zfs = false; // Expected failure because of ZFS 0050 #ifdef Q_OS_FREEBSD 0051 // FIXME: On FreeBSD, lsof does not support zfs (as of 2022), see 0052 // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=253553 0053 // 0054 // This affects regular files only. So for FreeBSD, check if 0055 // the tempDir seems to be on a ZFS filesystem, e.g. 0056 // 0057 // ``` 0058 // [adridg@beastie .../invent/kcoreaddons]$ lsof +d /tmp > /dev/null 0059 // lsof: WARNING: no ZFS support has been defined. 0060 // See 00FAQ for more information. 0061 // ``` 0062 { 0063 QProcess lsof; 0064 lsof.start(QStringLiteral("lsof"), {QStringLiteral("+d"), tempDir.path()}); 0065 lsof.waitForFinished(); 0066 0067 auto stderr = lsof.readAllStandardError(); 0068 xfail_zfs = (lsof.exitCode() != 0) && stderr.contains("ZFS"); 0069 } 0070 #endif 0071 0072 auto job = new KListOpenFilesJob(tempDir.path()); 0073 QVERIFY2(job->exec(), qPrintable(job->errorString())); 0074 QCOMPARE(job->error(), KJob::NoError); 0075 auto processInfoList = job->processInfoList(); 0076 if (xfail_zfs) { 0077 // Ths list is empty, so the subsequent find and validity-checks 0078 // don't make sense. 0079 QEXPECT_FAIL("", "lsof(8) does not support regular files on ZFS", Abort); 0080 } 0081 QVERIFY(!processInfoList.empty()); 0082 auto testProcessIterator = std::find_if(processInfoList.begin(), processInfoList.end(), [](const KProcessList::KProcessInfo &info) { 0083 return info.pid() == QCoreApplication::applicationPid(); 0084 }); 0085 QVERIFY(testProcessIterator != processInfoList.end()); 0086 const auto &processInfo = *testProcessIterator; 0087 QVERIFY(processInfo.isValid()); 0088 QCOMPARE(processInfo.pid(), QCoreApplication::applicationPid()); 0089 } 0090 0091 void KListOpenFilesJobTest::testNoOpenFiles() 0092 { 0093 if (!hasLsofInstalled()) { 0094 QSKIP("lsof is not installed - skipping test"); 0095 } 0096 QTemporaryDir tempDir; 0097 auto job = new KListOpenFilesJob(tempDir.path()); 0098 QVERIFY2(job->exec(), qPrintable(job->errorString())); 0099 QCOMPARE(job->error(), KJob::NoError); 0100 QVERIFY(job->processInfoList().empty()); 0101 } 0102 0103 void KListOpenFilesJobTest::testNonExistingDir() 0104 { 0105 if (!hasLsofInstalled()) { 0106 QSKIP("lsof is not installed - skipping test"); 0107 } 0108 QString nonExistingDir(QStringLiteral("/does/not/exist")); 0109 auto job = new KListOpenFilesJob(nonExistingDir); 0110 QVERIFY(!job->exec()); 0111 QCOMPARE(job->error(), static_cast<int>(KListOpenFilesJob::Error::DoesNotExist)); 0112 QCOMPARE(job->errorText(), QStringLiteral("Path %1 doesn't exist").arg(nonExistingDir)); 0113 QVERIFY(job->processInfoList().empty()); 0114 } 0115 0116 /** 0117 * @brief Helper class to temporarily set an environment variable and reset it on destruction 0118 */ 0119 class ScopedEnvVariable 0120 { 0121 public: 0122 ScopedEnvVariable(const QLatin1String &Name, const QByteArray &NewValue) 0123 : name(Name) 0124 , originalValue(qgetenv(name.latin1())) 0125 { 0126 qputenv(name.latin1(), NewValue); 0127 } 0128 ~ScopedEnvVariable() 0129 { 0130 qputenv(name.latin1(), originalValue); 0131 } 0132 0133 private: 0134 const QLatin1String name; 0135 const QByteArray originalValue; 0136 }; 0137 0138 void KListOpenFilesJobTest::testLsofNotFound() 0139 { 0140 // This test relies on clearing the PATH variable so that lsof is not found 0141 ScopedEnvVariable emptyPathEnvironment(QLatin1String("PATH"), QByteArray()); 0142 QDir path(QCoreApplication::applicationDirPath()); 0143 auto job = new KListOpenFilesJob(path.path()); 0144 QVERIFY(!job->exec()); 0145 QCOMPARE(job->error(), static_cast<int>(KListOpenFilesJob::Error::InternalError)); 0146 QVERIFY(job->processInfoList().empty()); 0147 } 0148 0149 #include "moc_klistopenfilesjobtest_unix.cpp"