diff options
Diffstat (limited to 'tests/auto/corelib/global')
4 files changed, 263 insertions, 1 deletions
diff --git a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp index a4aca82aa9..ef41ef8801 100644 --- a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp +++ b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp @@ -75,6 +75,13 @@ void tst_QGetPutEnv::getSetCheck() QVERIFY(result == "supervalue"); qputenv(varName,QByteArray()); + + // Now test qunsetenv + QVERIFY(qunsetenv(varName)); + QVERIFY(!qEnvironmentVariableIsSet(varName)); + QVERIFY(qEnvironmentVariableIsEmpty(varName)); + result = qgetenv(varName); + QCOMPARE(result, QByteArray()); } QTEST_MAIN(tst_QGetPutEnv) diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp index f54af657c0..3696ee264f 100644 --- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp +++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp @@ -55,6 +55,8 @@ private slots: void checkptr(); void qstaticassert(); void qConstructorFunction(); + void qCoreAppStartupFunction(); + void qCoreAppStartupFunctionRestart(); void isEnum(); void qAlignOf(); }; @@ -303,6 +305,33 @@ void tst_QGlobal::qConstructorFunction() QCOMPARE(qConstructorFunctionValue, 123); } +static int qStartupFunctionValue; +static void myStartupFunc() +{ + Q_ASSERT(QCoreApplication::instance()); + if (QCoreApplication::instance()) + qStartupFunctionValue += 124; +} + +Q_COREAPP_STARTUP_FUNCTION(myStartupFunc) + +void tst_QGlobal::qCoreAppStartupFunction() +{ + QCOMPARE(qStartupFunctionValue, 0); + int argc = 1; + char *argv[] = { const_cast<char*>("tst_qglobal") }; + QCoreApplication app(argc, argv); + QCOMPARE(qStartupFunctionValue, 124); +} + +void tst_QGlobal::qCoreAppStartupFunctionRestart() +{ + qStartupFunctionValue = 0; + qCoreAppStartupFunction(); + qStartupFunctionValue = 0; + qCoreAppStartupFunction(); +} + struct isEnum_A { int n_; }; @@ -532,5 +561,5 @@ void tst_QGlobal::qAlignOf() #undef TEST_AlignOf_RValueRef #undef TEST_AlignOf_impl -QTEST_MAIN(tst_QGlobal) +QTEST_APPLESS_MAIN(tst_QGlobal) #include "tst_qglobal.moc" diff --git a/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro b/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro new file mode 100644 index 0000000000..21cab8f67d --- /dev/null +++ b/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro @@ -0,0 +1,12 @@ +QT += testlib core-private + +QT -= gui + +TARGET = tst_qglobalstatic +CONFIG += console +CONFIG -= app_bundle +CONFIG += exceptions + +SOURCES += tst_qglobalstatic.cpp +DEFINES += SRCDIR=\\\"$$PWD/\\\" +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp new file mode 100644 index 0000000000..b9aa70fe80 --- /dev/null +++ b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Thiago Macieira <thiago@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QThread> +#include <QtTest/QtTest> + +class tst_QGlobalStatic : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void beforeInitialization(); + void api(); + void constVolatile(); + void exception(); + void threadStressTest(); + void afterDestruction(); +}; + +Q_GLOBAL_STATIC_WITH_ARGS(const int, constInt, (42)) +Q_GLOBAL_STATIC_WITH_ARGS(volatile int, volatileInt, (-47)) + +void otherFunction() +{ + // never called + constInt(); + volatileInt(); +} + +// do not initialize the following Q_GLOBAL_STATIC +Q_GLOBAL_STATIC(int, checkedBeforeInitialization) +void tst_QGlobalStatic::beforeInitialization() +{ + QVERIFY(!checkedBeforeInitialization.exists()); + QVERIFY(!checkedBeforeInitialization.isDestroyed()); +} + +struct Type { + int i; +}; + +Q_GLOBAL_STATIC(Type, checkedAfterInitialization) +void tst_QGlobalStatic::api() +{ + // check the API + QVERIFY((Type *)checkedAfterInitialization); + QVERIFY(checkedAfterInitialization()); + *checkedAfterInitialization = Type(); + *checkedAfterInitialization() = Type(); + + checkedAfterInitialization()->i = 47; + checkedAfterInitialization->i = 42; + QCOMPARE(checkedAfterInitialization()->i, 42); + checkedAfterInitialization()->i = 47; + QCOMPARE(checkedAfterInitialization->i, 47); + + QVERIFY(checkedAfterInitialization.exists()); + QVERIFY(!checkedAfterInitialization.isDestroyed()); +} + +void tst_QGlobalStatic::constVolatile() +{ + QCOMPARE(*constInt(), 42); + QCOMPARE((int)*volatileInt(), -47); + QCOMPARE(*constInt(), 42); + QCOMPARE((int)*volatileInt(), -47); +} + +struct ThrowingType +{ + static QBasicAtomicInt constructedCount; + static QBasicAtomicInt destructedCount; + ThrowingType(QBasicAtomicInt &throwControl) + { + constructedCount.ref(); + if (throwControl.fetchAndAddRelaxed(-1) != 0) + throw 0; + } + ~ThrowingType() { destructedCount.ref(); } +}; +QBasicAtomicInt ThrowingType::constructedCount = Q_BASIC_ATOMIC_INITIALIZER(0); +QBasicAtomicInt ThrowingType::destructedCount = Q_BASIC_ATOMIC_INITIALIZER(0); + +QBasicAtomicInt exceptionControlVar = Q_BASIC_ATOMIC_INITIALIZER(1); +Q_GLOBAL_STATIC_WITH_ARGS(ThrowingType, exceptionGS, (exceptionControlVar)) +void tst_QGlobalStatic::exception() +{ + if (exceptionControlVar.load() != 1) + QSKIP("This test cannot be run more than once"); + ThrowingType::constructedCount.store(0); + ThrowingType::destructedCount.store(0); + + bool exceptionCaught = false; + try { + exceptionGS(); + } catch (int) { + exceptionCaught = true; + } + QCOMPARE(ThrowingType::constructedCount.load(), 1); + QVERIFY(exceptionCaught); + + exceptionGS(); + QCOMPARE(ThrowingType::constructedCount.load(), 2); +} + +QBasicAtomicInt threadStressTestControlVar = Q_BASIC_ATOMIC_INITIALIZER(5); +Q_GLOBAL_STATIC_WITH_ARGS(ThrowingType, threadStressTestGS, (threadStressTestControlVar)) + + +void tst_QGlobalStatic::threadStressTest() +{ + class ThreadStressTestThread: public QThread + { + public: + QReadWriteLock *lock; + void run() + { + QReadLocker l(lock); + //usleep(qrand() * 200 / RAND_MAX); + // thundering herd + try { + threadStressTestGS(); + } catch (int) { + } + } + }; + + ThrowingType::constructedCount.store(0); + ThrowingType::destructedCount.store(0); + int expectedConstructionCount = threadStressTestControlVar.load() + 1; + if (expectedConstructionCount <= 0) + QSKIP("This test cannot be run more than once"); + + const int numThreads = 200; + ThreadStressTestThread threads[numThreads]; + QReadWriteLock lock; + lock.lockForWrite(); + for (int i = 0; i < numThreads; ++i) { + threads[i].lock = &lock; + threads[i].start(); + } + + // wait for all threads + // release the herd + lock.unlock(); + + for (int i = 0; i < numThreads; ++i) + threads[i].wait(); + + QCOMPARE(ThrowingType::constructedCount.loadAcquire(), expectedConstructionCount); + QCOMPARE(ThrowingType::destructedCount.loadAcquire(), 0); +} + +Q_GLOBAL_STATIC(int, checkedAfterDestruction) +void tst_QGlobalStatic::afterDestruction() +{ + // this test will not produce results now + // it will simply run some code on destruction (after the global statics have been deleted) + // if that fails, this will cause a crash + + // static destruction is LIFO: so we must add our exit-time code before the + // global static is used for the first time + static struct RunAtExit { + ~RunAtExit() { + int *ptr = checkedAfterDestruction(); + if (ptr) + qFatal("Global static is not null as was expected"); + } + } runAtExit; + (void) runAtExit; + + *checkedAfterDestruction = 42; +} + +QTEST_APPLESS_MAIN(tst_QGlobalStatic); + +#include "tst_qglobalstatic.moc" |