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)