From 0cdf33e9acb00b8f3654e8268253a3fb7c5db92c Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Tue, 16 Feb 2010 14:54:05 +1000 Subject: Fixed compile of shm/sem tests with vcproj generator. SUBDIRS+=../path/to/lackey from two different places means that qmake sees the lackey project twice. This breaks the vcproj generator. Make it so that lackey is only referred to once. --- tests/auto/auto.pro | 3 +- tests/auto/qsharedmemory/.gitignore | 3 - tests/auto/qsharedmemory/lackey/lackey.pro | 20 - tests/auto/qsharedmemory/lackey/main.cpp | 370 ---------- .../auto/qsharedmemory/lackey/scripts/consumer.js | 41 -- .../auto/qsharedmemory/lackey/scripts/producer.js | 44 -- .../lackey/scripts/readonly_segfault.js | 4 - .../lackey/scripts/systemlock_read.js | 11 - .../lackey/scripts/systemlock_readwrite.js | 11 - .../lackey/scripts/systemsemaphore_acquire.js | 18 - .../scripts/systemsemaphore_acquirerelease.js | 11 - .../lackey/scripts/systemsemaphore_release.js | 11 - tests/auto/qsharedmemory/qsharedmemory.pro | 4 - .../auto/qsharedmemory/qsystemlock/qsystemlock.pro | 22 - .../qsharedmemory/qsystemlock/tst_qsystemlock.cpp | 239 ------- tests/auto/qsharedmemory/src/qsystemlock.cpp | 246 ------- tests/auto/qsharedmemory/src/qsystemlock.h | 135 ---- tests/auto/qsharedmemory/src/qsystemlock_p.h | 109 --- tests/auto/qsharedmemory/src/qsystemlock_unix.cpp | 233 ------ tests/auto/qsharedmemory/src/qsystemlock_win.cpp | 182 ----- tests/auto/qsharedmemory/src/src.pri | 10 - tests/auto/qsharedmemory/test/test.pro | 37 - tests/auto/qsharedmemory/tst_qsharedmemory.cpp | 778 --------------------- tests/auto/qsystemsemaphore/.gitignore | 1 - tests/auto/qsystemsemaphore/files.qrc | 7 - tests/auto/qsystemsemaphore/qsystemsemaphore.pro | 4 - tests/auto/qsystemsemaphore/test/test.pro | 40 -- .../auto/qsystemsemaphore/tst_qsystemsemaphore.cpp | 302 -------- tests/auto/qtipc/lackey/lackey.pro | 20 + tests/auto/qtipc/lackey/main.cpp | 370 ++++++++++ tests/auto/qtipc/lackey/scripts/consumer.js | 41 ++ tests/auto/qtipc/lackey/scripts/producer.js | 44 ++ .../auto/qtipc/lackey/scripts/readonly_segfault.js | 4 + tests/auto/qtipc/lackey/scripts/systemlock_read.js | 11 + .../qtipc/lackey/scripts/systemlock_readwrite.js | 11 + .../lackey/scripts/systemsemaphore_acquire.js | 18 + .../scripts/systemsemaphore_acquirerelease.js | 11 + .../lackey/scripts/systemsemaphore_release.js | 11 + tests/auto/qtipc/qsharedmemory/.gitignore | 3 + tests/auto/qtipc/qsharedmemory/qsharedmemory.pro | 4 + .../qsharedmemory/qsystemlock/qsystemlock.pro | 22 + .../qsharedmemory/qsystemlock/tst_qsystemlock.cpp | 239 +++++++ tests/auto/qtipc/qsharedmemory/src/qsystemlock.cpp | 246 +++++++ tests/auto/qtipc/qsharedmemory/src/qsystemlock.h | 135 ++++ tests/auto/qtipc/qsharedmemory/src/qsystemlock_p.h | 109 +++ .../qtipc/qsharedmemory/src/qsystemlock_unix.cpp | 233 ++++++ .../qtipc/qsharedmemory/src/qsystemlock_win.cpp | 182 +++++ tests/auto/qtipc/qsharedmemory/src/src.pri | 10 + tests/auto/qtipc/qsharedmemory/test/test.pro | 37 + .../auto/qtipc/qsharedmemory/tst_qsharedmemory.cpp | 776 ++++++++++++++++++++ tests/auto/qtipc/qsystemsemaphore/.gitignore | 1 + tests/auto/qtipc/qsystemsemaphore/files.qrc | 7 + .../qtipc/qsystemsemaphore/qsystemsemaphore.pro | 36 + .../qsystemsemaphore/tst_qsystemsemaphore.cpp | 302 ++++++++ tests/auto/qtipc/qtipc.pro | 6 + 55 files changed, 2890 insertions(+), 2895 deletions(-) delete mode 100644 tests/auto/qsharedmemory/.gitignore delete mode 100644 tests/auto/qsharedmemory/lackey/lackey.pro delete mode 100644 tests/auto/qsharedmemory/lackey/main.cpp delete mode 100644 tests/auto/qsharedmemory/lackey/scripts/consumer.js delete mode 100644 tests/auto/qsharedmemory/lackey/scripts/producer.js delete mode 100644 tests/auto/qsharedmemory/lackey/scripts/readonly_segfault.js delete mode 100644 tests/auto/qsharedmemory/lackey/scripts/systemlock_read.js delete mode 100644 tests/auto/qsharedmemory/lackey/scripts/systemlock_readwrite.js delete mode 100644 tests/auto/qsharedmemory/lackey/scripts/systemsemaphore_acquire.js delete mode 100644 tests/auto/qsharedmemory/lackey/scripts/systemsemaphore_acquirerelease.js delete mode 100644 tests/auto/qsharedmemory/lackey/scripts/systemsemaphore_release.js delete mode 100644 tests/auto/qsharedmemory/qsharedmemory.pro delete mode 100644 tests/auto/qsharedmemory/qsystemlock/qsystemlock.pro delete mode 100644 tests/auto/qsharedmemory/qsystemlock/tst_qsystemlock.cpp delete mode 100644 tests/auto/qsharedmemory/src/qsystemlock.cpp delete mode 100644 tests/auto/qsharedmemory/src/qsystemlock.h delete mode 100644 tests/auto/qsharedmemory/src/qsystemlock_p.h delete mode 100644 tests/auto/qsharedmemory/src/qsystemlock_unix.cpp delete mode 100644 tests/auto/qsharedmemory/src/qsystemlock_win.cpp delete mode 100644 tests/auto/qsharedmemory/src/src.pri delete mode 100644 tests/auto/qsharedmemory/test/test.pro delete mode 100644 tests/auto/qsharedmemory/tst_qsharedmemory.cpp delete mode 100644 tests/auto/qsystemsemaphore/.gitignore delete mode 100644 tests/auto/qsystemsemaphore/files.qrc delete mode 100644 tests/auto/qsystemsemaphore/qsystemsemaphore.pro delete mode 100644 tests/auto/qsystemsemaphore/test/test.pro delete mode 100644 tests/auto/qsystemsemaphore/tst_qsystemsemaphore.cpp create mode 100644 tests/auto/qtipc/lackey/lackey.pro create mode 100644 tests/auto/qtipc/lackey/main.cpp create mode 100644 tests/auto/qtipc/lackey/scripts/consumer.js create mode 100644 tests/auto/qtipc/lackey/scripts/producer.js create mode 100644 tests/auto/qtipc/lackey/scripts/readonly_segfault.js create mode 100644 tests/auto/qtipc/lackey/scripts/systemlock_read.js create mode 100644 tests/auto/qtipc/lackey/scripts/systemlock_readwrite.js create mode 100644 tests/auto/qtipc/lackey/scripts/systemsemaphore_acquire.js create mode 100644 tests/auto/qtipc/lackey/scripts/systemsemaphore_acquirerelease.js create mode 100644 tests/auto/qtipc/lackey/scripts/systemsemaphore_release.js create mode 100644 tests/auto/qtipc/qsharedmemory/.gitignore create mode 100644 tests/auto/qtipc/qsharedmemory/qsharedmemory.pro create mode 100644 tests/auto/qtipc/qsharedmemory/qsystemlock/qsystemlock.pro create mode 100644 tests/auto/qtipc/qsharedmemory/qsystemlock/tst_qsystemlock.cpp create mode 100644 tests/auto/qtipc/qsharedmemory/src/qsystemlock.cpp create mode 100644 tests/auto/qtipc/qsharedmemory/src/qsystemlock.h create mode 100644 tests/auto/qtipc/qsharedmemory/src/qsystemlock_p.h create mode 100644 tests/auto/qtipc/qsharedmemory/src/qsystemlock_unix.cpp create mode 100644 tests/auto/qtipc/qsharedmemory/src/qsystemlock_win.cpp create mode 100644 tests/auto/qtipc/qsharedmemory/src/src.pri create mode 100644 tests/auto/qtipc/qsharedmemory/test/test.pro create mode 100644 tests/auto/qtipc/qsharedmemory/tst_qsharedmemory.cpp create mode 100644 tests/auto/qtipc/qsystemsemaphore/.gitignore create mode 100644 tests/auto/qtipc/qsystemsemaphore/files.qrc create mode 100644 tests/auto/qtipc/qsystemsemaphore/qsystemsemaphore.pro create mode 100644 tests/auto/qtipc/qsystemsemaphore/tst_qsystemsemaphore.cpp create mode 100644 tests/auto/qtipc/qtipc.pro diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 022b19a..9961e25 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -445,17 +445,16 @@ SUBDIRS += \ qplugin \ qpluginloader \ qscrollbar \ - qsharedmemory \ qsidebar \ qsizegrip \ qsqldriver \ - qsystemsemaphore \ qtconcurrentfilter \ qtconcurrentiteratekernel \ qtconcurrentmap \ qtconcurrentrun \ qtconcurrentthreadengine \ qthreadpool \ + qtipc \ qtokenautomaton \ qtouchevent \ qwidget_window \ diff --git a/tests/auto/qsharedmemory/.gitignore b/tests/auto/qsharedmemory/.gitignore deleted file mode 100644 index 03ddcf2..0000000 --- a/tests/auto/qsharedmemory/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -tst_qsharedmemory -lackey/lackey.exe -qsystemlock/tst_qsystemlock.exe diff --git a/tests/auto/qsharedmemory/lackey/lackey.pro b/tests/auto/qsharedmemory/lackey/lackey.pro deleted file mode 100644 index d25a50a..0000000 --- a/tests/auto/qsharedmemory/lackey/lackey.pro +++ /dev/null @@ -1,20 +0,0 @@ -include(../src/src.pri) - -QT = core script - -CONFIG += qtestlib - -DESTDIR = ./ - -win32: CONFIG += console -mac:CONFIG -= app_bundle - -requires(contains(QT_CONFIG,script)) - -DEFINES += QSHAREDMEMORY_DEBUG -DEFINES += QSYSTEMSEMAPHORE_DEBUG - -SOURCES += main.cpp -TARGET = lackey - - diff --git a/tests/auto/qsharedmemory/lackey/main.cpp b/tests/auto/qsharedmemory/lackey/main.cpp deleted file mode 100644 index fef8d22..0000000 --- a/tests/auto/qsharedmemory/lackey/main.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -class ScriptSystemSemaphore : public QObject -{ - Q_OBJECT - -public: - ScriptSystemSemaphore(QObject *parent = 0) : QObject(parent), ss(QString()) - { - } - -public slots: - bool acquire() - { - return ss.acquire(); - }; - - bool release(int n = 1) - { - return ss.release(n); - }; - - void setKey(const QString &key, int n = 0) - { - ss.setKey(key, n); - }; - - QString key() const - { - return ss.key(); - } - -private: - QSystemSemaphore ss; -}; - -class ScriptSystemLock : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString key WRITE setKey READ key) - -public: - ScriptSystemLock(QObject *parent = 0) : QObject(parent), sl(QString()) - { - } - -public slots: - - bool lockReadOnly() - { - return sl.lock(QSystemLock::ReadOnly); - } - - bool lock() - { - return sl.lock(); - }; - - bool unlock() - { - return sl.unlock(); - }; - - void setKey(const QString &key) - { - sl.setKey(key); - }; - - QString key() const - { - return sl.key(); - } - -private: - QSystemLock sl; -}; - -class ScriptSharedMemory : public QObject -{ - Q_OBJECT - Q_PROPERTY(bool attached READ isAttached) - Q_PROPERTY(QString key WRITE setKey READ key) - -public: - enum SharedMemoryError - { - NoError = 0, - PermissionDenied = 1, - InvalidSize = 2, - KeyError = 3, - AlreadyExists = 4, - NotFound = 5, - LockError = 6, - OutOfResources = 7, - UnknownError = 8 - }; - - ScriptSharedMemory(QObject *parent = 0) : QObject(parent) - { - } - -public slots: - void sleep(int x) const - { - QTest::qSleep(x); - } - - bool create(int size) - { - return sm.create(size); - }; - - bool createReadOnly(int size) - { - return sm.create(size, QSharedMemory::ReadOnly); - }; - - int size() const - { - return sm.size(); - }; - - bool attach() - { - return sm.attach(); - }; - - bool attachReadOnly() - { - return sm.attach(QSharedMemory::ReadOnly); - }; - - bool isAttached() const - { - return sm.isAttached(); - }; - - bool detach() - { - return sm.detach(); - }; - - int error() const - { - return (int)sm.error(); - }; - - QString errorString() const - { - return sm.errorString(); - }; - - void set(int i, QChar value) - { - ((char*)sm.data())[i] = value.toLatin1(); - } - - QString get(int i) - { - return QChar::fromLatin1(((char*)sm.data())[i]); - } - - char *data() const - { - return (char*)sm.data(); - }; - - void setKey(const QString &key) - { - sm.setKey(key); - }; - - QString key() const - { - return sm.key(); - } - - bool lock() - { - return sm.lock(); - } - - bool unlock() - { - return sm.unlock(); - } - -private: - QSharedMemory sm; -}; - -QT_BEGIN_NAMESPACE -Q_SCRIPT_DECLARE_QMETAOBJECT(ScriptSharedMemory, QObject*); -Q_SCRIPT_DECLARE_QMETAOBJECT(ScriptSystemLock, QObject*); -Q_SCRIPT_DECLARE_QMETAOBJECT(ScriptSystemSemaphore, QObject*); -QT_END_NAMESPACE - -static void interactive(QScriptEngine &eng) -{ -#ifdef Q_OS_WINCE - fprintf(stderr, "Interactive mode not supported on Windows CE\n"); - return; -#endif - QTextStream qin(stdin, QFile::ReadOnly); - - const char *qscript_prompt = "qs> "; - const char *dot_prompt = ".... "; - const char *prompt = qscript_prompt; - - QString code; - - forever { - QString line; - - printf("%s", prompt); - fflush(stdout); - - line = qin.readLine(); - if (line.isNull()) - break; - - code += line; - code += QLatin1Char('\n'); - - if (line.trimmed().isEmpty()) { - continue; - - } else if (! eng.canEvaluate(code)) { - prompt = dot_prompt; - - } else { - QScriptValue result = eng.evaluate(code); - code.clear(); - prompt = qscript_prompt; - if (!result.isUndefined()) - fprintf(stderr, "%s\n", qPrintable(result.toString())); - } - } -} - -int main(int argc, char *argv[]) -{ - QCoreApplication app(argc, argv); - - QScriptEngine eng; - QScriptValue globalObject = eng.globalObject(); - - QScriptValue sm = qScriptValueFromQMetaObject(&eng); - eng.globalObject().setProperty("ScriptSharedMemory", sm); - - QScriptValue sl = qScriptValueFromQMetaObject(&eng); - eng.globalObject().setProperty("ScriptSystemLock", sl); - - QScriptValue ss = qScriptValueFromQMetaObject(&eng); - eng.globalObject().setProperty("ScriptSystemSemaphore", ss); - - - if (! *++argv) { - interactive(eng); - return EXIT_SUCCESS; - } - - QStringList arguments = app.arguments(); - arguments.takeFirst(); - - while (!arguments.isEmpty()) { - QString fn = arguments.takeFirst(); - - if (fn == QLatin1String("-i")) { - interactive(eng); - break; - } - - QString contents; - - if (fn == QLatin1String("-")) { - QTextStream stream(stdin, QFile::ReadOnly); - contents = stream.readAll(); - } else { - QFile file(fn); - if (!file.exists()) { - fprintf(stderr, "%s doesn't exists\n", qPrintable(fn)); - return EXIT_FAILURE; - } - if (file.open(QFile::ReadOnly)) { - QTextStream stream(&file); - contents = stream.readAll(); - file.close(); - } - } - - if (contents.isEmpty()) - continue; - - if (contents[0] == '#') { - contents.prepend("//"); - QScriptValue args = eng.newArray(); - args.setProperty("0", QScriptValue(&eng, fn)); - int i = 1; - while (!arguments.isEmpty()) - args.setProperty(i++, QScriptValue(&eng, arguments.takeFirst())); - eng.currentContext()->activationObject().setProperty("args", args); - } - QScriptValue r = eng.evaluate(contents); - if (eng.hasUncaughtException()) { - int line = eng.uncaughtExceptionLineNumber(); - fprintf(stderr, "%d: %s\n\t%s\n\n", line, qPrintable(fn), qPrintable(r.toString())); - return EXIT_FAILURE; - } - if (r.isNumber()) - return r.toInt32(); - } - - return EXIT_SUCCESS; -} - -#include "main.moc" diff --git a/tests/auto/qsharedmemory/lackey/scripts/consumer.js b/tests/auto/qsharedmemory/lackey/scripts/consumer.js deleted file mode 100644 index 4d12dca..0000000 --- a/tests/auto/qsharedmemory/lackey/scripts/consumer.js +++ /dev/null @@ -1,41 +0,0 @@ -function QVERIFY(x, debugInfo) { - if (!(x)) { - print(debugInfo); - throw(debugInfo); - } -} - -var consumer = new ScriptSharedMemory; -consumer.setKey("market"); - -//print("consumer starting"); -var tries = 0;; -while(!consumer.attach()) { - if (tries == 5000) { - var message = "consumer exiting, waiting too long"; - print(message); - throw(message); - } - ++tries; - consumer.sleep(1); -} -//print("consumer attached"); - - -var i = 0; -while(true) { - QVERIFY(consumer.lock(), "lock"); - if (consumer.get(0) == 'Q') { - consumer.set(0, ++i); - //print ("consumer sets" + i); - } - if (consumer.get(0) == 'E') { - QVERIFY(consumer.unlock(), "unlock"); - break; - } - QVERIFY(consumer.unlock(), "unlock"); - consumer.sleep(10); -} - -//print("consumer detaching"); -QVERIFY(consumer.detach()); diff --git a/tests/auto/qsharedmemory/lackey/scripts/producer.js b/tests/auto/qsharedmemory/lackey/scripts/producer.js deleted file mode 100644 index e02cd8b..0000000 --- a/tests/auto/qsharedmemory/lackey/scripts/producer.js +++ /dev/null @@ -1,44 +0,0 @@ -function QVERIFY(x, debugInfo) { - if (!(x)) { - print(debugInfo); - throw(debugInfo); - } -} - -var producer = new ScriptSharedMemory; -producer.setKey("market"); - -var size = 1024; -if (!producer.create(size)) { - QVERIFY(producer.error() == 4, "create"); - QVERIFY(producer.attach()); -} -//print ("producer created and attached"); - -QVERIFY(producer.lock()); -producer.set(0, 'Q'); -QVERIFY(producer.unlock()); - -var i = 0; -while(i < 5) { - QVERIFY(producer.lock(), "lock"); - if (producer.get(0) == 'Q') { - QVERIFY(producer.unlock(), "unlock"); - producer.sleep(1); - continue; - } - //print("producer: " + i); - ++i; - producer.set(0, 'Q'); - QVERIFY(producer.unlock(), "unlock"); - producer.sleep(1); -} -QVERIFY(producer.lock()); -producer.set(0, 'E'); -QVERIFY(producer.unlock()); - -//print ("producer done"); - -// Sleep for a bit to let all consumers start, otherwise they will get stuck in the attach loop, -// because at least in Symbian the shared memory will be destroyed if there are no active handles to it. -producer.sleep(3000); \ No newline at end of file diff --git a/tests/auto/qsharedmemory/lackey/scripts/readonly_segfault.js b/tests/auto/qsharedmemory/lackey/scripts/readonly_segfault.js deleted file mode 100644 index 3eaf789..0000000 --- a/tests/auto/qsharedmemory/lackey/scripts/readonly_segfault.js +++ /dev/null @@ -1,4 +0,0 @@ -var sm = new ScriptSharedMemory; -sm.setKey("readonly_segfault"); -sm.createReadOnly(1024); -var data = sm.set(0, "a"); diff --git a/tests/auto/qsharedmemory/lackey/scripts/systemlock_read.js b/tests/auto/qsharedmemory/lackey/scripts/systemlock_read.js deleted file mode 100644 index 1048bc7..0000000 --- a/tests/auto/qsharedmemory/lackey/scripts/systemlock_read.js +++ /dev/null @@ -1,11 +0,0 @@ -function QVERIFY(x, debugInfo) { - if (!(x)) { - print(debugInfo); - throw(debugInfo); - } -} - -var lock = new ScriptSystemLock; -lock.setKey("market"); -QVERIFY(lock.lockReadOnly()); -QVERIFY(lock.unlock()); \ No newline at end of file diff --git a/tests/auto/qsharedmemory/lackey/scripts/systemlock_readwrite.js b/tests/auto/qsharedmemory/lackey/scripts/systemlock_readwrite.js deleted file mode 100644 index fc6367f..0000000 --- a/tests/auto/qsharedmemory/lackey/scripts/systemlock_readwrite.js +++ /dev/null @@ -1,11 +0,0 @@ -function QVERIFY(x, debugInfo) { - if (!(x)) { - print(debugInfo); - throw(debugInfo); - } -} - -var lock = new ScriptSystemLock; -lock.setKey("market"); -QVERIFY(lock.lock()); -QVERIFY(lock.unlock()); diff --git a/tests/auto/qsharedmemory/lackey/scripts/systemsemaphore_acquire.js b/tests/auto/qsharedmemory/lackey/scripts/systemsemaphore_acquire.js deleted file mode 100644 index 5cff429..0000000 --- a/tests/auto/qsharedmemory/lackey/scripts/systemsemaphore_acquire.js +++ /dev/null @@ -1,18 +0,0 @@ -#/bin/qscript -function QVERIFY(x, debugInfo) { - if (!(x)) { - print(debugInfo); - throw(debugInfo); - } -} - - -var sem = new ScriptSystemSemaphore; -sem.setKey("store"); - -var count = Number(args[1]); -if (isNaN(count)) - count = 1; -for (var i = 0; i < count; ++i) - QVERIFY(sem.acquire()); -print("done aquiring"); diff --git a/tests/auto/qsharedmemory/lackey/scripts/systemsemaphore_acquirerelease.js b/tests/auto/qsharedmemory/lackey/scripts/systemsemaphore_acquirerelease.js deleted file mode 100644 index cedde3f..0000000 --- a/tests/auto/qsharedmemory/lackey/scripts/systemsemaphore_acquirerelease.js +++ /dev/null @@ -1,11 +0,0 @@ -function QVERIFY(x, debugInfo) { - if (!(x)) { - print(debugInfo); - throw(debugInfo); - } -} - -var lock = new ScriptSystemSemaphore; -lock.setKey("store"); -QVERIFY(lock.acquire()); -QVERIFY(lock.release()); diff --git a/tests/auto/qsharedmemory/lackey/scripts/systemsemaphore_release.js b/tests/auto/qsharedmemory/lackey/scripts/systemsemaphore_release.js deleted file mode 100644 index c805e0f..0000000 --- a/tests/auto/qsharedmemory/lackey/scripts/systemsemaphore_release.js +++ /dev/null @@ -1,11 +0,0 @@ -function QVERIFY(x, debugInfo) { - if (!(x)) { - print(debugInfo); - throw(debugInfo); - } -} - -var sem = new ScriptSystemSemaphore; -sem.setKey("store"); -QVERIFY(sem.release()); -print ("done releasing"); diff --git a/tests/auto/qsharedmemory/qsharedmemory.pro b/tests/auto/qsharedmemory/qsharedmemory.pro deleted file mode 100644 index 0aad554..0000000 --- a/tests/auto/qsharedmemory/qsharedmemory.pro +++ /dev/null @@ -1,4 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = lackey test qsystemlock - - diff --git a/tests/auto/qsharedmemory/qsystemlock/qsystemlock.pro b/tests/auto/qsharedmemory/qsystemlock/qsystemlock.pro deleted file mode 100644 index e232443..0000000 --- a/tests/auto/qsharedmemory/qsystemlock/qsystemlock.pro +++ /dev/null @@ -1,22 +0,0 @@ -CONFIG += qttest_p4 -#QT = core - -include(../src/src.pri) -win32: CONFIG += console -mac:CONFIG -= app_bundle - -wince* { - DEFINES += SRCDIR=\\\"\\\" -} else:!symbian { - DEFINES += SRCDIR=\\\"$$PWD\\\" -} - -DESTDIR = ./ - -DEFINES += QSHAREDMEMORY_DEBUG -DEFINES += QSYSTEMSEMAPHORE_DEBUG - -SOURCES += tst_qsystemlock.cpp -TARGET = tst_qsystemlock - - diff --git a/tests/auto/qsharedmemory/qsystemlock/tst_qsystemlock.cpp b/tests/auto/qsharedmemory/qsystemlock/tst_qsystemlock.cpp deleted file mode 100644 index ea906b7..0000000 --- a/tests/auto/qsharedmemory/qsystemlock/tst_qsystemlock.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include -#include - -//TESTED_CLASS= -//TESTED_FILES= - -#ifdef Q_OS_SYMBIAN -// In Symbian OS test data is located in applications private dir -// And underlying Open C have application private dir in default search path -#define SRCDIR "" -#endif - - -#define EXISTING_SHARE "existing" - -class tst_QSystemLock : public QObject -{ - Q_OBJECT - -public: - tst_QSystemLock(); - virtual ~tst_QSystemLock(); - -public Q_SLOTS: - void init(); - void cleanup(); - -private slots: - void key_data(); - void key(); - - void basicLock(); - void complexLock(); - void lockModes(); - void sucessive(); - void processes_data(); - void processes(); - -private: - QSystemLock *existingLock; - -}; - -tst_QSystemLock::tst_QSystemLock() -{ -} - -tst_QSystemLock::~tst_QSystemLock() -{ -} - -void tst_QSystemLock::init() -{ - existingLock = new QSystemLock(EXISTING_SHARE); -} - -void tst_QSystemLock::cleanup() -{ - delete existingLock; -} - -void tst_QSystemLock::key_data() -{ - QTest::addColumn("constructorKey"); - QTest::addColumn("setKey"); - - QTest::newRow("null, null") << QString() << QString(); - QTest::newRow("null, one") << QString() << QString("one"); - QTest::newRow("one, two") << QString("one") << QString("two"); -} - -/*! - Basic key testing - */ -void tst_QSystemLock::key() -{ - QFETCH(QString, constructorKey); - QFETCH(QString, setKey); - - QSystemLock sl(constructorKey); - QCOMPARE(sl.key(), constructorKey); - sl.setKey(setKey); - QCOMPARE(sl.key(), setKey); -} - -void tst_QSystemLock::basicLock() -{ - QSystemLock lock("foo"); - QVERIFY(lock.lock()); - QVERIFY(lock.unlock()); -} - -void tst_QSystemLock::complexLock() -{ - QSystemLock lock("foo"); - QVERIFY(lock.lock(QSystemLock::ReadOnly)); - QVERIFY(lock.unlock()); - - QVERIFY(lock.lock(QSystemLock::ReadWrite)); - QVERIFY(lock.unlock()); - - QVERIFY(lock.lock(QSystemLock::ReadOnly)); - QVERIFY(lock.lock(QSystemLock::ReadOnly)); - QVERIFY(lock.unlock()); - QVERIFY(lock.unlock()); -} - -void tst_QSystemLock::lockModes() -{ - QSystemLock reader1("library"); - QSystemLock reader2("library"); - - QSystemLock librarian("library"); - QVERIFY(reader1.lock(QSystemLock::ReadOnly)); - QVERIFY(reader2.lock(QSystemLock::ReadOnly)); - QVERIFY(reader1.unlock()); - QVERIFY(reader2.unlock()); - QVERIFY(librarian.lock(QSystemLock::ReadWrite)); - QVERIFY(librarian.unlock()); -} - -void tst_QSystemLock::sucessive() -{ - QSystemLock lock("library"); - QVERIFY(lock.lock(QSystemLock::ReadOnly)); - QVERIFY(lock.lock(QSystemLock::ReadOnly)); - QVERIFY(lock.lock(QSystemLock::ReadOnly)); - QVERIFY(lock.lock(QSystemLock::ReadOnly)); - QVERIFY(lock.lock(QSystemLock::ReadOnly)); - QVERIFY(lock.unlock()); - QVERIFY(lock.unlock()); - QVERIFY(lock.unlock()); - QVERIFY(lock.unlock()); - QVERIFY(lock.unlock()); - QVERIFY(!lock.unlock()); -} - -void tst_QSystemLock::processes_data() -{ - QTest::addColumn("readOnly"); - QTest::addColumn("readWrite"); - for (int i = 0; i < 5; ++i) { - QTest::newRow("1/0 process") << 1 << 0; - QTest::newRow("0/1 process") << 0 << 1; - QTest::newRow("0/4 process") << 0 << 4; - QTest::newRow("1/1 process") << 1 << 1; - QTest::newRow("10/1 process") << 10 << 1; - QTest::newRow("1/10 process") << 1 << 10; - QTest::newRow("10/10 processes") << 10 << 10; - } -} - -/*! - Create external processes - */ -void tst_QSystemLock::processes() -{ - QSKIP("This test takes about 15 minutes and needs to be trimmed down before we can re-enable it", SkipAll); - QFETCH(int, readOnly); - QFETCH(int, readWrite); - - QStringList scripts; - for (int i = 0; i < readOnly; ++i) - scripts.append(QFileInfo(SRCDIR "/../lackey/scripts/systemlock_read.js").absoluteFilePath() ); - for (int i = 0; i < readWrite; ++i) - scripts.append(QFileInfo(SRCDIR "/../lackey/scripts/systemlock_readwrite.js").absoluteFilePath()); - - QList consumers; - unsigned int failedProcesses = 0; - for (int i = 0; i < scripts.count(); ++i) { - - QStringList arguments = QStringList() << scripts.at(i); - QProcess *p = new QProcess; - p->setProcessChannelMode(QProcess::ForwardedChannels); - - p->start("../lackey/lackey", arguments); - // test, if the process could be started. - - if (p->waitForStarted(2000)) - consumers.append(p); - else - ++failedProcesses; - } - - while (!consumers.isEmpty()) { - consumers.first()->waitForFinished(3000); - consumers.first()->kill(); - QCOMPARE(consumers.first()->exitStatus(), QProcess::NormalExit); - QCOMPARE(consumers.first()->exitCode(), 0); - delete consumers.takeFirst(); - } - QCOMPARE(failedProcesses, (unsigned int)(0)); -} - -QTEST_MAIN(tst_QSystemLock) -#include "tst_qsystemlock.moc" - diff --git a/tests/auto/qsharedmemory/src/qsystemlock.cpp b/tests/auto/qsharedmemory/src/qsystemlock.cpp deleted file mode 100644 index 4ead748..0000000 --- a/tests/auto/qsharedmemory/src/qsystemlock.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qsystemlock.h" -#include "qsystemlock_p.h" - -#include - -/*! \class QSystemLocker - - \brief The QSystemLocker class is a convenience class that simplifies - locking and unlocking system locks. - - The purpose of QSystemLocker is to simplify QSystemLock locking and - unlocking. Locking and unlocking a QSystemLock in complex functions and - statements or in exception handling code is error-prone and difficult to - debug. QSystemLocker can be used in such situations to ensure that the - state of the locks is always well-defined. - - QSystemLocker should be created within a function where a QSystemLock needs - to be locked. The system lock is locked when QSystemLocker is created. If - locked, the system lock will be unlocked when the QSystemLocker is - destroyed. QSystemLocker can be unlocked with unlock() and relocked with - relock(). - - \sa QSystemLock - */ - -/*! \fn QSystemLocker::QSystemLocker() - - Constructs a QSystemLocker and locks \a lock. The \a lock will be - unlocked when the QSystemLocker is destroyed. If lock is zero, - QSystemLocker does nothing. - - \sa QSystemLock::lock() - */ - -/*! \fn QSystemLocker::~QSystemLocker() - - Destroys the QSystemLocker and unlocks it if it was - locked in the constructor. - - \sa QSystemLock::unlock() - */ - -/*! \fn QSystemLocker::systemLock() - - Returns a pointer to the lock that was locked in the constructor. - */ - -/*! \fn QSystemLocker::relock() - - Relocks an unlocked locker. - - \sa unlock() - */ - -/*! \fn QSystemLocker::unlock() - - Unlocks this locker. You can use relock() to lock it again. - It does not need to be locked when destroyed. - - \sa relock() - */ - -/*! \class QSystemLock - - \brief The QSystemLock class provides a system wide lock - that can be used between threads or processes. - - The purpose of a QSystemLocker is to protect an object that can be - accessed by multiple threads or processes such as shared memory or a file. - - For example, say there is a method which prints a message to a log file: - - void log(const QString &logText) - { - QSystemLock systemLock(QLatin1String("logfile")); - systemLock.lock(); - QFile file(QDir::temp() + QLatin1String("/log")); - if (file.open(QIODevice::Append)) { - QTextStream out(&file); - out << logText; - } - systemLock.unlock(); - } - - If this is called from two seperate processes the resulting log file is - guaranteed to contain both lines. - - When you call lock(), other threads or processes that try to call lock() - with the same key will block until the thread or process that got the lock - calls unlock(). - - A non-blocking alternative to lock() is tryLock(). - */ - -/*! - Constructs a new system lock with \a key. The lock is created in an - unlocked state. - - \sa lock(), key(). - */ -QSystemLock::QSystemLock(const QString &key) -{ - d = new QSystemLockPrivate; - setKey(key); -} - -/*! - Destroys a system lock. - - warning: This will not unlock the system lock if it has been locked. -*/ -QSystemLock::~QSystemLock() -{ - d->cleanHandle(); - delete d; -} - -/*! - Sets a new key to this system lock. - - \sa key() - */ -void QSystemLock::setKey(const QString &key) -{ - if (key == d->key) - return; - d->cleanHandle(); - d->lockCount = 0; - d->key = key; - // cache the file name so it doesn't have to be generated all the time. - d->fileName = d->makeKeyFileName(); - d->error = QSystemLock::NoError; - d->errorString = QString(); - d->handle(); -} - -/*! - Returns the key assigned to this system lock - - \sa setKey() - */ -QString QSystemLock::key() const -{ - return d->key; -} - -/*! - Locks the system lock. Lock \a mode can either be ReadOnly or ReadWrite. - If a mode is ReadOnly, attempts by other processes to obtain - ReadOnly locks will succeed, and ReadWrite attempts will block until - all of the ReadOnly locks are unlocked. If locked as ReadWrite, all - other attempts to lock will block until the lock is unlocked. A given - QSystemLock can be locked multiple times without blocking, and will - only be unlocked after a corresponding number of unlock() - calls are made. Returns true on success; otherwise returns false. - - \sa unlock(), tryLock() - */ -bool QSystemLock::lock(LockMode mode) -{ - if (d->lockCount > 0 && mode == ReadOnly && d->lockedMode == ReadWrite) { - qWarning() << "QSystemLock::lock readwrite lock on top of readonly lock."; - return false; - } - return d->modifySemaphore(QSystemLockPrivate::Lock, mode); -} - -/*! - Unlocks the system lock. - Returns true on success; otherwise returns false. - - \sa lock() - */ -bool QSystemLock::unlock() -{ - if (d->lockCount == 0) { - qWarning() << "QSystemLock::unlock: unlock with no lock."; - return false; - } - return d->modifySemaphore(QSystemLockPrivate::Unlock, d->lockedMode); -} - -/*! - Returns the type of error that occurred last or NoError. - - \sa errorString() - */ -QSystemLock::SystemLockError QSystemLock::error() const -{ - return d->error; -} - -/*! - Returns the human-readable message appropriate to the current error - reported by error(). If no suitable string is available, an empty - string is returned. - - \sa error() - */ -QString QSystemLock::errorString() const -{ - return d->errorString; -} - diff --git a/tests/auto/qsharedmemory/src/qsystemlock.h b/tests/auto/qsharedmemory/src/qsystemlock.h deleted file mode 100644 index 7cd6b89..0000000 --- a/tests/auto/qsharedmemory/src/qsystemlock.h +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QSYSTEMLOCK_H -#define QSYSTEMLOCK_H - -#include - -QT_BEGIN_HEADER - -#ifndef QT_NO_SYSTEMLOCK - -QT_FORWARD_DECLARE_CLASS(QSystemLockPrivate) - -class QSystemLock -{ - -public: - enum SystemLockError - { - NoError, - UnknownError - }; - - QSystemLock(const QString &key); - ~QSystemLock(); - - void setKey(const QString &key); - QString key() const; - - enum LockMode - { - ReadOnly, - ReadWrite - }; - - bool lock(LockMode mode = ReadWrite); - bool unlock(); - - SystemLockError error() const; - QString errorString() const; - -private: - Q_DISABLE_COPY(QSystemLock) - - QSystemLockPrivate *d; -}; - -class QSystemLocker -{ - -public: - inline QSystemLocker(QSystemLock *systemLock, - QSystemLock::LockMode mode = QSystemLock::ReadWrite) : q_lock(systemLock) - { - autoUnLocked = relock(mode); - } - - inline ~QSystemLocker() - { - if (autoUnLocked) - unlock(); - } - - inline QSystemLock *systemLock() const - { - return q_lock; - } - - inline bool relock(QSystemLock::LockMode mode = QSystemLock::ReadWrite) - { - return (q_lock && q_lock->lock(mode)); - } - - inline bool unlock() - { - if (q_lock && q_lock->unlock()) { - autoUnLocked = false; - return true; - } - return false; - } - -private: - Q_DISABLE_COPY(QSystemLocker) - - bool autoUnLocked; - QSystemLock *q_lock; -}; - -#endif // QT_NO_SYSTEMLOCK - -QT_END_HEADER - -#endif // QSYSTEMLOCK_H - diff --git a/tests/auto/qsharedmemory/src/qsystemlock_p.h b/tests/auto/qsharedmemory/src/qsystemlock_p.h deleted file mode 100644 index 7995a91..0000000 --- a/tests/auto/qsharedmemory/src/qsystemlock_p.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QSYSTEMLOCK_P_H -#define QSYSTEMLOCK_P_H - -#ifndef QT_NO_SYSTEMLOCK - -#include "qsystemlock.h" -#include "private/qsharedmemory_p.h" -#ifndef Q_OS_WINCE -#include -#endif - -#define MAX_LOCKS 64 - -class QSystemLockPrivate -{ - -public: - QSystemLockPrivate(); - - QString makeKeyFileName() - { - return QSharedMemoryPrivate::makePlatformSafeKey(key, QLatin1String("qipc_systemlock_")); - } - - void setErrorString(const QString &function); - -#ifdef Q_OS_WIN - HANDLE handle(); - bool lock(HANDLE, int count); - bool unlock(HANDLE, int count); -#else - key_t handle(); -#endif - void cleanHandle(); - - enum Operation { - Lock, - Unlock - }; - bool modifySemaphore(Operation op, QSystemLock::LockMode mode = QSystemLock::ReadOnly); - - QString key; - QString fileName; -#ifdef Q_OS_WIN - HANDLE semaphore; - HANDLE semaphoreLock; -#else - int semaphore; -#endif - int lockCount; - QSystemLock::LockMode lockedMode; - - QSystemLock::SystemLockError error; - QString errorString; - -private: -#ifndef Q_OS_WIN - key_t unix_key; - bool createdFile; - bool createdSemaphore; -#endif -}; - -#endif // QT_NO_SYSTEMLOCK - -#endif // QSYSTEMLOCK_P_H - diff --git a/tests/auto/qsharedmemory/src/qsystemlock_unix.cpp b/tests/auto/qsharedmemory/src/qsystemlock_unix.cpp deleted file mode 100644 index 525aa78..0000000 --- a/tests/auto/qsharedmemory/src/qsystemlock_unix.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qsystemlock.h" -#include "qsystemlock_p.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -// We have to define this as on some sem.h will have it -union qt_semun { - int val; /* value for SETVAL */ - struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ - unsigned short *array; /* array for GETALL, SETALL */ -}; - -#define tr(x) QT_TRANSLATE_NOOP(QLatin1String("QSystemLock"), (x)) - -#if defined(Q_OS_SYMBIAN) -int createUnixKeyFile(const QString &fileName) -{ - if (QFile::exists(fileName)) - return 0; - - int fd = open(QFile::encodeName(fileName).constData(), - O_EXCL | O_CREAT | O_RDWR, 0640); - if (-1 == fd) { - if (errno == EEXIST) - return 0; - return -1; - } else { - close(fd); - } - return 1; -} -#endif - -QSystemLockPrivate::QSystemLockPrivate() : - semaphore(-1), lockCount(0), - error(QSystemLock::NoError), unix_key(-1), createdFile(false), createdSemaphore(false) -{ -} - -void QSystemLockPrivate::setErrorString(const QString &function) -{ - switch (errno) { - case EIDRM: - errorString = function + QLatin1String(": ") + tr("The semaphore set was removed"); - error = QSystemLock::UnknownError; - break; - default: - errorString = function + QLatin1String(": ") + tr("unknown error"); - error = QSystemLock::UnknownError; - qWarning() << errorString << "key" << key << "errno" << errno << ERANGE << ENOMEM << EINVAL << EINTR << EFBIG << EFAULT << EAGAIN << EACCES << E2BIG; - } -} - -/*! - \internal - - Setup unix_key - */ -key_t QSystemLockPrivate::handle() -{ - if (key.isEmpty()) - return -1; - - // ftok requires that an actual file exists somewhere - // If we have already made at some point in the past, - // double check that it is still there. - if (-1 != unix_key) { - int aNewunix_key = ftok(QFile::encodeName(fileName).constData(), 'Q'); - if (aNewunix_key != unix_key) { - cleanHandle(); - } else { - return unix_key; - } - } - - // Create the file needed for ftok -#if defined(Q_OS_SYMBIAN) - int built = createUnixKeyFile(fileName); -#else - int built = QSharedMemoryPrivate::createUnixKeyFile(fileName); -#endif - if (-1 == built) - return -1; - createdFile = (1 == built); - - // Get the unix key for the created file - unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q'); - if (-1 == unix_key) { - setErrorString(QLatin1String("QSystemLock::handle ftok")); - return -1; - } - - // Get semaphore - semaphore = semget(unix_key, 1, 0666 | IPC_CREAT | IPC_EXCL); - if (-1 == semaphore) { - if (errno == EEXIST) - semaphore = semget(unix_key, 1, 0666 | IPC_CREAT); - if (-1 == semaphore) { - setErrorString(QLatin1String("QSystemLock::handle semget")); - cleanHandle(); - return -1; - } - } else { - // Created semaphore, initialize value. - createdSemaphore = true; - qt_semun init_op; - init_op.val = MAX_LOCKS; - if (-1 == semctl(semaphore, 0, SETVAL, init_op)) { - setErrorString(QLatin1String("QSystemLock::handle semctl")); - cleanHandle(); - return -1; - } - } - - return unix_key; -} - -/*! - \internal - - Cleanup the unix_key - */ -void QSystemLockPrivate::cleanHandle() -{ - unix_key = -1; - - // remove the file if we made it - if (createdFile) { - if (!QFile::remove(fileName)) - setErrorString(QLatin1String("QSystemLock::cleanHandle QFile::remove")); - createdFile = false; - } - - if (createdSemaphore) { - if (-1 != semaphore) { - if (-1 == semctl(semaphore, 0, IPC_RMID)) { - setErrorString(QLatin1String("QSystemLock::cleanHandle semctl")); - } - semaphore = -1; - } - createdSemaphore = false; - } -} - -/*! - \internal - - modifySemaphore generates operation.sem_op and handles recursive behavior. - */ -bool QSystemLockPrivate::modifySemaphore(QSystemLockPrivate::Operation op, - QSystemLock::LockMode mode) -{ - if (-1 == handle()) - return false; - - if ((lockCount == 0 && op == Lock) || (lockCount > 0 && op == Unlock)) { - if (op == Unlock) { - --lockCount; - Q_ASSERT(lockCount >= 0); - if (lockCount > 0) - return true; - } - - struct sembuf operation; - operation.sem_num = 0; - operation.sem_op = (mode == QSystemLock::ReadWrite) ? MAX_LOCKS : 1; - if (op == Lock) - operation.sem_op *= -1; - operation.sem_flg = SEM_UNDO; - - if (-1 == semop(semaphore, &operation, 1)) { - setErrorString(QLatin1String("QSystemLock::modify")); - return false; - } - lockedMode = mode; - } - if (op == Lock) - lockCount++; - - return true; -} - diff --git a/tests/auto/qsharedmemory/src/qsystemlock_win.cpp b/tests/auto/qsharedmemory/src/qsystemlock_win.cpp deleted file mode 100644 index ac97100..0000000 --- a/tests/auto/qsharedmemory/src/qsystemlock_win.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qsystemlock.h" -#include "qsystemlock_p.h" -#include -#include -QSystemLockPrivate::QSystemLockPrivate() : - semaphore(0), semaphoreLock(0), - lockCount(0), error(QSystemLock::NoError) -{ -} - -void QSystemLockPrivate::setErrorString(const QString &function) -{ - BOOL windowsError = GetLastError(); - if (windowsError == 0) - return; - errorString = function + QLatin1String(": ") - + QLatin1String("Unknown error"); - error = QSystemLock::UnknownError; - qWarning() << errorString << "key" << key << (int)windowsError << semaphore << semaphoreLock; -} - -/*! - \internal - - Setup the semaphore - */ -HANDLE QSystemLockPrivate::handle() -{ - // don't allow making handles on empty keys - if (key.isEmpty()) - return 0; - - // Create it if it doesn't already exists. - if (semaphore == 0) { - QString safeName = makeKeyFileName(); - semaphore = CreateSemaphore(0, MAX_LOCKS, MAX_LOCKS, (wchar_t*)safeName.utf16()); - - if (semaphore == 0) { - setErrorString(QLatin1String("QSystemLockPrivate::handle")); - return 0; - } - } - - if (semaphoreLock == 0) { - QString safeLockName = QSharedMemoryPrivate::makePlatformSafeKey(key + QLatin1String("lock"), QLatin1String("qipc_systemlock_")); - semaphoreLock = CreateSemaphore(0, 1, 1, (wchar_t*)safeLockName.utf16()); - - if (semaphoreLock == 0) { - setErrorString(QLatin1String("QSystemLockPrivate::handle")); - return 0; - } - } - - return semaphore; -} - -/*! - \internal - - Cleanup the semaphore - */ -void QSystemLockPrivate::cleanHandle() -{ - if (semaphore && !CloseHandle(semaphore)) - setErrorString(QLatin1String("QSystemLockPrivate::cleanHandle:")); - if (semaphoreLock && !CloseHandle(semaphoreLock)) - setErrorString(QLatin1String("QSystemLockPrivate::cleanHandle:")); - semaphore = 0; - semaphoreLock = 0; -} - -bool QSystemLockPrivate::lock(HANDLE handle, int count) -{ - if (count == 1) { - WaitForSingleObject(handle, INFINITE); - return true; - } - - int i = count; - while (i > 0) { - if (WAIT_OBJECT_0 == WaitForSingleObject(handle, 0)) { - --i; - } else { - // undo what we have done, sleep and then try again later - ReleaseSemaphore(handle, (count - i), 0); - i = count; - ReleaseSemaphore(semaphoreLock, 1, 0); - Sleep(1); - WaitForSingleObject(semaphoreLock, INFINITE); - } - } - return true; -} - -bool QSystemLockPrivate::unlock(HANDLE handle, int count) -{ - if (0 == ReleaseSemaphore(handle, count, 0)) { - setErrorString(QLatin1String("QSystemLockPrivate::unlock")); - return false; - } - return true; -} - -/*! - \internal - - modifySemaphore handles recursive behavior and modifies the semaphore. - */ -bool QSystemLockPrivate::modifySemaphore(QSystemLockPrivate::Operation op, - QSystemLock::LockMode mode) -{ - if (0 == handle()) - return false; - - if ((lockCount == 0 && op == Lock) || (lockCount > 0 && op == Unlock)) { - if (op == Unlock) { - --lockCount; - Q_ASSERT(lockCount >= 0); - if (lockCount > 0) - return true; - } - - int count = (mode == QSystemLock::ReadWrite) ? MAX_LOCKS : 1; - if (op == Lock) { - lock(semaphoreLock, 1); - lock(semaphore, count); - if (count != MAX_LOCKS) unlock(semaphoreLock, 1); - lockedMode = mode; - } else { - if (count == MAX_LOCKS) unlock(semaphoreLock, 1); - unlock(semaphore, count); - } - - } - if (op == Lock) - lockCount++; - - return true; -} - diff --git a/tests/auto/qsharedmemory/src/src.pri b/tests/auto/qsharedmemory/src/src.pri deleted file mode 100644 index 5bc9de6..0000000 --- a/tests/auto/qsharedmemory/src/src.pri +++ /dev/null @@ -1,10 +0,0 @@ -INCLUDEPATH += $$PWD -DEPENDPATH += $$PWD - -SOURCES += $$PWD/qsystemlock.cpp - -HEADERS += $$PWD/qsystemlock.h \ - $$PWD/qsystemlock_p.h - -unix:SOURCES += $$PWD/qsystemlock_unix.cpp -win32:SOURCES += $$PWD/qsystemlock_win.cpp diff --git a/tests/auto/qsharedmemory/test/test.pro b/tests/auto/qsharedmemory/test/test.pro deleted file mode 100644 index c9f4fec..0000000 --- a/tests/auto/qsharedmemory/test/test.pro +++ /dev/null @@ -1,37 +0,0 @@ -load(qttest_p4) - -include(../src/src.pri) -QT -= gui - -DEFINES += QSHAREDMEMORY_DEBUG -DEFINES += QSYSTEMSEMAPHORE_DEBUG - -SOURCES += ../tst_qsharedmemory.cpp -TARGET = ../tst_qsharedmemory - -!wince*:win32 { - CONFIG(debug, debug|release) { - TARGET = ../../debug/tst_qsharedmemory -} else { - TARGET = ../../release/tst_qsharedmemory - } -} - -wince*:{ -requires(contains(QT_CONFIG,script)) -QT += gui script -addFiles.sources = ../lackey/lackey.exe ../lackey/scripts -addFiles.path = lackey -DEPLOYMENT += addFiles -DEFINES += SRCDIR=\\\"\\\" -}else:symbian*{ -requires(contains(QT_CONFIG,script)) -QT += gui script -addFiles.sources = ../lackey/scripts -addFiles.path = /data/qsharedmemorytemp/lackey -addBin.sources = lackey.exe -addBin.path = /sys/bin -DEPLOYMENT += addFiles addBin -} else { -DEFINES += SRCDIR=\\\"$$PWD/../\\\" -} diff --git a/tests/auto/qsharedmemory/tst_qsharedmemory.cpp b/tests/auto/qsharedmemory/tst_qsharedmemory.cpp deleted file mode 100644 index cea75bf..0000000 --- a/tests/auto/qsharedmemory/tst_qsharedmemory.cpp +++ /dev/null @@ -1,778 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include -#include - -//TESTED_CLASS= -//TESTED_FILES= - -#define EXISTING_SHARE "existing" -#define EXISTING_SIZE 1024 - -#ifdef Q_OS_SYMBIAN -#define SRCDIR "c:/data/qsharedmemorytemp/" -#endif -Q_DECLARE_METATYPE(QSharedMemory::SharedMemoryError) -Q_DECLARE_METATYPE(QSharedMemory::AccessMode) - -class tst_QSharedMemory : public QObject -{ - Q_OBJECT - -public: - tst_QSharedMemory(); - virtual ~tst_QSharedMemory(); - -public Q_SLOTS: - void init(); - void cleanup(); - -private slots: - // basics - void constructor(); - void key_data(); - void key(); - void create_data(); - void create(); - void attach_data(); - void attach(); - void lock(); - - // custom edge cases - void removeWhileAttached(); - void emptyMemory(); - void readOnly(); - - // basics all together - void simpleProducerConsumer_data(); - void simpleProducerConsumer(); - void simpleDoubleProducerConsumer(); - - // with threads - void simpleThreadedProducerConsumer_data(); - void simpleThreadedProducerConsumer(); - - // with processes - void simpleProcessProducerConsumer_data(); - void simpleProcessProducerConsumer(); - - // extreme cases - void useTooMuchMemory(); - void attachTooMuch(); - -protected: - int remove(const QString &key); - - QString rememberKey(const QString &key) - { - if (key == EXISTING_SHARE) - return key; - if (!keys.contains(key)) { - keys.append(key); - remove(key); - } - return key; - } - - QStringList keys; - QList jail; - QSharedMemory *existingSharedMemory; -}; - -tst_QSharedMemory::tst_QSharedMemory() : existingSharedMemory(0) -{ -} - -tst_QSharedMemory::~tst_QSharedMemory() -{ -} - -void tst_QSharedMemory::init() -{ - existingSharedMemory = new QSharedMemory(EXISTING_SHARE); - if (!existingSharedMemory->create(EXISTING_SIZE)) { - QVERIFY(existingSharedMemory->error() == QSharedMemory::AlreadyExists); - } -} - -void tst_QSharedMemory::cleanup() -{ - delete existingSharedMemory; - qDeleteAll(jail.begin(), jail.end()); - jail.clear(); - - keys.append(EXISTING_SHARE); - for (int i = 0; i < keys.count(); ++i) { - QSharedMemory sm(keys.at(i)); - if (!sm.create(1024)) { - //if(sm.error() != QSharedMemory::KeyError) - // qWarning() << "test cleanup: remove failed:" << keys.at(i) << sm.error() << sm.errorString(); - sm.attach(); - sm.detach(); - remove(keys.at(i)); - } - } -} - -#ifndef Q_OS_WIN -#include "private/qsharedmemory_p.h" -#include -#include -#include -#endif - -int tst_QSharedMemory::remove(const QString &key) -{ -#ifndef Q_OS_WIN - // On unix the shared memory might exists from a previously failed test - // or segfault, remove it it does - if (key.isEmpty()) - return -1; - - // ftok requires that an actual file exists somewhere - QString fileName = QSharedMemoryPrivate::makePlatformSafeKey(key); - if (!QFile::exists(fileName)) { - //qDebug() << "exits failed"; - return -2; - } - - int unix_key = ftok(fileName.toLatin1().constData(), 'Q'); - if (-1 == unix_key) { - qDebug() << "ftok failed"; - return -3; - } - - int id = shmget(unix_key, 0, 0660); - if (-1 == id) { - qDebug() << "shmget failed"; - return -4; - } - - struct shmid_ds shmid_ds; - if (-1 == shmctl(id, IPC_RMID, &shmid_ds)) { - qDebug() << "shmctl failed"; - return -5; - } - return QFile::remove(fileName); -#else - Q_UNUSED(key); - return 0; -#endif -} - -/*! - Tests the default values - */ -void tst_QSharedMemory::constructor() -{ - QSharedMemory sm; - QCOMPARE(sm.key(), QString()); - QVERIFY(!sm.isAttached()); - QVERIFY(sm.data() == 0); - QCOMPARE(sm.size(), 0); - QCOMPARE(sm.error(), QSharedMemory::NoError); - QVERIFY(sm.errorString() == QString()); -} - -void tst_QSharedMemory::key_data() -{ - QTest::addColumn("constructorKey"); - QTest::addColumn("setKey"); - - QTest::newRow("null, null") << QString() << QString(); - QTest::newRow("null, one") << QString() << QString("one"); - QTest::newRow("one, two") << QString("one") << QString("two"); - QTest::newRow("invalid") << QString("o/e") << QString("t/o"); -} - -/*! - Basic key testing - */ -void tst_QSharedMemory::key() -{ - QFETCH(QString, constructorKey); - QFETCH(QString, setKey); - - QSharedMemory sm(constructorKey); - QCOMPARE(sm.key(), constructorKey); - sm.setKey(setKey); - QCOMPARE(sm.key(), setKey); - QCOMPARE(sm.isAttached(), false); - - QCOMPARE(sm.error(), QSharedMemory::NoError); - QVERIFY(sm.errorString() == QString()); - QVERIFY(sm.data() == 0); - QCOMPARE(sm.size(), 0); - - QCOMPARE(sm.detach(), false); -} - -void tst_QSharedMemory::create_data() -{ - QTest::addColumn("key"); - QTest::addColumn("size"); - QTest::addColumn("canCreate"); - QTest::addColumn("error"); - - QTest::newRow("null key") << QString() << 1024 - << false << QSharedMemory::LockError; - QTest::newRow("-1 size") << QString("negsize") << -1 - << false << QSharedMemory::InvalidSize; - QTest::newRow("nor size") << QString("norsize") << 1024 - << true << QSharedMemory::NoError; - QTest::newRow("already exists") << QString(EXISTING_SHARE) << EXISTING_SIZE - << false << QSharedMemory::AlreadyExists; -} - -/*! - Basic create testing - */ -void tst_QSharedMemory::create() -{ - QFETCH(QString, key); - QFETCH(int, size); - QFETCH(bool, canCreate); - QFETCH(QSharedMemory::SharedMemoryError, error); - - QSharedMemory sm(rememberKey(key)); - QCOMPARE(sm.create(size), canCreate); - if(sm.error() != error) - qDebug() << sm.errorString(); - QCOMPARE(sm.key(), key); - if (canCreate) { - QVERIFY(sm.errorString() == QString()); - QVERIFY(sm.data() != 0); - QVERIFY(sm.size() != 0); - } else { - QVERIFY(sm.data() == 0); - QVERIFY(sm.errorString() != QString()); - } -} - -void tst_QSharedMemory::attach_data() -{ - QTest::addColumn("key"); - QTest::addColumn("exists"); - QTest::addColumn("error"); - - QTest::newRow("null key") << QString() << false << QSharedMemory::LockError; - QTest::newRow("doesn't exists") << QString("doesntexists") << false << QSharedMemory::NotFound; - QTest::newRow("already exists") << QString(EXISTING_SHARE) << true << QSharedMemory::NoError; -} - -/*! - Basic attach/detach testing - */ -void tst_QSharedMemory::attach() -{ - QFETCH(QString, key); - QFETCH(bool, exists); - QFETCH(QSharedMemory::SharedMemoryError, error); -#ifdef Q_OS_HPUX - if (QLatin1String(QTest::currentDataTag()) == QLatin1String("already exists")) { - QSKIP("HPUX doesn't allow for multiple attaches per process", SkipSingle); - } -#endif - QSharedMemory sm(key); - QCOMPARE(sm.attach(), exists); - QCOMPARE(sm.isAttached(), exists); - QCOMPARE(sm.error(), error); - QCOMPARE(sm.key(), key); - if (exists) { - QVERIFY(sm.data() != 0); - QVERIFY(sm.size() != 0); - QCOMPARE(sm.errorString(), QString()); - QVERIFY(sm.detach()); - // Make sure detach doesn't screw up something and we can't re-attach. - QVERIFY(sm.attach()); - QVERIFY(sm.detach()); - QCOMPARE(sm.size(), 0); - QVERIFY(sm.data() == 0); - } else { - QVERIFY(sm.data() == 0); - QVERIFY(sm.size() == 0); - QVERIFY(sm.errorString() != QString()); - QVERIFY(!sm.detach()); - } -} - -void tst_QSharedMemory::lock() -{ - QSharedMemory shm; - QVERIFY(!shm.lock()); - QCOMPARE(shm.error(), QSharedMemory::LockError); - - shm.setKey(QLatin1String("qsharedmemory")); - - QVERIFY(!shm.lock()); - QCOMPARE(shm.error(), QSharedMemory::LockError); - - QVERIFY(shm.create(100)); - QVERIFY(shm.lock()); - QTest::ignoreMessage(QtWarningMsg, "QSharedMemory::lock: already locked"); - QVERIFY(shm.lock()); - // don't lock forever -} - -/*! - Other shared memory are allowed to be attached after we remove, - but new shared memory are not allowed to attach after a remove. - */ -void tst_QSharedMemory::removeWhileAttached() -{ -#ifdef Q_OS_HPUX - QSKIP("HPUX doesn't allow for multiple attaches per process", SkipAll); -#endif - rememberKey("one"); - - // attach 1 - QSharedMemory *smOne = new QSharedMemory(QLatin1String("one")); - QVERIFY(smOne->create(1024)); - QVERIFY(smOne->isAttached()); - - // attach 2 - QSharedMemory *smTwo = new QSharedMemory(QLatin1String("one")); - QVERIFY(smTwo->attach()); - QVERIFY(smTwo->isAttached()); - - // detach 1 and remove, remove one first to catch another error. - delete smOne; - delete smTwo; - - // three shouldn't be able to attach - QSharedMemory smThree(QLatin1String("one")); - QVERIFY(!smThree.attach()); - QCOMPARE(smThree.error(), QSharedMemory::NotFound); -} - -/*! - The memory should be set to 0 after created. - */ -void tst_QSharedMemory::emptyMemory() -{ - QSharedMemory sm(rememberKey(QLatin1String("voidland"))); - int size = 1024; - QVERIFY(sm.create(size, QSharedMemory::ReadOnly)); - char *get = (char*)sm.data(); - char null = 0; - for (int i = 0; i < size; ++i) - QCOMPARE(get[i], null); -} - -/*! - Verify that attach with ReadOnly is actually read only - by writing to data and causing a segfault. -*/ -void tst_QSharedMemory::readOnly() -{ -#ifdef Q_OS_WIN - QSKIP("This test opens a crash dialog on Windows", SkipSingle); -#endif -#if defined (Q_OS_SYMBIAN) - QSKIP("Readonly shared memory is not supported in symbian", SkipAll); -#endif - QString program = "./lackey/lackey"; - QStringList arguments; - rememberKey("readonly_segfault"); - arguments << SRCDIR "lackey/scripts/readonly_segfault.js"; - - // ### on windows disable the popup somehow - QProcess p; - p.start(program, arguments); - p.setProcessChannelMode(QProcess::ForwardedChannels); - p.waitForFinished(); - QCOMPARE(p.error(), QProcess::Crashed); -} - -/*! - Keep making shared memory until the kernel stops us. - */ -void tst_QSharedMemory::useTooMuchMemory() -{ -#ifdef Q_OS_LINUX - bool success = true; - int count = 0; - while (success) { - QString key = QString("maxmemorytest_%1").arg(count++); - QSharedMemory *sm = new QSharedMemory(rememberKey(key)); - QVERIFY(sm); - jail.append(sm); - int size = 32768 * 1024; - success = sm->create(size); - if (!success && sm->error() == QSharedMemory::AlreadyExists) { - // left over from a crash, clean it up - sm->attach(); - sm->detach(); - success = sm->create(size); - } - - if (!success) { - QVERIFY(!sm->isAttached()); - QCOMPARE(sm->key(), key); - QCOMPARE(sm->size(), 0); - QVERIFY(sm->data() == 0); - if (sm->error() != QSharedMemory::OutOfResources) - qDebug() << sm->error() << sm->errorString(); - // ### Linux wont return OutOfResources if there are not enough semaphores to use. - QVERIFY(sm->error() == QSharedMemory::OutOfResources - || sm->error() == QSharedMemory::LockError); - QVERIFY(sm->errorString() != QString()); - QVERIFY(!sm->attach()); - QVERIFY(!sm->detach()); - } else { - QVERIFY(sm->isAttached()); - } - } -#endif -} - -/*! - Create one shared memory (government) and see how many other shared memories (wars) we can - attach before the system runs out of resources. - */ -void tst_QSharedMemory::attachTooMuch() -{ - QSKIP("disabled", SkipAll); -#ifdef Q_OS_HPUX - QSKIP("HPUX doesn't allow for multiple attaches per process", SkipAll); -#endif -#ifdef Q_OS_WINCE - QSKIP("This nearly kills the system itself, so skip for Qt/WinCE", SkipAll); -#endif - QSharedMemory government(rememberKey("government")); - QVERIFY(government.create(1024)); - while (true) { - QSharedMemory *war = new QSharedMemory(government.key()); - QVERIFY(war); - jail.append(war); - if (!war->attach()) { - QVERIFY(!war->isAttached()); - QCOMPARE(war->key(), government.key()); - QCOMPARE(war->size(), 0); - QVERIFY(war->data() == 0); - QCOMPARE(war->error(), QSharedMemory::OutOfResources); - QVERIFY(war->errorString() != QString()); - QVERIFY(!war->detach()); - break; - } else { - QVERIFY(war->isAttached()); - } - } -} - -void tst_QSharedMemory::simpleProducerConsumer_data() -{ - QTest::addColumn("mode"); - - QTest::newRow("readonly") << QSharedMemory::ReadOnly; - QTest::newRow("readwrite") << QSharedMemory::ReadWrite; -} - -/*! - The basic consumer producer that rounds out the basic testing. - If this fails then any muli-threading/process might fail (but be - harder to debug) - - This doesn't require nor test any locking system. - */ -void tst_QSharedMemory::simpleProducerConsumer() -{ -#ifdef Q_OS_HPUX - QSKIP("HPUX doesn't allow for multiple attaches per process", SkipAll); -#endif - QFETCH(QSharedMemory::AccessMode, mode); - - rememberKey(QLatin1String("market")); - QSharedMemory producer(QLatin1String("market")); - QSharedMemory consumer(QLatin1String("market")); - int size = 512; - QVERIFY(producer.create(size)); - QVERIFY(consumer.attach(mode)); - - char *put = (char*)producer.data(); - char *get = (char*)consumer.data(); - // On Windows CE you always have ReadWrite access. Thus - // ViewMapOfFile returns the same pointer - // On Symbian, the address will always be same, as - // write protection of chunks is not currently supported by Symbian -#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) - QVERIFY(put != get); -#endif - for (int i = 0; i < size; ++i) { - put[i] = 'Q'; - QCOMPARE(get[i], 'Q'); - } - QVERIFY(consumer.detach()); -} - -void tst_QSharedMemory::simpleDoubleProducerConsumer() -{ -#ifdef Q_OS_HPUX - QSKIP("HPUX doesn't allow for multiple attaches per process", SkipAll); -#endif - rememberKey(QLatin1String("market")); - QSharedMemory producer(QLatin1String("market")); - int size = 512; - QVERIFY(producer.create(size)); - QVERIFY(producer.detach()); - QVERIFY(producer.create(size)); - - { - QSharedMemory consumer(QLatin1String("market")); - QVERIFY(consumer.attach()); - } -} - -class Consumer : public QThread -{ - -public: - void run() - { - QSharedMemory consumer(QLatin1String("market")); - while (!consumer.attach()) { - if (consumer.error() != QSharedMemory::NotFound) - qDebug() << "consumer: failed to connect" << consumer.error() << consumer.errorString(); - QVERIFY(consumer.error() == QSharedMemory::NotFound || consumer.error() == QSharedMemory::KeyError); - QTest::qWait(1); - } - - char *memory = (char*)consumer.data(); - - int i = 0; - while (true) { - if(!consumer.lock()) - break; - if (memory[0] == 'Q') - memory[0] = ++i; - if (memory[0] == 'E') { - memory[1]++; - QVERIFY(consumer.unlock()); - break; - } - QVERIFY(consumer.unlock()); - QTest::qWait(1); - } - - QVERIFY(consumer.detach()); - } -}; - -class Producer : public QThread -{ - -public: - void run() - { - QSharedMemory producer(QLatin1String("market")); - int size = 1024; - if (!producer.create(size)) { - // left over from a crash... - if (producer.error() == QSharedMemory::AlreadyExists) { - producer.attach(); - producer.detach(); - QVERIFY(producer.create(size)); - } - } - QVERIFY(producer.isAttached()); - char *memory = (char*)producer.data(); - memory[1] = '0'; - QTime timer; - timer.start(); - int i = 0; - while (i < 5 && timer.elapsed() < 5000) { - QVERIFY(producer.lock()); - if (memory[0] == 'Q') { - QVERIFY(producer.unlock()); - QTest::qWait(1); - continue; - } - ++i; - memory[0] = 'Q'; - QVERIFY(producer.unlock()); - QTest::qWait(1); - } - - // tell everyone to quit - QVERIFY(producer.lock()); - memory[0] = 'E'; - QVERIFY(producer.unlock()); - -#if defined(Q_OS_SYMBIAN) - // Sleep a while to ensure that consumers start properly - QTest::qSleep(1000); -#endif - } -private: - -}; - -void tst_QSharedMemory::simpleThreadedProducerConsumer_data() -{ - QTest::addColumn("producerIsThread"); - QTest::addColumn("threads"); - for (int i = 0; i < 5; ++i) { - QTest::newRow("1 consumer, producer is thread") << true << 1; - QTest::newRow("1 consumer, producer is this") << false << 1; - QTest::newRow("5 consumers, producer is thread") << true << 5; - QTest::newRow("5 consumers, producer is this") << false << 5; - } -} - -/*! - The basic producer/consumer, but this time using threads. - */ -void tst_QSharedMemory::simpleThreadedProducerConsumer() -{ - QFETCH(bool, producerIsThread); - QFETCH(int, threads); - rememberKey(QLatin1String("market")); - -#if defined Q_OS_HPUX && defined __ia64 - QSKIP("This test locks up on gravlaks.troll.no", SkipSingle); -#endif - - Producer p; -#if defined(Q_OS_SYMBIAN) - enum - { - /** - * The maximum stack size. - */ - SymbianStackSize = 0x14000 - }; - p.setStackSize(SymbianStackSize); -#endif - if (producerIsThread) - p.start(); - - QList consumers; - for (int i = 0; i < threads; ++i) { - consumers.append(new Consumer()); -#if defined(Q_OS_SYMBIAN) - consumers.last()->setStackSize(SymbianStackSize); -#endif - consumers.last()->start(); - } - - if (!producerIsThread) - p.run(); - - p.wait(5000); - while (!consumers.isEmpty()) { - QVERIFY(consumers.first()->wait(5000)); - delete consumers.takeFirst(); - } -} - -void tst_QSharedMemory::simpleProcessProducerConsumer_data() -{ - QTest::addColumn("processes"); - int tries = 5; - for (int i = 0; i < tries; ++i) { - QTest::newRow("1 process") << 1; - QTest::newRow("5 processes") << 5; - } -} - -/*! - Create external processes that produce and consume. - */ -void tst_QSharedMemory::simpleProcessProducerConsumer() -{ -#if defined (Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) - QSKIP("Cannot launch multiple Qt processes in Symbian emulator", SkipAll); -#endif - QFETCH(int, processes); - - rememberKey("market"); - -#ifndef Q_OS_WINCE - QStringList arguments = QStringList() << SRCDIR "lackey/scripts/producer.js"; -#else - QStringList arguments = QStringList() << QFileInfo(SRCDIR "lackey/scripts/producer.js").absoluteFilePath(); -#endif - QProcess producer; - producer.setProcessChannelMode(QProcess::ForwardedChannels); - producer.start( "./lackey/lackey", arguments); - producer.waitForStarted(); - QVERIFY(producer.error() != QProcess::FailedToStart); - - QList consumers; - unsigned int failedProcesses = 0; - for (int i = 0; i < processes; ++i) { -#ifndef Q_OS_WINCE - QStringList arguments = QStringList() << SRCDIR "lackey/scripts/consumer.js"; -#else - QStringList arguments = QStringList() << QFileInfo(SRCDIR "lackey/scripts/consumer.js").absoluteFilePath(); -#endif - QProcess *p = new QProcess; - p->setProcessChannelMode(QProcess::ForwardedChannels); - p->start("./lackey/lackey", arguments); - - if (p->waitForStarted(2000)) - consumers.append(p); - else - ++failedProcesses; - } - - QVERIFY(producer.waitForFinished(5000)); - - bool consumerFailed = false; - - while (!consumers.isEmpty()) { - QVERIFY(consumers.first()->waitForFinished(3000)); - if (consumers.first()->state() == QProcess::Running || - consumers.first()->exitStatus() != QProcess::NormalExit || - consumers.first()->exitCode() != 0) { - consumerFailed = true; - } - delete consumers.takeFirst(); - } - QCOMPARE(consumerFailed, false); - QCOMPARE(failedProcesses, (unsigned int)(0)); -} - -QTEST_MAIN(tst_QSharedMemory) -#include "tst_qsharedmemory.moc" - diff --git a/tests/auto/qsystemsemaphore/.gitignore b/tests/auto/qsystemsemaphore/.gitignore deleted file mode 100644 index 2b60bfb..0000000 --- a/tests/auto/qsystemsemaphore/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qsystemsemaphore diff --git a/tests/auto/qsystemsemaphore/files.qrc b/tests/auto/qsystemsemaphore/files.qrc deleted file mode 100644 index 7b344ba..0000000 --- a/tests/auto/qsystemsemaphore/files.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - ../qsharedmemory/lackey/scripts/systemsemaphore_acquire.js - ../qsharedmemory/lackey/scripts/systemsemaphore_release.js - ../qsharedmemory/lackey/scripts/systemsemaphore_acquirerelease.js - - diff --git a/tests/auto/qsystemsemaphore/qsystemsemaphore.pro b/tests/auto/qsystemsemaphore/qsystemsemaphore.pro deleted file mode 100644 index a3f4a34..0000000 --- a/tests/auto/qsystemsemaphore/qsystemsemaphore.pro +++ /dev/null @@ -1,4 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = ../qsharedmemory/lackey test - - diff --git a/tests/auto/qsystemsemaphore/test/test.pro b/tests/auto/qsystemsemaphore/test/test.pro deleted file mode 100644 index ed7898c..0000000 --- a/tests/auto/qsystemsemaphore/test/test.pro +++ /dev/null @@ -1,40 +0,0 @@ -CONFIG += qttest_p4 -#QT = core - -include(../../qsharedmemory/src/src.pri) -win32: CONFIG += console - -DEFINES += QSHAREDMEMORY_DEBUG -DEFINES += QSYSTEMSEMAPHORE_DEBUG - -SOURCES += ../tst_qsystemsemaphore.cpp -TARGET = tst_qsystemsemaphore -DESTDIR = ../ -win32 { - CONFIG(debug, debug|release): DESTDIR = ../debug - else: DESTDIR = ../release -} - -RESOURCES += ../files.qrc - -wince*: { -requires(contains(QT_CONFIG,script)) -# this test calls lackey, which then again depends on QtScript. -# let's add it here so that it gets deployed easily -QT += script -lackey.sources = ../../qsharedmemory/lackey/lackey.exe -lackey.path = ../qsharedmemory/lackey - -DEPLOYMENT += lackey -} - -symbian: { -requires(contains(QT_CONFIG,script)) -# this test calls lackey, which then again depends on QtScript. -# let's add it here so that it gets deployed easily -QT += script - -lackey.sources = ../../qsharedmemory/lackey/lackey.exe -lackey.path = /sys/bin -DEPLOYMENT += lackey -} diff --git a/tests/auto/qsystemsemaphore/tst_qsystemsemaphore.cpp b/tests/auto/qsystemsemaphore/tst_qsystemsemaphore.cpp deleted file mode 100644 index bf4efdc..0000000 --- a/tests/auto/qsystemsemaphore/tst_qsystemsemaphore.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include -#include -//TESTED_CLASS= -//TESTED_FILES= - -#define EXISTING_SHARE "existing" -#define LACKYLOC "../qsharedmemory/lackey" -#define LACKYWAITTIME 10000 - -class tst_QSystemSemaphore : public QObject -{ - Q_OBJECT - -public: - tst_QSystemSemaphore(); - virtual ~tst_QSystemSemaphore(); - -public Q_SLOTS: - void init(); - void cleanup(); - -private slots: - void key_data(); - void key(); - - void basicacquire(); - void complexacquire(); - - void basicProcesses(); - - void processes_data(); - void processes(); - - void undo(); - void initialValue(); - -private: - QSystemSemaphore *existingLock; - - QString makeFile(const QString &resource) - { - QFile memory(resource); - if (!memory.open(QIODevice::ReadOnly)) { - qDebug() << "error reading resource" << resource; - return QString(); - } - QTemporaryFile *file = new QTemporaryFile; - file->open(); - file->write(memory.readAll()); - tempFiles.append(file); - file->flush(); -#ifdef Q_OS_WINCE - // flush does not flush to disk on Windows CE. It flushes it into its application - // cache. Thus we need to close the file to be able that other processes(lackey) can read it - QString fileName = file->fileName(); - file->close(); - return fileName; -#endif - return file->fileName(); - } - - QString acquire_js() { return makeFile(":/systemsemaphore_acquire.js"); } - QString release_js() { return makeFile(":/systemsemaphore_release.js"); } - QString acquirerelease_js() { return makeFile(":/systemsemaphore_acquirerelease.js"); } - QList tempFiles; -}; - -tst_QSystemSemaphore::tst_QSystemSemaphore() -{ - if (!QFile::exists(LACKYLOC "/lackey")) - qWarning() << "lackey executable doesn't exists!"; -} - -tst_QSystemSemaphore::~tst_QSystemSemaphore() -{ - qDeleteAll(tempFiles); -} - -void tst_QSystemSemaphore::init() -{ - existingLock = new QSystemSemaphore(EXISTING_SHARE, 1, QSystemSemaphore::Create); -} - -void tst_QSystemSemaphore::cleanup() -{ - delete existingLock; -} - -void tst_QSystemSemaphore::key_data() -{ - QTest::addColumn("constructorKey"); - QTest::addColumn("setKey"); - - QTest::newRow("null, null") << QString() << QString(); - QTest::newRow("null, one") << QString() << QString("one"); - QTest::newRow("one, two") << QString("one") << QString("two"); -} - -/*! - Basic key testing - */ -void tst_QSystemSemaphore::key() -{ - QFETCH(QString, constructorKey); - QFETCH(QString, setKey); - - QSystemSemaphore sem(constructorKey); - QCOMPARE(sem.key(), constructorKey); - QCOMPARE(sem.error(), QSystemSemaphore::NoError); - QCOMPARE(sem.errorString(), QString()); - - sem.setKey(setKey); - QCOMPARE(sem.key(), setKey); - QCOMPARE(sem.error(), QSystemSemaphore::NoError); - QCOMPARE(sem.errorString(), QString()); -} - -void tst_QSystemSemaphore::basicacquire() -{ - QSystemSemaphore sem("QSystemSemaphore_basicacquire", 1, QSystemSemaphore::Create); - QVERIFY(sem.acquire()); - QCOMPARE(sem.error(), QSystemSemaphore::NoError); - QVERIFY(sem.release()); - QCOMPARE(sem.error(), QSystemSemaphore::NoError); - QCOMPARE(sem.errorString(), QString()); -} - -void tst_QSystemSemaphore::complexacquire() -{ - QSystemSemaphore sem("QSystemSemaphore_complexacquire", 2, QSystemSemaphore::Create); - QVERIFY(sem.acquire()); - QVERIFY(sem.release()); - QVERIFY(sem.acquire()); - QVERIFY(sem.release()); - QVERIFY(sem.acquire()); - QVERIFY(sem.acquire()); - QVERIFY(sem.release()); - QVERIFY(sem.release()); - QCOMPARE(sem.error(), QSystemSemaphore::NoError); - QCOMPARE(sem.errorString(), QString()); -} - -void tst_QSystemSemaphore::basicProcesses() -{ -#if defined (Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) - QSKIP("Cannot launch multiple Qt processes in Symbian emulator", SkipAll); -#endif - QSystemSemaphore sem("store", 0, QSystemSemaphore::Create); - - QStringList acquireArguments = QStringList() << acquire_js(); - QStringList releaseArguments = QStringList() << release_js(); - QProcess acquire; - acquire.setProcessChannelMode(QProcess::ForwardedChannels); - - QProcess release; - release.setProcessChannelMode(QProcess::ForwardedChannels); - - acquire.start(LACKYLOC "/lackey", acquireArguments); - acquire.waitForFinished(LACKYWAITTIME); - QVERIFY(acquire.state() == QProcess::Running); - acquire.kill(); - release.start(LACKYLOC "/lackey", releaseArguments); - acquire.waitForFinished(LACKYWAITTIME); - release.waitForFinished(LACKYWAITTIME); - QVERIFY(acquire.state() == QProcess::NotRunning); -} - -void tst_QSystemSemaphore::processes_data() -{ - QTest::addColumn("processes"); - for (int i = 0; i < 5; ++i) { - QTest::newRow("1 process") << 1; - QTest::newRow("3 process") << 3; - QTest::newRow("10 process") << 10; - } -} - -void tst_QSystemSemaphore::processes() -{ -#if defined (Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) - QSKIP("Cannot launch multiple Qt processes in Symbian emulator", SkipAll); -#endif - QSystemSemaphore sem("store", 1, QSystemSemaphore::Create); - - QFETCH(int, processes); - QStringList scripts; - for (int i = 0; i < processes; ++i) - scripts.append(acquirerelease_js()); - - QList consumers; - for (int i = 0; i < scripts.count(); ++i) { - QStringList arguments = QStringList() << scripts.at(i); - QProcess *p = new QProcess; - p->setProcessChannelMode(QProcess::ForwardedChannels); - consumers.append(p); - p->start(LACKYLOC "/lackey", arguments); - } - - while (!consumers.isEmpty()) { - consumers.first()->waitForFinished(); - QCOMPARE(consumers.first()->exitStatus(), QProcess::NormalExit); - QCOMPARE(consumers.first()->exitCode(), 0); - delete consumers.takeFirst(); - } -} - -void tst_QSystemSemaphore::undo() -{ -#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) - QSKIP("This test only checks a unix behavior", SkipSingle); -#endif - - QSystemSemaphore sem("store", 1, QSystemSemaphore::Create); - - QStringList acquireArguments = QStringList() << acquire_js(); - QProcess acquire; - acquire.setProcessChannelMode(QProcess::ForwardedChannels); - acquire.start(LACKYLOC "/lackey", acquireArguments); - acquire.waitForFinished(LACKYWAITTIME); - QVERIFY(acquire.state()== QProcess::NotRunning); - - // At process exit the kernel should auto undo - - acquire.start(LACKYLOC "/lackey", acquireArguments); - acquire.waitForFinished(LACKYWAITTIME); - QVERIFY(acquire.state()== QProcess::NotRunning); -} - -void tst_QSystemSemaphore::initialValue() -{ -#if defined (Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) - QSKIP("Cannot launch multiple Qt processes in Symbian emulator", SkipAll); -#endif - QSystemSemaphore sem("store", 1, QSystemSemaphore::Create); - - QStringList acquireArguments = QStringList() << acquire_js(); - QStringList releaseArguments = QStringList() << release_js(); - QProcess acquire; - acquire.setProcessChannelMode(QProcess::ForwardedChannels); - - QProcess release; - release.setProcessChannelMode(QProcess::ForwardedChannels); - - acquire.start(LACKYLOC "/lackey", acquireArguments); - acquire.waitForFinished(LACKYWAITTIME); - QVERIFY(acquire.state()== QProcess::NotRunning); - - acquire.start(LACKYLOC "/lackey", acquireArguments << "2"); - acquire.waitForFinished(LACKYWAITTIME); - QVERIFY(acquire.state()== QProcess::Running); - acquire.kill(); - - release.start(LACKYLOC "/lackey", releaseArguments); - acquire.waitForFinished(LACKYWAITTIME); - release.waitForFinished(LACKYWAITTIME); - QVERIFY(acquire.state()== QProcess::NotRunning); -} -QTEST_MAIN(tst_QSystemSemaphore) -#include "tst_qsystemsemaphore.moc" - diff --git a/tests/auto/qtipc/lackey/lackey.pro b/tests/auto/qtipc/lackey/lackey.pro new file mode 100644 index 0000000..3912312 --- /dev/null +++ b/tests/auto/qtipc/lackey/lackey.pro @@ -0,0 +1,20 @@ +include(../qsharedmemory/src/src.pri) + +QT = core script + +CONFIG += qtestlib + +DESTDIR = ./ + +win32: CONFIG += console +mac:CONFIG -= app_bundle + +requires(contains(QT_CONFIG,script)) + +DEFINES += QSHAREDMEMORY_DEBUG +DEFINES += QSYSTEMSEMAPHORE_DEBUG + +SOURCES += main.cpp +TARGET = lackey + + diff --git a/tests/auto/qtipc/lackey/main.cpp b/tests/auto/qtipc/lackey/main.cpp new file mode 100644 index 0000000..fef8d22 --- /dev/null +++ b/tests/auto/qtipc/lackey/main.cpp @@ -0,0 +1,370 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +class ScriptSystemSemaphore : public QObject +{ + Q_OBJECT + +public: + ScriptSystemSemaphore(QObject *parent = 0) : QObject(parent), ss(QString()) + { + } + +public slots: + bool acquire() + { + return ss.acquire(); + }; + + bool release(int n = 1) + { + return ss.release(n); + }; + + void setKey(const QString &key, int n = 0) + { + ss.setKey(key, n); + }; + + QString key() const + { + return ss.key(); + } + +private: + QSystemSemaphore ss; +}; + +class ScriptSystemLock : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString key WRITE setKey READ key) + +public: + ScriptSystemLock(QObject *parent = 0) : QObject(parent), sl(QString()) + { + } + +public slots: + + bool lockReadOnly() + { + return sl.lock(QSystemLock::ReadOnly); + } + + bool lock() + { + return sl.lock(); + }; + + bool unlock() + { + return sl.unlock(); + }; + + void setKey(const QString &key) + { + sl.setKey(key); + }; + + QString key() const + { + return sl.key(); + } + +private: + QSystemLock sl; +}; + +class ScriptSharedMemory : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool attached READ isAttached) + Q_PROPERTY(QString key WRITE setKey READ key) + +public: + enum SharedMemoryError + { + NoError = 0, + PermissionDenied = 1, + InvalidSize = 2, + KeyError = 3, + AlreadyExists = 4, + NotFound = 5, + LockError = 6, + OutOfResources = 7, + UnknownError = 8 + }; + + ScriptSharedMemory(QObject *parent = 0) : QObject(parent) + { + } + +public slots: + void sleep(int x) const + { + QTest::qSleep(x); + } + + bool create(int size) + { + return sm.create(size); + }; + + bool createReadOnly(int size) + { + return sm.create(size, QSharedMemory::ReadOnly); + }; + + int size() const + { + return sm.size(); + }; + + bool attach() + { + return sm.attach(); + }; + + bool attachReadOnly() + { + return sm.attach(QSharedMemory::ReadOnly); + }; + + bool isAttached() const + { + return sm.isAttached(); + }; + + bool detach() + { + return sm.detach(); + }; + + int error() const + { + return (int)sm.error(); + }; + + QString errorString() const + { + return sm.errorString(); + }; + + void set(int i, QChar value) + { + ((char*)sm.data())[i] = value.toLatin1(); + } + + QString get(int i) + { + return QChar::fromLatin1(((char*)sm.data())[i]); + } + + char *data() const + { + return (char*)sm.data(); + }; + + void setKey(const QString &key) + { + sm.setKey(key); + }; + + QString key() const + { + return sm.key(); + } + + bool lock() + { + return sm.lock(); + } + + bool unlock() + { + return sm.unlock(); + } + +private: + QSharedMemory sm; +}; + +QT_BEGIN_NAMESPACE +Q_SCRIPT_DECLARE_QMETAOBJECT(ScriptSharedMemory, QObject*); +Q_SCRIPT_DECLARE_QMETAOBJECT(ScriptSystemLock, QObject*); +Q_SCRIPT_DECLARE_QMETAOBJECT(ScriptSystemSemaphore, QObject*); +QT_END_NAMESPACE + +static void interactive(QScriptEngine &eng) +{ +#ifdef Q_OS_WINCE + fprintf(stderr, "Interactive mode not supported on Windows CE\n"); + return; +#endif + QTextStream qin(stdin, QFile::ReadOnly); + + const char *qscript_prompt = "qs> "; + const char *dot_prompt = ".... "; + const char *prompt = qscript_prompt; + + QString code; + + forever { + QString line; + + printf("%s", prompt); + fflush(stdout); + + line = qin.readLine(); + if (line.isNull()) + break; + + code += line; + code += QLatin1Char('\n'); + + if (line.trimmed().isEmpty()) { + continue; + + } else if (! eng.canEvaluate(code)) { + prompt = dot_prompt; + + } else { + QScriptValue result = eng.evaluate(code); + code.clear(); + prompt = qscript_prompt; + if (!result.isUndefined()) + fprintf(stderr, "%s\n", qPrintable(result.toString())); + } + } +} + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + QScriptEngine eng; + QScriptValue globalObject = eng.globalObject(); + + QScriptValue sm = qScriptValueFromQMetaObject(&eng); + eng.globalObject().setProperty("ScriptSharedMemory", sm); + + QScriptValue sl = qScriptValueFromQMetaObject(&eng); + eng.globalObject().setProperty("ScriptSystemLock", sl); + + QScriptValue ss = qScriptValueFromQMetaObject(&eng); + eng.globalObject().setProperty("ScriptSystemSemaphore", ss); + + + if (! *++argv) { + interactive(eng); + return EXIT_SUCCESS; + } + + QStringList arguments = app.arguments(); + arguments.takeFirst(); + + while (!arguments.isEmpty()) { + QString fn = arguments.takeFirst(); + + if (fn == QLatin1String("-i")) { + interactive(eng); + break; + } + + QString contents; + + if (fn == QLatin1String("-")) { + QTextStream stream(stdin, QFile::ReadOnly); + contents = stream.readAll(); + } else { + QFile file(fn); + if (!file.exists()) { + fprintf(stderr, "%s doesn't exists\n", qPrintable(fn)); + return EXIT_FAILURE; + } + if (file.open(QFile::ReadOnly)) { + QTextStream stream(&file); + contents = stream.readAll(); + file.close(); + } + } + + if (contents.isEmpty()) + continue; + + if (contents[0] == '#') { + contents.prepend("//"); + QScriptValue args = eng.newArray(); + args.setProperty("0", QScriptValue(&eng, fn)); + int i = 1; + while (!arguments.isEmpty()) + args.setProperty(i++, QScriptValue(&eng, arguments.takeFirst())); + eng.currentContext()->activationObject().setProperty("args", args); + } + QScriptValue r = eng.evaluate(contents); + if (eng.hasUncaughtException()) { + int line = eng.uncaughtExceptionLineNumber(); + fprintf(stderr, "%d: %s\n\t%s\n\n", line, qPrintable(fn), qPrintable(r.toString())); + return EXIT_FAILURE; + } + if (r.isNumber()) + return r.toInt32(); + } + + return EXIT_SUCCESS; +} + +#include "main.moc" diff --git a/tests/auto/qtipc/lackey/scripts/consumer.js b/tests/auto/qtipc/lackey/scripts/consumer.js new file mode 100644 index 0000000..4d12dca --- /dev/null +++ b/tests/auto/qtipc/lackey/scripts/consumer.js @@ -0,0 +1,41 @@ +function QVERIFY(x, debugInfo) { + if (!(x)) { + print(debugInfo); + throw(debugInfo); + } +} + +var consumer = new ScriptSharedMemory; +consumer.setKey("market"); + +//print("consumer starting"); +var tries = 0;; +while(!consumer.attach()) { + if (tries == 5000) { + var message = "consumer exiting, waiting too long"; + print(message); + throw(message); + } + ++tries; + consumer.sleep(1); +} +//print("consumer attached"); + + +var i = 0; +while(true) { + QVERIFY(consumer.lock(), "lock"); + if (consumer.get(0) == 'Q') { + consumer.set(0, ++i); + //print ("consumer sets" + i); + } + if (consumer.get(0) == 'E') { + QVERIFY(consumer.unlock(), "unlock"); + break; + } + QVERIFY(consumer.unlock(), "unlock"); + consumer.sleep(10); +} + +//print("consumer detaching"); +QVERIFY(consumer.detach()); diff --git a/tests/auto/qtipc/lackey/scripts/producer.js b/tests/auto/qtipc/lackey/scripts/producer.js new file mode 100644 index 0000000..e02cd8b --- /dev/null +++ b/tests/auto/qtipc/lackey/scripts/producer.js @@ -0,0 +1,44 @@ +function QVERIFY(x, debugInfo) { + if (!(x)) { + print(debugInfo); + throw(debugInfo); + } +} + +var producer = new ScriptSharedMemory; +producer.setKey("market"); + +var size = 1024; +if (!producer.create(size)) { + QVERIFY(producer.error() == 4, "create"); + QVERIFY(producer.attach()); +} +//print ("producer created and attached"); + +QVERIFY(producer.lock()); +producer.set(0, 'Q'); +QVERIFY(producer.unlock()); + +var i = 0; +while(i < 5) { + QVERIFY(producer.lock(), "lock"); + if (producer.get(0) == 'Q') { + QVERIFY(producer.unlock(), "unlock"); + producer.sleep(1); + continue; + } + //print("producer: " + i); + ++i; + producer.set(0, 'Q'); + QVERIFY(producer.unlock(), "unlock"); + producer.sleep(1); +} +QVERIFY(producer.lock()); +producer.set(0, 'E'); +QVERIFY(producer.unlock()); + +//print ("producer done"); + +// Sleep for a bit to let all consumers start, otherwise they will get stuck in the attach loop, +// because at least in Symbian the shared memory will be destroyed if there are no active handles to it. +producer.sleep(3000); \ No newline at end of file diff --git a/tests/auto/qtipc/lackey/scripts/readonly_segfault.js b/tests/auto/qtipc/lackey/scripts/readonly_segfault.js new file mode 100644 index 0000000..3eaf789 --- /dev/null +++ b/tests/auto/qtipc/lackey/scripts/readonly_segfault.js @@ -0,0 +1,4 @@ +var sm = new ScriptSharedMemory; +sm.setKey("readonly_segfault"); +sm.createReadOnly(1024); +var data = sm.set(0, "a"); diff --git a/tests/auto/qtipc/lackey/scripts/systemlock_read.js b/tests/auto/qtipc/lackey/scripts/systemlock_read.js new file mode 100644 index 0000000..1048bc7 --- /dev/null +++ b/tests/auto/qtipc/lackey/scripts/systemlock_read.js @@ -0,0 +1,11 @@ +function QVERIFY(x, debugInfo) { + if (!(x)) { + print(debugInfo); + throw(debugInfo); + } +} + +var lock = new ScriptSystemLock; +lock.setKey("market"); +QVERIFY(lock.lockReadOnly()); +QVERIFY(lock.unlock()); \ No newline at end of file diff --git a/tests/auto/qtipc/lackey/scripts/systemlock_readwrite.js b/tests/auto/qtipc/lackey/scripts/systemlock_readwrite.js new file mode 100644 index 0000000..fc6367f --- /dev/null +++ b/tests/auto/qtipc/lackey/scripts/systemlock_readwrite.js @@ -0,0 +1,11 @@ +function QVERIFY(x, debugInfo) { + if (!(x)) { + print(debugInfo); + throw(debugInfo); + } +} + +var lock = new ScriptSystemLock; +lock.setKey("market"); +QVERIFY(lock.lock()); +QVERIFY(lock.unlock()); diff --git a/tests/auto/qtipc/lackey/scripts/systemsemaphore_acquire.js b/tests/auto/qtipc/lackey/scripts/systemsemaphore_acquire.js new file mode 100644 index 0000000..5cff429 --- /dev/null +++ b/tests/auto/qtipc/lackey/scripts/systemsemaphore_acquire.js @@ -0,0 +1,18 @@ +#/bin/qscript +function QVERIFY(x, debugInfo) { + if (!(x)) { + print(debugInfo); + throw(debugInfo); + } +} + + +var sem = new ScriptSystemSemaphore; +sem.setKey("store"); + +var count = Number(args[1]); +if (isNaN(count)) + count = 1; +for (var i = 0; i < count; ++i) + QVERIFY(sem.acquire()); +print("done aquiring"); diff --git a/tests/auto/qtipc/lackey/scripts/systemsemaphore_acquirerelease.js b/tests/auto/qtipc/lackey/scripts/systemsemaphore_acquirerelease.js new file mode 100644 index 0000000..cedde3f --- /dev/null +++ b/tests/auto/qtipc/lackey/scripts/systemsemaphore_acquirerelease.js @@ -0,0 +1,11 @@ +function QVERIFY(x, debugInfo) { + if (!(x)) { + print(debugInfo); + throw(debugInfo); + } +} + +var lock = new ScriptSystemSemaphore; +lock.setKey("store"); +QVERIFY(lock.acquire()); +QVERIFY(lock.release()); diff --git a/tests/auto/qtipc/lackey/scripts/systemsemaphore_release.js b/tests/auto/qtipc/lackey/scripts/systemsemaphore_release.js new file mode 100644 index 0000000..c805e0f --- /dev/null +++ b/tests/auto/qtipc/lackey/scripts/systemsemaphore_release.js @@ -0,0 +1,11 @@ +function QVERIFY(x, debugInfo) { + if (!(x)) { + print(debugInfo); + throw(debugInfo); + } +} + +var sem = new ScriptSystemSemaphore; +sem.setKey("store"); +QVERIFY(sem.release()); +print ("done releasing"); diff --git a/tests/auto/qtipc/qsharedmemory/.gitignore b/tests/auto/qtipc/qsharedmemory/.gitignore new file mode 100644 index 0000000..03ddcf2 --- /dev/null +++ b/tests/auto/qtipc/qsharedmemory/.gitignore @@ -0,0 +1,3 @@ +tst_qsharedmemory +lackey/lackey.exe +qsystemlock/tst_qsystemlock.exe diff --git a/tests/auto/qtipc/qsharedmemory/qsharedmemory.pro b/tests/auto/qtipc/qsharedmemory/qsharedmemory.pro new file mode 100644 index 0000000..9fef8e4 --- /dev/null +++ b/tests/auto/qtipc/qsharedmemory/qsharedmemory.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +SUBDIRS = test qsystemlock + + diff --git a/tests/auto/qtipc/qsharedmemory/qsystemlock/qsystemlock.pro b/tests/auto/qtipc/qsharedmemory/qsystemlock/qsystemlock.pro new file mode 100644 index 0000000..e232443 --- /dev/null +++ b/tests/auto/qtipc/qsharedmemory/qsystemlock/qsystemlock.pro @@ -0,0 +1,22 @@ +CONFIG += qttest_p4 +#QT = core + +include(../src/src.pri) +win32: CONFIG += console +mac:CONFIG -= app_bundle + +wince* { + DEFINES += SRCDIR=\\\"\\\" +} else:!symbian { + DEFINES += SRCDIR=\\\"$$PWD\\\" +} + +DESTDIR = ./ + +DEFINES += QSHAREDMEMORY_DEBUG +DEFINES += QSYSTEMSEMAPHORE_DEBUG + +SOURCES += tst_qsystemlock.cpp +TARGET = tst_qsystemlock + + diff --git a/tests/auto/qtipc/qsharedmemory/qsystemlock/tst_qsystemlock.cpp b/tests/auto/qtipc/qsharedmemory/qsystemlock/tst_qsystemlock.cpp new file mode 100644 index 0000000..ea906b7 --- /dev/null +++ b/tests/auto/qtipc/qsharedmemory/qsystemlock/tst_qsystemlock.cpp @@ -0,0 +1,239 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include + +//TESTED_CLASS= +//TESTED_FILES= + +#ifdef Q_OS_SYMBIAN +// In Symbian OS test data is located in applications private dir +// And underlying Open C have application private dir in default search path +#define SRCDIR "" +#endif + + +#define EXISTING_SHARE "existing" + +class tst_QSystemLock : public QObject +{ + Q_OBJECT + +public: + tst_QSystemLock(); + virtual ~tst_QSystemLock(); + +public Q_SLOTS: + void init(); + void cleanup(); + +private slots: + void key_data(); + void key(); + + void basicLock(); + void complexLock(); + void lockModes(); + void sucessive(); + void processes_data(); + void processes(); + +private: + QSystemLock *existingLock; + +}; + +tst_QSystemLock::tst_QSystemLock() +{ +} + +tst_QSystemLock::~tst_QSystemLock() +{ +} + +void tst_QSystemLock::init() +{ + existingLock = new QSystemLock(EXISTING_SHARE); +} + +void tst_QSystemLock::cleanup() +{ + delete existingLock; +} + +void tst_QSystemLock::key_data() +{ + QTest::addColumn("constructorKey"); + QTest::addColumn("setKey"); + + QTest::newRow("null, null") << QString() << QString(); + QTest::newRow("null, one") << QString() << QString("one"); + QTest::newRow("one, two") << QString("one") << QString("two"); +} + +/*! + Basic key testing + */ +void tst_QSystemLock::key() +{ + QFETCH(QString, constructorKey); + QFETCH(QString, setKey); + + QSystemLock sl(constructorKey); + QCOMPARE(sl.key(), constructorKey); + sl.setKey(setKey); + QCOMPARE(sl.key(), setKey); +} + +void tst_QSystemLock::basicLock() +{ + QSystemLock lock("foo"); + QVERIFY(lock.lock()); + QVERIFY(lock.unlock()); +} + +void tst_QSystemLock::complexLock() +{ + QSystemLock lock("foo"); + QVERIFY(lock.lock(QSystemLock::ReadOnly)); + QVERIFY(lock.unlock()); + + QVERIFY(lock.lock(QSystemLock::ReadWrite)); + QVERIFY(lock.unlock()); + + QVERIFY(lock.lock(QSystemLock::ReadOnly)); + QVERIFY(lock.lock(QSystemLock::ReadOnly)); + QVERIFY(lock.unlock()); + QVERIFY(lock.unlock()); +} + +void tst_QSystemLock::lockModes() +{ + QSystemLock reader1("library"); + QSystemLock reader2("library"); + + QSystemLock librarian("library"); + QVERIFY(reader1.lock(QSystemLock::ReadOnly)); + QVERIFY(reader2.lock(QSystemLock::ReadOnly)); + QVERIFY(reader1.unlock()); + QVERIFY(reader2.unlock()); + QVERIFY(librarian.lock(QSystemLock::ReadWrite)); + QVERIFY(librarian.unlock()); +} + +void tst_QSystemLock::sucessive() +{ + QSystemLock lock("library"); + QVERIFY(lock.lock(QSystemLock::ReadOnly)); + QVERIFY(lock.lock(QSystemLock::ReadOnly)); + QVERIFY(lock.lock(QSystemLock::ReadOnly)); + QVERIFY(lock.lock(QSystemLock::ReadOnly)); + QVERIFY(lock.lock(QSystemLock::ReadOnly)); + QVERIFY(lock.unlock()); + QVERIFY(lock.unlock()); + QVERIFY(lock.unlock()); + QVERIFY(lock.unlock()); + QVERIFY(lock.unlock()); + QVERIFY(!lock.unlock()); +} + +void tst_QSystemLock::processes_data() +{ + QTest::addColumn("readOnly"); + QTest::addColumn("readWrite"); + for (int i = 0; i < 5; ++i) { + QTest::newRow("1/0 process") << 1 << 0; + QTest::newRow("0/1 process") << 0 << 1; + QTest::newRow("0/4 process") << 0 << 4; + QTest::newRow("1/1 process") << 1 << 1; + QTest::newRow("10/1 process") << 10 << 1; + QTest::newRow("1/10 process") << 1 << 10; + QTest::newRow("10/10 processes") << 10 << 10; + } +} + +/*! + Create external processes + */ +void tst_QSystemLock::processes() +{ + QSKIP("This test takes about 15 minutes and needs to be trimmed down before we can re-enable it", SkipAll); + QFETCH(int, readOnly); + QFETCH(int, readWrite); + + QStringList scripts; + for (int i = 0; i < readOnly; ++i) + scripts.append(QFileInfo(SRCDIR "/../lackey/scripts/systemlock_read.js").absoluteFilePath() ); + for (int i = 0; i < readWrite; ++i) + scripts.append(QFileInfo(SRCDIR "/../lackey/scripts/systemlock_readwrite.js").absoluteFilePath()); + + QList consumers; + unsigned int failedProcesses = 0; + for (int i = 0; i < scripts.count(); ++i) { + + QStringList arguments = QStringList() << scripts.at(i); + QProcess *p = new QProcess; + p->setProcessChannelMode(QProcess::ForwardedChannels); + + p->start("../lackey/lackey", arguments); + // test, if the process could be started. + + if (p->waitForStarted(2000)) + consumers.append(p); + else + ++failedProcesses; + } + + while (!consumers.isEmpty()) { + consumers.first()->waitForFinished(3000); + consumers.first()->kill(); + QCOMPARE(consumers.first()->exitStatus(), QProcess::NormalExit); + QCOMPARE(consumers.first()->exitCode(), 0); + delete consumers.takeFirst(); + } + QCOMPARE(failedProcesses, (unsigned int)(0)); +} + +QTEST_MAIN(tst_QSystemLock) +#include "tst_qsystemlock.moc" + diff --git a/tests/auto/qtipc/qsharedmemory/src/qsystemlock.cpp b/tests/auto/qtipc/qsharedmemory/src/qsystemlock.cpp new file mode 100644 index 0000000..4ead748 --- /dev/null +++ b/tests/auto/qtipc/qsharedmemory/src/qsystemlock.cpp @@ -0,0 +1,246 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qsystemlock.h" +#include "qsystemlock_p.h" + +#include + +/*! \class QSystemLocker + + \brief The QSystemLocker class is a convenience class that simplifies + locking and unlocking system locks. + + The purpose of QSystemLocker is to simplify QSystemLock locking and + unlocking. Locking and unlocking a QSystemLock in complex functions and + statements or in exception handling code is error-prone and difficult to + debug. QSystemLocker can be used in such situations to ensure that the + state of the locks is always well-defined. + + QSystemLocker should be created within a function where a QSystemLock needs + to be locked. The system lock is locked when QSystemLocker is created. If + locked, the system lock will be unlocked when the QSystemLocker is + destroyed. QSystemLocker can be unlocked with unlock() and relocked with + relock(). + + \sa QSystemLock + */ + +/*! \fn QSystemLocker::QSystemLocker() + + Constructs a QSystemLocker and locks \a lock. The \a lock will be + unlocked when the QSystemLocker is destroyed. If lock is zero, + QSystemLocker does nothing. + + \sa QSystemLock::lock() + */ + +/*! \fn QSystemLocker::~QSystemLocker() + + Destroys the QSystemLocker and unlocks it if it was + locked in the constructor. + + \sa QSystemLock::unlock() + */ + +/*! \fn QSystemLocker::systemLock() + + Returns a pointer to the lock that was locked in the constructor. + */ + +/*! \fn QSystemLocker::relock() + + Relocks an unlocked locker. + + \sa unlock() + */ + +/*! \fn QSystemLocker::unlock() + + Unlocks this locker. You can use relock() to lock it again. + It does not need to be locked when destroyed. + + \sa relock() + */ + +/*! \class QSystemLock + + \brief The QSystemLock class provides a system wide lock + that can be used between threads or processes. + + The purpose of a QSystemLocker is to protect an object that can be + accessed by multiple threads or processes such as shared memory or a file. + + For example, say there is a method which prints a message to a log file: + + void log(const QString &logText) + { + QSystemLock systemLock(QLatin1String("logfile")); + systemLock.lock(); + QFile file(QDir::temp() + QLatin1String("/log")); + if (file.open(QIODevice::Append)) { + QTextStream out(&file); + out << logText; + } + systemLock.unlock(); + } + + If this is called from two seperate processes the resulting log file is + guaranteed to contain both lines. + + When you call lock(), other threads or processes that try to call lock() + with the same key will block until the thread or process that got the lock + calls unlock(). + + A non-blocking alternative to lock() is tryLock(). + */ + +/*! + Constructs a new system lock with \a key. The lock is created in an + unlocked state. + + \sa lock(), key(). + */ +QSystemLock::QSystemLock(const QString &key) +{ + d = new QSystemLockPrivate; + setKey(key); +} + +/*! + Destroys a system lock. + + warning: This will not unlock the system lock if it has been locked. +*/ +QSystemLock::~QSystemLock() +{ + d->cleanHandle(); + delete d; +} + +/*! + Sets a new key to this system lock. + + \sa key() + */ +void QSystemLock::setKey(const QString &key) +{ + if (key == d->key) + return; + d->cleanHandle(); + d->lockCount = 0; + d->key = key; + // cache the file name so it doesn't have to be generated all the time. + d->fileName = d->makeKeyFileName(); + d->error = QSystemLock::NoError; + d->errorString = QString(); + d->handle(); +} + +/*! + Returns the key assigned to this system lock + + \sa setKey() + */ +QString QSystemLock::key() const +{ + return d->key; +} + +/*! + Locks the system lock. Lock \a mode can either be ReadOnly or ReadWrite. + If a mode is ReadOnly, attempts by other processes to obtain + ReadOnly locks will succeed, and ReadWrite attempts will block until + all of the ReadOnly locks are unlocked. If locked as ReadWrite, all + other attempts to lock will block until the lock is unlocked. A given + QSystemLock can be locked multiple times without blocking, and will + only be unlocked after a corresponding number of unlock() + calls are made. Returns true on success; otherwise returns false. + + \sa unlock(), tryLock() + */ +bool QSystemLock::lock(LockMode mode) +{ + if (d->lockCount > 0 && mode == ReadOnly && d->lockedMode == ReadWrite) { + qWarning() << "QSystemLock::lock readwrite lock on top of readonly lock."; + return false; + } + return d->modifySemaphore(QSystemLockPrivate::Lock, mode); +} + +/*! + Unlocks the system lock. + Returns true on success; otherwise returns false. + + \sa lock() + */ +bool QSystemLock::unlock() +{ + if (d->lockCount == 0) { + qWarning() << "QSystemLock::unlock: unlock with no lock."; + return false; + } + return d->modifySemaphore(QSystemLockPrivate::Unlock, d->lockedMode); +} + +/*! + Returns the type of error that occurred last or NoError. + + \sa errorString() + */ +QSystemLock::SystemLockError QSystemLock::error() const +{ + return d->error; +} + +/*! + Returns the human-readable message appropriate to the current error + reported by error(). If no suitable string is available, an empty + string is returned. + + \sa error() + */ +QString QSystemLock::errorString() const +{ + return d->errorString; +} + diff --git a/tests/auto/qtipc/qsharedmemory/src/qsystemlock.h b/tests/auto/qtipc/qsharedmemory/src/qsystemlock.h new file mode 100644 index 0000000..7cd6b89 --- /dev/null +++ b/tests/auto/qtipc/qsharedmemory/src/qsystemlock.h @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QSYSTEMLOCK_H +#define QSYSTEMLOCK_H + +#include + +QT_BEGIN_HEADER + +#ifndef QT_NO_SYSTEMLOCK + +QT_FORWARD_DECLARE_CLASS(QSystemLockPrivate) + +class QSystemLock +{ + +public: + enum SystemLockError + { + NoError, + UnknownError + }; + + QSystemLock(const QString &key); + ~QSystemLock(); + + void setKey(const QString &key); + QString key() const; + + enum LockMode + { + ReadOnly, + ReadWrite + }; + + bool lock(LockMode mode = ReadWrite); + bool unlock(); + + SystemLockError error() const; + QString errorString() const; + +private: + Q_DISABLE_COPY(QSystemLock) + + QSystemLockPrivate *d; +}; + +class QSystemLocker +{ + +public: + inline QSystemLocker(QSystemLock *systemLock, + QSystemLock::LockMode mode = QSystemLock::ReadWrite) : q_lock(systemLock) + { + autoUnLocked = relock(mode); + } + + inline ~QSystemLocker() + { + if (autoUnLocked) + unlock(); + } + + inline QSystemLock *systemLock() const + { + return q_lock; + } + + inline bool relock(QSystemLock::LockMode mode = QSystemLock::ReadWrite) + { + return (q_lock && q_lock->lock(mode)); + } + + inline bool unlock() + { + if (q_lock && q_lock->unlock()) { + autoUnLocked = false; + return true; + } + return false; + } + +private: + Q_DISABLE_COPY(QSystemLocker) + + bool autoUnLocked; + QSystemLock *q_lock; +}; + +#endif // QT_NO_SYSTEMLOCK + +QT_END_HEADER + +#endif // QSYSTEMLOCK_H + diff --git a/tests/auto/qtipc/qsharedmemory/src/qsystemlock_p.h b/tests/auto/qtipc/qsharedmemory/src/qsystemlock_p.h new file mode 100644 index 0000000..7995a91 --- /dev/null +++ b/tests/auto/qtipc/qsharedmemory/src/qsystemlock_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QSYSTEMLOCK_P_H +#define QSYSTEMLOCK_P_H + +#ifndef QT_NO_SYSTEMLOCK + +#include "qsystemlock.h" +#include "private/qsharedmemory_p.h" +#ifndef Q_OS_WINCE +#include +#endif + +#define MAX_LOCKS 64 + +class QSystemLockPrivate +{ + +public: + QSystemLockPrivate(); + + QString makeKeyFileName() + { + return QSharedMemoryPrivate::makePlatformSafeKey(key, QLatin1String("qipc_systemlock_")); + } + + void setErrorString(const QString &function); + +#ifdef Q_OS_WIN + HANDLE handle(); + bool lock(HANDLE, int count); + bool unlock(HANDLE, int count); +#else + key_t handle(); +#endif + void cleanHandle(); + + enum Operation { + Lock, + Unlock + }; + bool modifySemaphore(Operation op, QSystemLock::LockMode mode = QSystemLock::ReadOnly); + + QString key; + QString fileName; +#ifdef Q_OS_WIN + HANDLE semaphore; + HANDLE semaphoreLock; +#else + int semaphore; +#endif + int lockCount; + QSystemLock::LockMode lockedMode; + + QSystemLock::SystemLockError error; + QString errorString; + +private: +#ifndef Q_OS_WIN + key_t unix_key; + bool createdFile; + bool createdSemaphore; +#endif +}; + +#endif // QT_NO_SYSTEMLOCK + +#endif // QSYSTEMLOCK_P_H + diff --git a/tests/auto/qtipc/qsharedmemory/src/qsystemlock_unix.cpp b/tests/auto/qtipc/qsharedmemory/src/qsystemlock_unix.cpp new file mode 100644 index 0000000..525aa78 --- /dev/null +++ b/tests/auto/qtipc/qsharedmemory/src/qsystemlock_unix.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qsystemlock.h" +#include "qsystemlock_p.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +// We have to define this as on some sem.h will have it +union qt_semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ + unsigned short *array; /* array for GETALL, SETALL */ +}; + +#define tr(x) QT_TRANSLATE_NOOP(QLatin1String("QSystemLock"), (x)) + +#if defined(Q_OS_SYMBIAN) +int createUnixKeyFile(const QString &fileName) +{ + if (QFile::exists(fileName)) + return 0; + + int fd = open(QFile::encodeName(fileName).constData(), + O_EXCL | O_CREAT | O_RDWR, 0640); + if (-1 == fd) { + if (errno == EEXIST) + return 0; + return -1; + } else { + close(fd); + } + return 1; +} +#endif + +QSystemLockPrivate::QSystemLockPrivate() : + semaphore(-1), lockCount(0), + error(QSystemLock::NoError), unix_key(-1), createdFile(false), createdSemaphore(false) +{ +} + +void QSystemLockPrivate::setErrorString(const QString &function) +{ + switch (errno) { + case EIDRM: + errorString = function + QLatin1String(": ") + tr("The semaphore set was removed"); + error = QSystemLock::UnknownError; + break; + default: + errorString = function + QLatin1String(": ") + tr("unknown error"); + error = QSystemLock::UnknownError; + qWarning() << errorString << "key" << key << "errno" << errno << ERANGE << ENOMEM << EINVAL << EINTR << EFBIG << EFAULT << EAGAIN << EACCES << E2BIG; + } +} + +/*! + \internal + + Setup unix_key + */ +key_t QSystemLockPrivate::handle() +{ + if (key.isEmpty()) + return -1; + + // ftok requires that an actual file exists somewhere + // If we have already made at some point in the past, + // double check that it is still there. + if (-1 != unix_key) { + int aNewunix_key = ftok(QFile::encodeName(fileName).constData(), 'Q'); + if (aNewunix_key != unix_key) { + cleanHandle(); + } else { + return unix_key; + } + } + + // Create the file needed for ftok +#if defined(Q_OS_SYMBIAN) + int built = createUnixKeyFile(fileName); +#else + int built = QSharedMemoryPrivate::createUnixKeyFile(fileName); +#endif + if (-1 == built) + return -1; + createdFile = (1 == built); + + // Get the unix key for the created file + unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q'); + if (-1 == unix_key) { + setErrorString(QLatin1String("QSystemLock::handle ftok")); + return -1; + } + + // Get semaphore + semaphore = semget(unix_key, 1, 0666 | IPC_CREAT | IPC_EXCL); + if (-1 == semaphore) { + if (errno == EEXIST) + semaphore = semget(unix_key, 1, 0666 | IPC_CREAT); + if (-1 == semaphore) { + setErrorString(QLatin1String("QSystemLock::handle semget")); + cleanHandle(); + return -1; + } + } else { + // Created semaphore, initialize value. + createdSemaphore = true; + qt_semun init_op; + init_op.val = MAX_LOCKS; + if (-1 == semctl(semaphore, 0, SETVAL, init_op)) { + setErrorString(QLatin1String("QSystemLock::handle semctl")); + cleanHandle(); + return -1; + } + } + + return unix_key; +} + +/*! + \internal + + Cleanup the unix_key + */ +void QSystemLockPrivate::cleanHandle() +{ + unix_key = -1; + + // remove the file if we made it + if (createdFile) { + if (!QFile::remove(fileName)) + setErrorString(QLatin1String("QSystemLock::cleanHandle QFile::remove")); + createdFile = false; + } + + if (createdSemaphore) { + if (-1 != semaphore) { + if (-1 == semctl(semaphore, 0, IPC_RMID)) { + setErrorString(QLatin1String("QSystemLock::cleanHandle semctl")); + } + semaphore = -1; + } + createdSemaphore = false; + } +} + +/*! + \internal + + modifySemaphore generates operation.sem_op and handles recursive behavior. + */ +bool QSystemLockPrivate::modifySemaphore(QSystemLockPrivate::Operation op, + QSystemLock::LockMode mode) +{ + if (-1 == handle()) + return false; + + if ((lockCount == 0 && op == Lock) || (lockCount > 0 && op == Unlock)) { + if (op == Unlock) { + --lockCount; + Q_ASSERT(lockCount >= 0); + if (lockCount > 0) + return true; + } + + struct sembuf operation; + operation.sem_num = 0; + operation.sem_op = (mode == QSystemLock::ReadWrite) ? MAX_LOCKS : 1; + if (op == Lock) + operation.sem_op *= -1; + operation.sem_flg = SEM_UNDO; + + if (-1 == semop(semaphore, &operation, 1)) { + setErrorString(QLatin1String("QSystemLock::modify")); + return false; + } + lockedMode = mode; + } + if (op == Lock) + lockCount++; + + return true; +} + diff --git a/tests/auto/qtipc/qsharedmemory/src/qsystemlock_win.cpp b/tests/auto/qtipc/qsharedmemory/src/qsystemlock_win.cpp new file mode 100644 index 0000000..ac97100 --- /dev/null +++ b/tests/auto/qtipc/qsharedmemory/src/qsystemlock_win.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qsystemlock.h" +#include "qsystemlock_p.h" +#include +#include +QSystemLockPrivate::QSystemLockPrivate() : + semaphore(0), semaphoreLock(0), + lockCount(0), error(QSystemLock::NoError) +{ +} + +void QSystemLockPrivate::setErrorString(const QString &function) +{ + BOOL windowsError = GetLastError(); + if (windowsError == 0) + return; + errorString = function + QLatin1String(": ") + + QLatin1String("Unknown error"); + error = QSystemLock::UnknownError; + qWarning() << errorString << "key" << key << (int)windowsError << semaphore << semaphoreLock; +} + +/*! + \internal + + Setup the semaphore + */ +HANDLE QSystemLockPrivate::handle() +{ + // don't allow making handles on empty keys + if (key.isEmpty()) + return 0; + + // Create it if it doesn't already exists. + if (semaphore == 0) { + QString safeName = makeKeyFileName(); + semaphore = CreateSemaphore(0, MAX_LOCKS, MAX_LOCKS, (wchar_t*)safeName.utf16()); + + if (semaphore == 0) { + setErrorString(QLatin1String("QSystemLockPrivate::handle")); + return 0; + } + } + + if (semaphoreLock == 0) { + QString safeLockName = QSharedMemoryPrivate::makePlatformSafeKey(key + QLatin1String("lock"), QLatin1String("qipc_systemlock_")); + semaphoreLock = CreateSemaphore(0, 1, 1, (wchar_t*)safeLockName.utf16()); + + if (semaphoreLock == 0) { + setErrorString(QLatin1String("QSystemLockPrivate::handle")); + return 0; + } + } + + return semaphore; +} + +/*! + \internal + + Cleanup the semaphore + */ +void QSystemLockPrivate::cleanHandle() +{ + if (semaphore && !CloseHandle(semaphore)) + setErrorString(QLatin1String("QSystemLockPrivate::cleanHandle:")); + if (semaphoreLock && !CloseHandle(semaphoreLock)) + setErrorString(QLatin1String("QSystemLockPrivate::cleanHandle:")); + semaphore = 0; + semaphoreLock = 0; +} + +bool QSystemLockPrivate::lock(HANDLE handle, int count) +{ + if (count == 1) { + WaitForSingleObject(handle, INFINITE); + return true; + } + + int i = count; + while (i > 0) { + if (WAIT_OBJECT_0 == WaitForSingleObject(handle, 0)) { + --i; + } else { + // undo what we have done, sleep and then try again later + ReleaseSemaphore(handle, (count - i), 0); + i = count; + ReleaseSemaphore(semaphoreLock, 1, 0); + Sleep(1); + WaitForSingleObject(semaphoreLock, INFINITE); + } + } + return true; +} + +bool QSystemLockPrivate::unlock(HANDLE handle, int count) +{ + if (0 == ReleaseSemaphore(handle, count, 0)) { + setErrorString(QLatin1String("QSystemLockPrivate::unlock")); + return false; + } + return true; +} + +/*! + \internal + + modifySemaphore handles recursive behavior and modifies the semaphore. + */ +bool QSystemLockPrivate::modifySemaphore(QSystemLockPrivate::Operation op, + QSystemLock::LockMode mode) +{ + if (0 == handle()) + return false; + + if ((lockCount == 0 && op == Lock) || (lockCount > 0 && op == Unlock)) { + if (op == Unlock) { + --lockCount; + Q_ASSERT(lockCount >= 0); + if (lockCount > 0) + return true; + } + + int count = (mode == QSystemLock::ReadWrite) ? MAX_LOCKS : 1; + if (op == Lock) { + lock(semaphoreLock, 1); + lock(semaphore, count); + if (count != MAX_LOCKS) unlock(semaphoreLock, 1); + lockedMode = mode; + } else { + if (count == MAX_LOCKS) unlock(semaphoreLock, 1); + unlock(semaphore, count); + } + + } + if (op == Lock) + lockCount++; + + return true; +} + diff --git a/tests/auto/qtipc/qsharedmemory/src/src.pri b/tests/auto/qtipc/qsharedmemory/src/src.pri new file mode 100644 index 0000000..5bc9de6 --- /dev/null +++ b/tests/auto/qtipc/qsharedmemory/src/src.pri @@ -0,0 +1,10 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD + +SOURCES += $$PWD/qsystemlock.cpp + +HEADERS += $$PWD/qsystemlock.h \ + $$PWD/qsystemlock_p.h + +unix:SOURCES += $$PWD/qsystemlock_unix.cpp +win32:SOURCES += $$PWD/qsystemlock_win.cpp diff --git a/tests/auto/qtipc/qsharedmemory/test/test.pro b/tests/auto/qtipc/qsharedmemory/test/test.pro new file mode 100644 index 0000000..40ba8b9 --- /dev/null +++ b/tests/auto/qtipc/qsharedmemory/test/test.pro @@ -0,0 +1,37 @@ +load(qttest_p4) + +include(../src/src.pri) +QT -= gui + +DEFINES += QSHAREDMEMORY_DEBUG +DEFINES += QSYSTEMSEMAPHORE_DEBUG + +SOURCES += ../tst_qsharedmemory.cpp +TARGET = ../tst_qsharedmemory + +!wince*:win32 { + CONFIG(debug, debug|release) { + TARGET = ../../debug/tst_qsharedmemory +} else { + TARGET = ../../release/tst_qsharedmemory + } +} + +wince*:{ +requires(contains(QT_CONFIG,script)) +QT += gui script +addFiles.sources = ../../lackey/lackey.exe ../../lackey/scripts +addFiles.path = lackey +DEPLOYMENT += addFiles +DEFINES += SRCDIR=\\\"\\\" +}else:symbian*{ +requires(contains(QT_CONFIG,script)) +QT += gui script +addFiles.sources = ../../lackey/scripts +addFiles.path = /data/qsharedmemorytemp/lackey +addBin.sources = lackey.exe +addBin.path = /sys/bin +DEPLOYMENT += addFiles addBin +} else { +DEFINES += SRCDIR=\\\"$$PWD/../\\\" +} diff --git a/tests/auto/qtipc/qsharedmemory/tst_qsharedmemory.cpp b/tests/auto/qtipc/qsharedmemory/tst_qsharedmemory.cpp new file mode 100644 index 0000000..83f65b0 --- /dev/null +++ b/tests/auto/qtipc/qsharedmemory/tst_qsharedmemory.cpp @@ -0,0 +1,776 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include + +//TESTED_CLASS= +//TESTED_FILES= + +#define EXISTING_SHARE "existing" +#define EXISTING_SIZE 1024 + +#ifdef Q_OS_SYMBIAN +#define SRCDIR "c:/data/qsharedmemorytemp/" +#define LACKEYDIR SRCDIR "lackey" +#elif Q_OS_WINCE +#define LACKEYDIR SRCDIR "lackey" +#else +#define LACKEYDIR SRCDIR "../lackey" +#endif + +Q_DECLARE_METATYPE(QSharedMemory::SharedMemoryError) +Q_DECLARE_METATYPE(QSharedMemory::AccessMode) + +class tst_QSharedMemory : public QObject +{ + Q_OBJECT + +public: + tst_QSharedMemory(); + virtual ~tst_QSharedMemory(); + +public Q_SLOTS: + void init(); + void cleanup(); + +private slots: + // basics + void constructor(); + void key_data(); + void key(); + void create_data(); + void create(); + void attach_data(); + void attach(); + void lock(); + + // custom edge cases + void removeWhileAttached(); + void emptyMemory(); + void readOnly(); + + // basics all together + void simpleProducerConsumer_data(); + void simpleProducerConsumer(); + void simpleDoubleProducerConsumer(); + + // with threads + void simpleThreadedProducerConsumer_data(); + void simpleThreadedProducerConsumer(); + + // with processes + void simpleProcessProducerConsumer_data(); + void simpleProcessProducerConsumer(); + + // extreme cases + void useTooMuchMemory(); + void attachTooMuch(); + +protected: + int remove(const QString &key); + + QString rememberKey(const QString &key) + { + if (key == EXISTING_SHARE) + return key; + if (!keys.contains(key)) { + keys.append(key); + remove(key); + } + return key; + } + + QStringList keys; + QList jail; + QSharedMemory *existingSharedMemory; +}; + +tst_QSharedMemory::tst_QSharedMemory() : existingSharedMemory(0) +{ +} + +tst_QSharedMemory::~tst_QSharedMemory() +{ +} + +void tst_QSharedMemory::init() +{ + existingSharedMemory = new QSharedMemory(EXISTING_SHARE); + if (!existingSharedMemory->create(EXISTING_SIZE)) { + QVERIFY(existingSharedMemory->error() == QSharedMemory::AlreadyExists); + } +} + +void tst_QSharedMemory::cleanup() +{ + delete existingSharedMemory; + qDeleteAll(jail.begin(), jail.end()); + jail.clear(); + + keys.append(EXISTING_SHARE); + for (int i = 0; i < keys.count(); ++i) { + QSharedMemory sm(keys.at(i)); + if (!sm.create(1024)) { + //if(sm.error() != QSharedMemory::KeyError) + // qWarning() << "test cleanup: remove failed:" << keys.at(i) << sm.error() << sm.errorString(); + sm.attach(); + sm.detach(); + remove(keys.at(i)); + } + } +} + +#ifndef Q_OS_WIN +#include "private/qsharedmemory_p.h" +#include +#include +#include +#endif + +int tst_QSharedMemory::remove(const QString &key) +{ +#ifndef Q_OS_WIN + // On unix the shared memory might exists from a previously failed test + // or segfault, remove it it does + if (key.isEmpty()) + return -1; + + // ftok requires that an actual file exists somewhere + QString fileName = QSharedMemoryPrivate::makePlatformSafeKey(key); + if (!QFile::exists(fileName)) { + //qDebug() << "exits failed"; + return -2; + } + + int unix_key = ftok(fileName.toLatin1().constData(), 'Q'); + if (-1 == unix_key) { + qDebug() << "ftok failed"; + return -3; + } + + int id = shmget(unix_key, 0, 0660); + if (-1 == id) { + qDebug() << "shmget failed"; + return -4; + } + + struct shmid_ds shmid_ds; + if (-1 == shmctl(id, IPC_RMID, &shmid_ds)) { + qDebug() << "shmctl failed"; + return -5; + } + return QFile::remove(fileName); +#else + Q_UNUSED(key); + return 0; +#endif +} + +/*! + Tests the default values + */ +void tst_QSharedMemory::constructor() +{ + QSharedMemory sm; + QCOMPARE(sm.key(), QString()); + QVERIFY(!sm.isAttached()); + QVERIFY(sm.data() == 0); + QCOMPARE(sm.size(), 0); + QCOMPARE(sm.error(), QSharedMemory::NoError); + QVERIFY(sm.errorString() == QString()); +} + +void tst_QSharedMemory::key_data() +{ + QTest::addColumn("constructorKey"); + QTest::addColumn("setKey"); + + QTest::newRow("null, null") << QString() << QString(); + QTest::newRow("null, one") << QString() << QString("one"); + QTest::newRow("one, two") << QString("one") << QString("two"); + QTest::newRow("invalid") << QString("o/e") << QString("t/o"); +} + +/*! + Basic key testing + */ +void tst_QSharedMemory::key() +{ + QFETCH(QString, constructorKey); + QFETCH(QString, setKey); + + QSharedMemory sm(constructorKey); + QCOMPARE(sm.key(), constructorKey); + sm.setKey(setKey); + QCOMPARE(sm.key(), setKey); + QCOMPARE(sm.isAttached(), false); + + QCOMPARE(sm.error(), QSharedMemory::NoError); + QVERIFY(sm.errorString() == QString()); + QVERIFY(sm.data() == 0); + QCOMPARE(sm.size(), 0); + + QCOMPARE(sm.detach(), false); +} + +void tst_QSharedMemory::create_data() +{ + QTest::addColumn("key"); + QTest::addColumn("size"); + QTest::addColumn("canCreate"); + QTest::addColumn("error"); + + QTest::newRow("null key") << QString() << 1024 + << false << QSharedMemory::LockError; + QTest::newRow("-1 size") << QString("negsize") << -1 + << false << QSharedMemory::InvalidSize; + QTest::newRow("nor size") << QString("norsize") << 1024 + << true << QSharedMemory::NoError; + QTest::newRow("already exists") << QString(EXISTING_SHARE) << EXISTING_SIZE + << false << QSharedMemory::AlreadyExists; +} + +/*! + Basic create testing + */ +void tst_QSharedMemory::create() +{ + QFETCH(QString, key); + QFETCH(int, size); + QFETCH(bool, canCreate); + QFETCH(QSharedMemory::SharedMemoryError, error); + + QSharedMemory sm(rememberKey(key)); + QCOMPARE(sm.create(size), canCreate); + if(sm.error() != error) + qDebug() << sm.errorString(); + QCOMPARE(sm.key(), key); + if (canCreate) { + QVERIFY(sm.errorString() == QString()); + QVERIFY(sm.data() != 0); + QVERIFY(sm.size() != 0); + } else { + QVERIFY(sm.data() == 0); + QVERIFY(sm.errorString() != QString()); + } +} + +void tst_QSharedMemory::attach_data() +{ + QTest::addColumn("key"); + QTest::addColumn("exists"); + QTest::addColumn("error"); + + QTest::newRow("null key") << QString() << false << QSharedMemory::LockError; + QTest::newRow("doesn't exists") << QString("doesntexists") << false << QSharedMemory::NotFound; + QTest::newRow("already exists") << QString(EXISTING_SHARE) << true << QSharedMemory::NoError; +} + +/*! + Basic attach/detach testing + */ +void tst_QSharedMemory::attach() +{ + QFETCH(QString, key); + QFETCH(bool, exists); + QFETCH(QSharedMemory::SharedMemoryError, error); +#ifdef Q_OS_HPUX + if (QLatin1String(QTest::currentDataTag()) == QLatin1String("already exists")) { + QSKIP("HPUX doesn't allow for multiple attaches per process", SkipSingle); + } +#endif + QSharedMemory sm(key); + QCOMPARE(sm.attach(), exists); + QCOMPARE(sm.isAttached(), exists); + QCOMPARE(sm.error(), error); + QCOMPARE(sm.key(), key); + if (exists) { + QVERIFY(sm.data() != 0); + QVERIFY(sm.size() != 0); + QCOMPARE(sm.errorString(), QString()); + QVERIFY(sm.detach()); + // Make sure detach doesn't screw up something and we can't re-attach. + QVERIFY(sm.attach()); + QVERIFY(sm.detach()); + QCOMPARE(sm.size(), 0); + QVERIFY(sm.data() == 0); + } else { + QVERIFY(sm.data() == 0); + QVERIFY(sm.size() == 0); + QVERIFY(sm.errorString() != QString()); + QVERIFY(!sm.detach()); + } +} + +void tst_QSharedMemory::lock() +{ + QSharedMemory shm; + QVERIFY(!shm.lock()); + QCOMPARE(shm.error(), QSharedMemory::LockError); + + shm.setKey(QLatin1String("qsharedmemory")); + + QVERIFY(!shm.lock()); + QCOMPARE(shm.error(), QSharedMemory::LockError); + + QVERIFY(shm.create(100)); + QVERIFY(shm.lock()); + QTest::ignoreMessage(QtWarningMsg, "QSharedMemory::lock: already locked"); + QVERIFY(shm.lock()); + // don't lock forever +} + +/*! + Other shared memory are allowed to be attached after we remove, + but new shared memory are not allowed to attach after a remove. + */ +void tst_QSharedMemory::removeWhileAttached() +{ +#ifdef Q_OS_HPUX + QSKIP("HPUX doesn't allow for multiple attaches per process", SkipAll); +#endif + rememberKey("one"); + + // attach 1 + QSharedMemory *smOne = new QSharedMemory(QLatin1String("one")); + QVERIFY(smOne->create(1024)); + QVERIFY(smOne->isAttached()); + + // attach 2 + QSharedMemory *smTwo = new QSharedMemory(QLatin1String("one")); + QVERIFY(smTwo->attach()); + QVERIFY(smTwo->isAttached()); + + // detach 1 and remove, remove one first to catch another error. + delete smOne; + delete smTwo; + + // three shouldn't be able to attach + QSharedMemory smThree(QLatin1String("one")); + QVERIFY(!smThree.attach()); + QCOMPARE(smThree.error(), QSharedMemory::NotFound); +} + +/*! + The memory should be set to 0 after created. + */ +void tst_QSharedMemory::emptyMemory() +{ + QSharedMemory sm(rememberKey(QLatin1String("voidland"))); + int size = 1024; + QVERIFY(sm.create(size, QSharedMemory::ReadOnly)); + char *get = (char*)sm.data(); + char null = 0; + for (int i = 0; i < size; ++i) + QCOMPARE(get[i], null); +} + +/*! + Verify that attach with ReadOnly is actually read only + by writing to data and causing a segfault. +*/ +void tst_QSharedMemory::readOnly() +{ +#ifdef Q_OS_WIN + QSKIP("This test opens a crash dialog on Windows", SkipSingle); +#endif +#if defined (Q_OS_SYMBIAN) + QSKIP("Readonly shared memory is not supported in symbian", SkipAll); +#endif + QString program = LACKEYDIR "/lackey"; + QStringList arguments; + rememberKey("readonly_segfault"); + arguments << LACKEYDIR "/scripts/readonly_segfault.js"; + + // ### on windows disable the popup somehow + QProcess p; + p.start(program, arguments); + p.setProcessChannelMode(QProcess::ForwardedChannels); + p.waitForFinished(); + QCOMPARE(p.error(), QProcess::Crashed); +} + +/*! + Keep making shared memory until the kernel stops us. + */ +void tst_QSharedMemory::useTooMuchMemory() +{ +#ifdef Q_OS_LINUX + bool success = true; + int count = 0; + while (success) { + QString key = QString("maxmemorytest_%1").arg(count++); + QSharedMemory *sm = new QSharedMemory(rememberKey(key)); + QVERIFY(sm); + jail.append(sm); + int size = 32768 * 1024; + success = sm->create(size); + if (!success && sm->error() == QSharedMemory::AlreadyExists) { + // left over from a crash, clean it up + sm->attach(); + sm->detach(); + success = sm->create(size); + } + + if (!success) { + QVERIFY(!sm->isAttached()); + QCOMPARE(sm->key(), key); + QCOMPARE(sm->size(), 0); + QVERIFY(sm->data() == 0); + if (sm->error() != QSharedMemory::OutOfResources) + qDebug() << sm->error() << sm->errorString(); + // ### Linux wont return OutOfResources if there are not enough semaphores to use. + QVERIFY(sm->error() == QSharedMemory::OutOfResources + || sm->error() == QSharedMemory::LockError); + QVERIFY(sm->errorString() != QString()); + QVERIFY(!sm->attach()); + QVERIFY(!sm->detach()); + } else { + QVERIFY(sm->isAttached()); + } + } +#endif +} + +/*! + Create one shared memory (government) and see how many other shared memories (wars) we can + attach before the system runs out of resources. + */ +void tst_QSharedMemory::attachTooMuch() +{ + QSKIP("disabled", SkipAll); +#ifdef Q_OS_HPUX + QSKIP("HPUX doesn't allow for multiple attaches per process", SkipAll); +#endif +#ifdef Q_OS_WINCE + QSKIP("This nearly kills the system itself, so skip for Qt/WinCE", SkipAll); +#endif + QSharedMemory government(rememberKey("government")); + QVERIFY(government.create(1024)); + while (true) { + QSharedMemory *war = new QSharedMemory(government.key()); + QVERIFY(war); + jail.append(war); + if (!war->attach()) { + QVERIFY(!war->isAttached()); + QCOMPARE(war->key(), government.key()); + QCOMPARE(war->size(), 0); + QVERIFY(war->data() == 0); + QCOMPARE(war->error(), QSharedMemory::OutOfResources); + QVERIFY(war->errorString() != QString()); + QVERIFY(!war->detach()); + break; + } else { + QVERIFY(war->isAttached()); + } + } +} + +void tst_QSharedMemory::simpleProducerConsumer_data() +{ + QTest::addColumn("mode"); + + QTest::newRow("readonly") << QSharedMemory::ReadOnly; + QTest::newRow("readwrite") << QSharedMemory::ReadWrite; +} + +/*! + The basic consumer producer that rounds out the basic testing. + If this fails then any muli-threading/process might fail (but be + harder to debug) + + This doesn't require nor test any locking system. + */ +void tst_QSharedMemory::simpleProducerConsumer() +{ +#ifdef Q_OS_HPUX + QSKIP("HPUX doesn't allow for multiple attaches per process", SkipAll); +#endif + QFETCH(QSharedMemory::AccessMode, mode); + + rememberKey(QLatin1String("market")); + QSharedMemory producer(QLatin1String("market")); + QSharedMemory consumer(QLatin1String("market")); + int size = 512; + QVERIFY(producer.create(size)); + QVERIFY(consumer.attach(mode)); + + char *put = (char*)producer.data(); + char *get = (char*)consumer.data(); + // On Windows CE you always have ReadWrite access. Thus + // ViewMapOfFile returns the same pointer + // On Symbian, the address will always be same, as + // write protection of chunks is not currently supported by Symbian +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) + QVERIFY(put != get); +#endif + for (int i = 0; i < size; ++i) { + put[i] = 'Q'; + QCOMPARE(get[i], 'Q'); + } + QVERIFY(consumer.detach()); +} + +void tst_QSharedMemory::simpleDoubleProducerConsumer() +{ +#ifdef Q_OS_HPUX + QSKIP("HPUX doesn't allow for multiple attaches per process", SkipAll); +#endif + rememberKey(QLatin1String("market")); + QSharedMemory producer(QLatin1String("market")); + int size = 512; + QVERIFY(producer.create(size)); + QVERIFY(producer.detach()); + QVERIFY(producer.create(size)); + + { + QSharedMemory consumer(QLatin1String("market")); + QVERIFY(consumer.attach()); + } +} + +class Consumer : public QThread +{ + +public: + void run() + { + QSharedMemory consumer(QLatin1String("market")); + while (!consumer.attach()) { + if (consumer.error() != QSharedMemory::NotFound) + qDebug() << "consumer: failed to connect" << consumer.error() << consumer.errorString(); + QVERIFY(consumer.error() == QSharedMemory::NotFound || consumer.error() == QSharedMemory::KeyError); + QTest::qWait(1); + } + + char *memory = (char*)consumer.data(); + + int i = 0; + while (true) { + if(!consumer.lock()) + break; + if (memory[0] == 'Q') + memory[0] = ++i; + if (memory[0] == 'E') { + memory[1]++; + QVERIFY(consumer.unlock()); + break; + } + QVERIFY(consumer.unlock()); + QTest::qWait(1); + } + + QVERIFY(consumer.detach()); + } +}; + +class Producer : public QThread +{ + +public: + void run() + { + QSharedMemory producer(QLatin1String("market")); + int size = 1024; + if (!producer.create(size)) { + // left over from a crash... + if (producer.error() == QSharedMemory::AlreadyExists) { + producer.attach(); + producer.detach(); + QVERIFY(producer.create(size)); + } + } + QVERIFY(producer.isAttached()); + char *memory = (char*)producer.data(); + memory[1] = '0'; + QTime timer; + timer.start(); + int i = 0; + while (i < 5 && timer.elapsed() < 5000) { + QVERIFY(producer.lock()); + if (memory[0] == 'Q') { + QVERIFY(producer.unlock()); + QTest::qWait(1); + continue; + } + ++i; + memory[0] = 'Q'; + QVERIFY(producer.unlock()); + QTest::qWait(1); + } + + // tell everyone to quit + QVERIFY(producer.lock()); + memory[0] = 'E'; + QVERIFY(producer.unlock()); + +#if defined(Q_OS_SYMBIAN) + // Sleep a while to ensure that consumers start properly + QTest::qSleep(1000); +#endif + } +private: + +}; + +void tst_QSharedMemory::simpleThreadedProducerConsumer_data() +{ + QTest::addColumn("producerIsThread"); + QTest::addColumn("threads"); + for (int i = 0; i < 5; ++i) { + QTest::newRow("1 consumer, producer is thread") << true << 1; + QTest::newRow("1 consumer, producer is this") << false << 1; + QTest::newRow("5 consumers, producer is thread") << true << 5; + QTest::newRow("5 consumers, producer is this") << false << 5; + } +} + +/*! + The basic producer/consumer, but this time using threads. + */ +void tst_QSharedMemory::simpleThreadedProducerConsumer() +{ + QFETCH(bool, producerIsThread); + QFETCH(int, threads); + rememberKey(QLatin1String("market")); + +#if defined Q_OS_HPUX && defined __ia64 + QSKIP("This test locks up on gravlaks.troll.no", SkipSingle); +#endif + + Producer p; +#if defined(Q_OS_SYMBIAN) + enum + { + /** + * The maximum stack size. + */ + SymbianStackSize = 0x14000 + }; + p.setStackSize(SymbianStackSize); +#endif + if (producerIsThread) + p.start(); + + QList consumers; + for (int i = 0; i < threads; ++i) { + consumers.append(new Consumer()); +#if defined(Q_OS_SYMBIAN) + consumers.last()->setStackSize(SymbianStackSize); +#endif + consumers.last()->start(); + } + + if (!producerIsThread) + p.run(); + + p.wait(5000); + while (!consumers.isEmpty()) { + QVERIFY(consumers.first()->wait(5000)); + delete consumers.takeFirst(); + } +} + +void tst_QSharedMemory::simpleProcessProducerConsumer_data() +{ + QTest::addColumn("processes"); + int tries = 5; + for (int i = 0; i < tries; ++i) { + QTest::newRow("1 process") << 1; + QTest::newRow("5 processes") << 5; + } +} + +/*! + Create external processes that produce and consume. + */ +void tst_QSharedMemory::simpleProcessProducerConsumer() +{ +#if defined (Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) + QSKIP("Cannot launch multiple Qt processes in Symbian emulator", SkipAll); +#endif + QFETCH(int, processes); + + rememberKey("market"); + + QStringList arguments = QStringList() << LACKEYDIR "/scripts/producer.js"; + QProcess producer; + producer.setProcessChannelMode(QProcess::ForwardedChannels); + producer.start( LACKEYDIR "/lackey", arguments); + producer.waitForStarted(); + QVERIFY(producer.error() != QProcess::FailedToStart); + + QList consumers; + unsigned int failedProcesses = 0; + for (int i = 0; i < processes; ++i) { + QStringList arguments = QStringList() << LACKEYDIR "/scripts/consumer.js"; + QProcess *p = new QProcess; + p->setProcessChannelMode(QProcess::ForwardedChannels); + p->start(LACKEYDIR "/lackey", arguments); + + if (p->waitForStarted(2000)) + consumers.append(p); + else + ++failedProcesses; + } + + QVERIFY(producer.waitForFinished(5000)); + + bool consumerFailed = false; + + while (!consumers.isEmpty()) { + QVERIFY(consumers.first()->waitForFinished(3000)); + if (consumers.first()->state() == QProcess::Running || + consumers.first()->exitStatus() != QProcess::NormalExit || + consumers.first()->exitCode() != 0) { + consumerFailed = true; + } + delete consumers.takeFirst(); + } + QCOMPARE(consumerFailed, false); + QCOMPARE(failedProcesses, (unsigned int)(0)); +} + +QTEST_MAIN(tst_QSharedMemory) +#include "tst_qsharedmemory.moc" + diff --git a/tests/auto/qtipc/qsystemsemaphore/.gitignore b/tests/auto/qtipc/qsystemsemaphore/.gitignore new file mode 100644 index 0000000..2b60bfb --- /dev/null +++ b/tests/auto/qtipc/qsystemsemaphore/.gitignore @@ -0,0 +1 @@ +tst_qsystemsemaphore diff --git a/tests/auto/qtipc/qsystemsemaphore/files.qrc b/tests/auto/qtipc/qsystemsemaphore/files.qrc new file mode 100644 index 0000000..6296690 --- /dev/null +++ b/tests/auto/qtipc/qsystemsemaphore/files.qrc @@ -0,0 +1,7 @@ + + + ../lackey/scripts/systemsemaphore_acquire.js + ../lackey/scripts/systemsemaphore_release.js + ../lackey/scripts/systemsemaphore_acquirerelease.js + + diff --git a/tests/auto/qtipc/qsystemsemaphore/qsystemsemaphore.pro b/tests/auto/qtipc/qsystemsemaphore/qsystemsemaphore.pro new file mode 100644 index 0000000..1f9205e --- /dev/null +++ b/tests/auto/qtipc/qsystemsemaphore/qsystemsemaphore.pro @@ -0,0 +1,36 @@ +CONFIG += qttest_p4 +#QT = core + +include(../qsharedmemory/src/src.pri) +win32: CONFIG += console + +DEFINES += QSHAREDMEMORY_DEBUG +DEFINES += QSYSTEMSEMAPHORE_DEBUG + +SOURCES += tst_qsystemsemaphore.cpp +TARGET = tst_qsystemsemaphore + +RESOURCES += files.qrc + +wince*: { +requires(contains(QT_CONFIG,script)) +# this test calls lackey, which then again depends on QtScript. +# let's add it here so that it gets deployed easily +QT += script +lackey.sources = ../lackey/lackey.exe +lackey.path = ../lackey + +DEPLOYMENT += lackey +} + +symbian: { +requires(contains(QT_CONFIG,script)) +# this test calls lackey, which then again depends on QtScript. +# let's add it here so that it gets deployed easily +QT += script + +lackey.sources = ../lackey/lackey.exe +lackey.path = /sys/bin +DEPLOYMENT += lackey +} + diff --git a/tests/auto/qtipc/qsystemsemaphore/tst_qsystemsemaphore.cpp b/tests/auto/qtipc/qsystemsemaphore/tst_qsystemsemaphore.cpp new file mode 100644 index 0000000..eb82fd4 --- /dev/null +++ b/tests/auto/qtipc/qsystemsemaphore/tst_qsystemsemaphore.cpp @@ -0,0 +1,302 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include +//TESTED_CLASS= +//TESTED_FILES= + +#define EXISTING_SHARE "existing" +#define LACKYLOC "../lackey" +#define LACKYWAITTIME 10000 + +class tst_QSystemSemaphore : public QObject +{ + Q_OBJECT + +public: + tst_QSystemSemaphore(); + virtual ~tst_QSystemSemaphore(); + +public Q_SLOTS: + void init(); + void cleanup(); + +private slots: + void key_data(); + void key(); + + void basicacquire(); + void complexacquire(); + + void basicProcesses(); + + void processes_data(); + void processes(); + + void undo(); + void initialValue(); + +private: + QSystemSemaphore *existingLock; + + QString makeFile(const QString &resource) + { + QFile memory(resource); + if (!memory.open(QIODevice::ReadOnly)) { + qDebug() << "error reading resource" << resource; + return QString(); + } + QTemporaryFile *file = new QTemporaryFile; + file->open(); + file->write(memory.readAll()); + tempFiles.append(file); + file->flush(); +#ifdef Q_OS_WINCE + // flush does not flush to disk on Windows CE. It flushes it into its application + // cache. Thus we need to close the file to be able that other processes(lackey) can read it + QString fileName = file->fileName(); + file->close(); + return fileName; +#endif + return file->fileName(); + } + + QString acquire_js() { return makeFile(":/systemsemaphore_acquire.js"); } + QString release_js() { return makeFile(":/systemsemaphore_release.js"); } + QString acquirerelease_js() { return makeFile(":/systemsemaphore_acquirerelease.js"); } + QList tempFiles; +}; + +tst_QSystemSemaphore::tst_QSystemSemaphore() +{ + if (!QFile::exists(LACKYLOC "/lackey")) + qWarning() << "lackey executable doesn't exists!"; +} + +tst_QSystemSemaphore::~tst_QSystemSemaphore() +{ + qDeleteAll(tempFiles); +} + +void tst_QSystemSemaphore::init() +{ + existingLock = new QSystemSemaphore(EXISTING_SHARE, 1, QSystemSemaphore::Create); +} + +void tst_QSystemSemaphore::cleanup() +{ + delete existingLock; +} + +void tst_QSystemSemaphore::key_data() +{ + QTest::addColumn("constructorKey"); + QTest::addColumn("setKey"); + + QTest::newRow("null, null") << QString() << QString(); + QTest::newRow("null, one") << QString() << QString("one"); + QTest::newRow("one, two") << QString("one") << QString("two"); +} + +/*! + Basic key testing + */ +void tst_QSystemSemaphore::key() +{ + QFETCH(QString, constructorKey); + QFETCH(QString, setKey); + + QSystemSemaphore sem(constructorKey); + QCOMPARE(sem.key(), constructorKey); + QCOMPARE(sem.error(), QSystemSemaphore::NoError); + QCOMPARE(sem.errorString(), QString()); + + sem.setKey(setKey); + QCOMPARE(sem.key(), setKey); + QCOMPARE(sem.error(), QSystemSemaphore::NoError); + QCOMPARE(sem.errorString(), QString()); +} + +void tst_QSystemSemaphore::basicacquire() +{ + QSystemSemaphore sem("QSystemSemaphore_basicacquire", 1, QSystemSemaphore::Create); + QVERIFY(sem.acquire()); + QCOMPARE(sem.error(), QSystemSemaphore::NoError); + QVERIFY(sem.release()); + QCOMPARE(sem.error(), QSystemSemaphore::NoError); + QCOMPARE(sem.errorString(), QString()); +} + +void tst_QSystemSemaphore::complexacquire() +{ + QSystemSemaphore sem("QSystemSemaphore_complexacquire", 2, QSystemSemaphore::Create); + QVERIFY(sem.acquire()); + QVERIFY(sem.release()); + QVERIFY(sem.acquire()); + QVERIFY(sem.release()); + QVERIFY(sem.acquire()); + QVERIFY(sem.acquire()); + QVERIFY(sem.release()); + QVERIFY(sem.release()); + QCOMPARE(sem.error(), QSystemSemaphore::NoError); + QCOMPARE(sem.errorString(), QString()); +} + +void tst_QSystemSemaphore::basicProcesses() +{ +#if defined (Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) + QSKIP("Cannot launch multiple Qt processes in Symbian emulator", SkipAll); +#endif + QSystemSemaphore sem("store", 0, QSystemSemaphore::Create); + + QStringList acquireArguments = QStringList() << acquire_js(); + QStringList releaseArguments = QStringList() << release_js(); + QProcess acquire; + acquire.setProcessChannelMode(QProcess::ForwardedChannels); + + QProcess release; + release.setProcessChannelMode(QProcess::ForwardedChannels); + + acquire.start(LACKYLOC "/lackey", acquireArguments); + acquire.waitForFinished(LACKYWAITTIME); + QVERIFY(acquire.state() == QProcess::Running); + acquire.kill(); + release.start(LACKYLOC "/lackey", releaseArguments); + acquire.waitForFinished(LACKYWAITTIME); + release.waitForFinished(LACKYWAITTIME); + QVERIFY(acquire.state() == QProcess::NotRunning); +} + +void tst_QSystemSemaphore::processes_data() +{ + QTest::addColumn("processes"); + for (int i = 0; i < 5; ++i) { + QTest::newRow("1 process") << 1; + QTest::newRow("3 process") << 3; + QTest::newRow("10 process") << 10; + } +} + +void tst_QSystemSemaphore::processes() +{ +#if defined (Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) + QSKIP("Cannot launch multiple Qt processes in Symbian emulator", SkipAll); +#endif + QSystemSemaphore sem("store", 1, QSystemSemaphore::Create); + + QFETCH(int, processes); + QStringList scripts; + for (int i = 0; i < processes; ++i) + scripts.append(acquirerelease_js()); + + QList consumers; + for (int i = 0; i < scripts.count(); ++i) { + QStringList arguments = QStringList() << scripts.at(i); + QProcess *p = new QProcess; + p->setProcessChannelMode(QProcess::ForwardedChannels); + consumers.append(p); + p->start(LACKYLOC "/lackey", arguments); + } + + while (!consumers.isEmpty()) { + consumers.first()->waitForFinished(); + QCOMPARE(consumers.first()->exitStatus(), QProcess::NormalExit); + QCOMPARE(consumers.first()->exitCode(), 0); + delete consumers.takeFirst(); + } +} + +void tst_QSystemSemaphore::undo() +{ +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + QSKIP("This test only checks a unix behavior", SkipSingle); +#endif + + QSystemSemaphore sem("store", 1, QSystemSemaphore::Create); + + QStringList acquireArguments = QStringList() << acquire_js(); + QProcess acquire; + acquire.setProcessChannelMode(QProcess::ForwardedChannels); + acquire.start(LACKYLOC "/lackey", acquireArguments); + acquire.waitForFinished(LACKYWAITTIME); + QVERIFY(acquire.state()== QProcess::NotRunning); + + // At process exit the kernel should auto undo + + acquire.start(LACKYLOC "/lackey", acquireArguments); + acquire.waitForFinished(LACKYWAITTIME); + QVERIFY(acquire.state()== QProcess::NotRunning); +} + +void tst_QSystemSemaphore::initialValue() +{ +#if defined (Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) + QSKIP("Cannot launch multiple Qt processes in Symbian emulator", SkipAll); +#endif + QSystemSemaphore sem("store", 1, QSystemSemaphore::Create); + + QStringList acquireArguments = QStringList() << acquire_js(); + QStringList releaseArguments = QStringList() << release_js(); + QProcess acquire; + acquire.setProcessChannelMode(QProcess::ForwardedChannels); + + QProcess release; + release.setProcessChannelMode(QProcess::ForwardedChannels); + + acquire.start(LACKYLOC "/lackey", acquireArguments); + acquire.waitForFinished(LACKYWAITTIME); + QVERIFY(acquire.state()== QProcess::NotRunning); + + acquire.start(LACKYLOC "/lackey", acquireArguments << "2"); + acquire.waitForFinished(LACKYWAITTIME); + QVERIFY(acquire.state()== QProcess::Running); + acquire.kill(); + + release.start(LACKYLOC "/lackey", releaseArguments); + acquire.waitForFinished(LACKYWAITTIME); + release.waitForFinished(LACKYWAITTIME); + QVERIFY(acquire.state()== QProcess::NotRunning); +} +QTEST_MAIN(tst_QSystemSemaphore) +#include "tst_qsystemsemaphore.moc" + diff --git a/tests/auto/qtipc/qtipc.pro b/tests/auto/qtipc/qtipc.pro new file mode 100644 index 0000000..60037d2 --- /dev/null +++ b/tests/auto/qtipc/qtipc.pro @@ -0,0 +1,6 @@ +TEMPLATE=subdirs +SUBDIRS=\ + lackey \ + qsharedmemory \ + qsystemsemaphore \ + -- cgit v0.12