diff options
author | Shane Kearns <shane.kearns@accenture.com> | 2011-05-04 12:02:57 (GMT) |
---|---|---|
committer | Shane Kearns <shane.kearns@accenture.com> | 2011-05-04 12:19:24 (GMT) |
commit | 5f241ec1426447380b1e938ac7888fb16cde94f8 (patch) | |
tree | 73908acf04908598eb8953930ba8af7794e7bfb3 /tests | |
parent | ae128aef03d246c9f89bed015092b1c5a925bcbc (diff) | |
download | Qt-5f241ec1426447380b1e938ac7888fb16cde94f8.zip Qt-5f241ec1426447380b1e938ac7888fb16cde94f8.tar.gz Qt-5f241ec1426447380b1e938ac7888fb16cde94f8.tar.bz2 |
Fix QNetworkConfigurationManager usage outside main thread first
QNetworkConfigurationManager creates the engines loaded from plugins
as objects in the main thread.
If a QNetworkConfigurationManager instance is created in a worker thread
without any instance previously existing in the main thread, then it
is uninitialised until the main thread has run.
This causes allConfigurations() to return an empty list if called
immediately after instantiation, for example.
This fix initialises the plugins using blocking queued connections,
which causes the worker thread to block until the initialisation function
has been called in the context of the main thread.
Deadlock is possible if the main thread is for some reason waiting on the
worker thread, but it will not deadlock on QNetworkConfigurationManager's
mutex.
If this is a problem for an application, it should use
QNetworkConfigurationManager from the main thread first to preload the
plugins.
Task-number: QTBUG-18795
Task-number: QTBUG-18799
Reviewed-by: Cristiano Di Flora
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp | 38 | ||||
-rw-r--r-- | tests/auto/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp | 31 |
2 files changed, 68 insertions, 1 deletions
diff --git a/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp b/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp index 443fd18..57812d3 100644 --- a/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp +++ b/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp @@ -62,6 +62,7 @@ public slots: void cleanup(); private slots: + void usedInThread(); // this test must be first, or it will falsely pass void allConfigurations(); void defaultConfiguration(); void configurationFromIdentifier(); @@ -329,6 +330,43 @@ void tst_QNetworkConfigurationManager::configurationFromIdentifier() QVERIFY(!invalid.isValid()); } +class QNCMTestThread : public QThread +{ +protected: + virtual void run() + { + QNetworkConfigurationManager manager; + preScanConfigs = manager.allConfigurations(); + QSignalSpy spy(&manager, SIGNAL(updateCompleted())); + manager.updateConfigurations(); //initiate scans + QTRY_VERIFY(spy.count() == 1); //wait for scan to complete + configs = manager.allConfigurations(); + } +public: + QList<QNetworkConfiguration> configs; + QList<QNetworkConfiguration> preScanConfigs; +}; + +// regression test for QTBUG-18795 +void tst_QNetworkConfigurationManager::usedInThread() +{ + QNCMTestThread thread; + connect(&thread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + thread.start(); + QTestEventLoop::instance().enterLoop(5); + QVERIFY(thread.isFinished()); + qDebug() << "prescan:" << thread.preScanConfigs.count(); + qDebug() << "postscan:" << thread.configs.count(); + + QNetworkConfigurationManager manager; + QList<QNetworkConfiguration> preScanConfigs = manager.allConfigurations(); + QSignalSpy spy(&manager, SIGNAL(updateCompleted())); + manager.updateConfigurations(); //initiate scans + QTRY_VERIFY(spy.count() == 1); //wait for scan to complete + QList<QNetworkConfiguration> configs = manager.allConfigurations(); + QCOMPARE(thread.configs, configs); + QCOMPARE(thread.preScanConfigs, preScanConfigs); +} QTEST_MAIN(tst_QNetworkConfigurationManager) #include "tst_qnetworkconfigurationmanager.moc" diff --git a/tests/auto/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp b/tests/auto/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp index 10fa7c6..85b1944 100644 --- a/tests/auto/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp +++ b/tests/auto/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -41,14 +41,17 @@ #include <QtTest/QTest> +#include <QtTest/QTestEventLoop> #include <qcoreapplication.h> #include <qdebug.h> #include <qnetworkproxy.h> +#include <QThread> class tst_QNetworkProxyFactory : public QObject { Q_OBJECT private slots: + void systemProxyForQueryCalledFromThread(); void systemProxyForQuery() const; private: @@ -96,5 +99,31 @@ void tst_QNetworkProxyFactory::systemProxyForQuery() const QFAIL("One or more system proxy lookup failures occurred."); } +class QSPFQThread : public QThread +{ +protected: + virtual void run() + { + proxies = QNetworkProxyFactory::systemProxyForQuery(query); + } +public: + QNetworkProxyQuery query; + QList<QNetworkProxy> proxies; +}; + +//regression test for QTBUG-18799 +void tst_QNetworkProxyFactory::systemProxyForQueryCalledFromThread() +{ + QUrl url(QLatin1String("http://qt.nokia.com")); + QNetworkProxyQuery query(url); + QSPFQThread thread; + thread.query = query; + connect(&thread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + thread.start(); + QTestEventLoop::instance().enterLoop(5); + QVERIFY(thread.isFinished()); + QCOMPARE(thread.proxies, QNetworkProxyFactory::systemProxyForQuery(query)); +} + QTEST_MAIN(tst_QNetworkProxyFactory) #include "tst_qnetworkproxyfactory.moc" |