File indexing completed on 2024-04-14 14:19:43

0001 /* This file is part of the KDE libraries
0002     Copyright (c) 2005 Thomas Braxton <brax108@cox.net>
0003 
0004     This library is free software; you can redistribute it and/or
0005     modify it under the terms of the GNU Library General Public
0006     License version 2 as published by the Free Software Foundation.
0007 
0008     This library is distributed in the hope that it will be useful,
0009     but WITHOUT ANY WARRANTY; without even the implied warranty of
0010     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0011     Library General Public License for more details.
0012 
0013     You should have received a copy of the GNU Library General Public License
0014     along with this library; see the file COPYING.LIB.  If not, write to
0015     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0016     Boston, MA 02110-1301, USA.
0017 */
0018 
0019 #include "klockfiletest.h"
0020 #include "moc_klockfiletest.cpp"
0021 
0022 #include <unistd.h>
0023 #include <QTest>
0024 #include <QFile>
0025 #include <QProcess>
0026 #include <QIODevice>
0027 #include <QTextStream>
0028 #include <QtConcurrentRun>
0029 
0030 namespace QTest
0031 {
0032 
0033 char *toString(const KLockFile::LockResult &result)
0034 {
0035     static const char *const strings[] = {
0036         "LockOK", "LockFail", "LockError", "LockStale"
0037     };
0038     return qstrdup(strings[result]);
0039 }
0040 }
0041 
0042 // Here's how to test file locking on a FAT filesystem, on linux:
0043 // cd /tmp
0044 // dd if=/dev/zero of=fatfile count=180000
0045 // mkfs.vfat -F32 fatfile
0046 // mkdir -p fatsystem
0047 // sudo mount -o loop -o uid=$UID fatfile fatsystem
0048 //
0049 // static const char *const lockName = "/tmp/fatsystem/klockfiletest.lock";
0050 //
0051 // =====================================================================
0052 //
0053 // And here's how to test file locking over NFS, on linux:
0054 // In /etc/exports:    /tmp/nfs localhost(rw,sync,no_subtree_check)
0055 // sudo mount -t nfs localhost:/tmp/nfs /tmp/nfs-mount
0056 //
0057 // static const char *const lockName = "/tmp/nfs-mount/klockfiletest.lock";
0058 //
0059 // =====================================================================
0060 //
0061 
0062 static const char *const lockName = "klockfiletest.lock";
0063 
0064 void Test_KLockFile::initTestCase()
0065 {
0066     qApp->setApplicationName(QLatin1String("qttest"));
0067     QDir::setCurrent(QCoreApplication::applicationDirPath());
0068     QFile::remove(QString::fromLatin1(lockName));
0069     lockFile = new KLockFile(QLatin1String(lockName));
0070 }
0071 
0072 void Test_KLockFile::cleanupTestCase()
0073 {
0074     delete lockFile;
0075 }
0076 
0077 static KLockFile::LockResult testLockFromProcess(const QString &lockName)
0078 {
0079     const int ret = QProcess::execute(QString::fromLatin1("./klockfile_testlock"), QStringList() << lockName);
0080     return KLockFile::LockResult(ret);
0081 }
0082 
0083 static KLockFile::LockResult testLockFromThread()
0084 {
0085     KLockFile *lockFile = new KLockFile(QLatin1String(lockName));
0086     KLockFile::LockResult result = lockFile->lock(KLockFile::NoBlockFlag);
0087     delete lockFile;
0088     return result;
0089 }
0090 
0091 void Test_KLockFile::testLock()
0092 {
0093     QVERIFY(!lockFile->isLocked());
0094     QCOMPARE(lockFile->lock(), KLockFile::LockOK);
0095     QVERIFY(lockFile->isLocked());
0096 
0097     // Try to lock it again, should fail
0098     KLockFile *lockFile2 = new KLockFile(QLatin1String(lockName));
0099     QVERIFY(!lockFile2->isLocked());
0100     QCOMPARE(lockFile2->lock(KLockFile::NoBlockFlag), KLockFile::LockFail);
0101     QVERIFY(!lockFile2->isLocked());
0102     delete lockFile2;
0103 
0104     // Try from a different process.
0105     QCOMPARE(testLockFromProcess(QLatin1String(lockName)), KLockFile::LockFail);
0106 
0107     // Also try from a different thread.
0108     QFuture<KLockFile::LockResult> ret = QtConcurrent::run<KLockFile::LockResult>(testLockFromThread);
0109     QCOMPARE(ret.result(), KLockFile::LockFail);
0110 }
0111 
0112 void Test_KLockFile::testStale()
0113 {
0114 #ifdef Q_OS_WIN
0115     qDebug("unix stale lock support not implemented yet");
0116 #else
0117     QVERIFY(lockFile->isLocked());
0118 
0119     const int secs = 2;
0120     KLockFile lf = KLockFile(QLatin1String(lockName));
0121     lf.setStaleTime(secs);
0122     QVERIFY(lf.staleTime() == secs);
0123 
0124     QTest::qWait(secs * 1000);
0125     QCOMPARE(lf.lock(), KLockFile::LockStale);
0126     QVERIFY(!lf.isLocked());
0127 
0128     int pid;
0129     QString host, app;
0130     if (lf.getLockInfo(pid, host, app)) {
0131         QCOMPARE(pid, ::getpid());
0132         char hostname[256];
0133         if (::gethostname(hostname, sizeof(hostname)) == 0) {
0134             QCOMPARE(host, QLatin1String(hostname));
0135         }
0136         QCOMPARE(app, QLatin1String("qttest")); // this is our app name
0137     }
0138 #endif
0139 }
0140 
0141 void Test_KLockFile::testUnlock()
0142 {
0143     QVERIFY(lockFile->isLocked());
0144     lockFile->unlock();
0145     QVERIFY(!lockFile->isLocked());
0146 }
0147 
0148 void Test_KLockFile::testStaleNoBlockFlag()
0149 {
0150 #ifdef Q_OS_WIN
0151     QSKIP("lockfile on windows has different format", SkipSingle);
0152 #else
0153     char hostname[256];
0154     ::gethostname(hostname, sizeof(hostname));
0155 
0156     QFile f(QString::fromLatin1(lockName));
0157     QVERIFY(f.open(QIODevice::WriteOnly));
0158     QTextStream stream(&f);
0159     stream << QString::number(111222) << endl << QLatin1String("qttest") << endl << hostname << endl;
0160     stream.flush();
0161     f.close();
0162 
0163     KLockFile lockFile(QString::fromLatin1(lockName));
0164     QVERIFY(!lockFile.isLocked());
0165     QCOMPARE(lockFile.lock(KLockFile::NoBlockFlag), KLockFile::LockStale);
0166     QByteArray expectedMsg = QByteArray("WARNING: deleting stale lockfile ") + lockName;
0167     QTest::ignoreMessage(QtWarningMsg, expectedMsg.data());
0168     QCOMPARE(lockFile.lock(KLockFile::NoBlockFlag | KLockFile::ForceFlag), KLockFile::LockOK);
0169 
0170     QVERIFY(lockFile.isLocked());
0171 #endif
0172 }
0173 
0174 QTEST_MAIN(Test_KLockFile)