Merge remote-tracking branch 'origin/5.9' into 5.10

Change-Id: Iede384644c3df5ee01b701806dfdb586dd6bb138
This commit is contained in:
Liang Qi 2017-11-28 11:23:34 +01:00
commit 1139be7b30
16 changed files with 422 additions and 182 deletions

144
dist/changes-5.9.3 vendored Normal file
View File

@ -0,0 +1,144 @@
Qt 5.9.3 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.9.0 through 5.9.2.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
http://doc.qt.io/qt-5/index.html
The Qt version 5.9 series is binary compatible with the 5.8.x series.
Applications compiled for 5.8 will continue to run with 5.9.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Qt 5.9.3 Changes *
****************************************************************************
QtCore
------
- QFileSystemWatcher:
* [QTBUG-64171] Fixed a bug that would cause the application to crash if
QFileSystemWatcher was created in an auxiliary thread on Windows.
- QStorageInfo:
* [QTBUG-61420] Fixed decoding of volume labels containing certain
uncommon characters on Linux.
- QThreadPool:
* Improved performance with large amount of QRunnable items.
QtGui
------
- [QTBUG-64239] Fixed memory corruption on scaled emojis.
- [QTBUG-63846] Fixed dragging inside a modal window when a
QShapedPixmapWindow is used.
- [QTBUG-61777] Fixed painting of zero-length lines with scaling.
- [QTBUG-61244] Fixed centering of some items in layouts.
- [QTBUG-63168] Fixed a crash when reparenting QWindowContainer.
QtNetwork
---------
- QHostAddress:
* [QTBUG-63764] Fixed a problem in QHostAddress not detaching in its
setters and thus spoiling shared data.
- QNetworkAccessManager:
* [QTBUG-63075] Added support for HTTP status 308.
* [QTBUG-61300] Fixed a problem with mixing headers from different
responses.
* [QTBUG-63471] Fixed redirects support in HTTP/2 protocol handler.
* [QTBUG-63313] Fixed cookies received during a redirect not being
applied in the redirect.
* [QTBUG-63142] Fixed HTTP method always being changed to GET when
redirected with 307 and 308.
- QNetworkCookieJar:
* Fixed cookies with a root path ("/") not matching an empty path ("").
QtSql
------
- PostgreSQL:
* Fixed handling of binary data for PostgreSQL 9.x and later
* Fixed detection of PostgreSQL 9.x and later
- OCI:
* [QTBUG-57765] Fixed a bug that would see some cached results returned
when issuing a forward only query
QtWidgets
---------
- QAction:
* [QTBUG-62006] Ensured setData() does not emit changed() if no change
happened.
- QDockWidget:
* [QTBUG-63526] Fixed an issue in QDockWidgets where the widget would
not resize despite showing a resize cursor.
- QHeaderView:
* [QTBUG-54601] Fixed resizing when hidden sections were involved.
* [QTBUG-64036] Ensured maximumSectionSize property is honored during
resizeSections().
- QListView:
* [QTBUG-45427] Fixed the laying out of a QListView in a grid layout
after the dataChanged() signal is emitted.
- QMenuBar
* [QTBUG-34160] Fixed a problem with adding the same QAction to more than
one menu.
- QWidget
* [QTBUG-56860] Fixed widget losing focus after showing menu second time.
- QWizard:
* [QTBUG-46894] Fixed the shortcut for the Next button on Windows.
Platform-specific changes
-------------------------
- Cocoa:
* optimize backingstore flush on 10-bit displays
* [QTBUG-57076] [QTBUG-63712] Attach menu items when updating the menubar
* [QTBUG-63444] Toggle titlebar transparency to support unified toolbar
- iOS:
* [QTBUG-57428][QTBUG-63660] add support for adding mimetypes other than text
on the clipboard
- Windows:
* [QTBUG-63654] Windows font database: Remove clamping of default font size
- X11:
* [QTBUG-48034] Don't misdetect certain trackballs as tablets
* [QTBUG-62840] Fix crash on X servers with BGR888 display
Third-Party Code
----------------
- Improved documentation about Freetype 2 licenses.
- Updated Sqlite to fix CVE-2017-10989.
- Updated bundled libpng to version 1.6.34.
Tools
-----
* qmake:
- [QTBUG-63409] Fixed a build error with MSVC when concrt.h was included
while exceptions are disabled.
- [QTBUG-62985] Fixed a bug that caused the accidental creation of files
called "NUL" when using MinGW.

View File

@ -723,184 +723,189 @@ public class QtActivityDelegate
Bundle extras = m_activity.getIntent().getExtras(); Bundle extras = m_activity.getIntent().getExtras();
if (extras != null) { if (extras != null) {
if ( /*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0 try {
&&*/ extras.containsKey("debug_ping") final String dc = "--Added-by-androiddeployqt--/debugger.command";
&& extras.getString("debug_ping").equals("true")) { String debuggerCommand =
try { new BufferedReader(new InputStreamReader(m_activity.getAssets().open(dc))).readLine();
final String dc = "--Added-by-androiddeployqt--/debugger.command"; if ( /*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0
String debuggerCommand = &&*/ extras.containsKey("debug_ping")
new BufferedReader(new InputStreamReader(m_activity.getAssets().open(dc))).readLine(); && extras.getString("debug_ping").equals("true")) {
String packagePath = try {
m_activity.getPackageManager().getApplicationInfo(m_activity.getPackageName(), String packagePath =
PackageManager.GET_CONFIGURATIONS).dataDir + "/"; m_activity.getPackageManager().getApplicationInfo(m_activity.getPackageName(),
PackageManager.GET_CONFIGURATIONS).dataDir + "/";
debugLog("extra parameters: " + extras); debugLog("extra parameters: " + extras);
String packageName = m_activity.getPackageName(); String packageName = m_activity.getPackageName();
String pingFile = extras.getString("ping_file"); String pingFile = extras.getString("ping_file");
String pongFile = extras.getString("pong_file"); String pongFile = extras.getString("pong_file");
String gdbserverSocket = extras.getString("gdbserver_socket"); String gdbserverSocket = extras.getString("gdbserver_socket");
String gdbserverCommand = packagePath + debuggerCommand + gdbserverSocket; String gdbserverCommand = packagePath + debuggerCommand + gdbserverSocket;
String pingSocket = extras.getString("ping_socket"); String pingSocket = extras.getString("ping_socket");
boolean usePing = pingFile != null; boolean usePing = pingFile != null;
boolean usePong = pongFile != null; boolean usePong = pongFile != null;
boolean useSocket = gdbserverSocket != null; boolean useSocket = gdbserverSocket != null;
boolean usePingSocket = pingSocket != null; boolean usePingSocket = pingSocket != null;
int napTime = 200; // milliseconds between file accesses int napTime = 200; // milliseconds between file accesses
int timeOut = 30000; // ms until we give up on ping and pong int timeOut = 30000; // ms until we give up on ping and pong
int maxAttempts = timeOut / napTime; int maxAttempts = timeOut / napTime;
if (gdbserverSocket != null) { if (gdbserverSocket != null) {
debugLog("removing gdb socket " + gdbserverSocket); debugLog("removing gdb socket " + gdbserverSocket);
new File(gdbserverSocket).delete(); new File(gdbserverSocket).delete();
}
if (usePing) {
debugLog("removing ping file " + pingFile);
File ping = new File(pingFile);
if (ping.exists()) {
if (!ping.delete())
debugLog("ping file cannot be deleted");
} }
}
if (usePong) { if (usePing) {
debugLog("removing pong file " + pongFile); debugLog("removing ping file " + pingFile);
File pong = new File(pongFile); File ping = new File(pingFile);
if (pong.exists()) { if (ping.exists()) {
if (!pong.delete()) if (!ping.delete())
debugLog("pong file cannot be deleted"); debugLog("ping file cannot be deleted");
}
}
debugLog("starting " + gdbserverCommand);
m_debuggerProcess = Runtime.getRuntime().exec(gdbserverCommand);
debugLog("gdbserver started");
if (useSocket) {
int i;
for (i = 0; i < maxAttempts; ++i) {
debugLog("waiting for socket at " + gdbserverSocket + ", attempt " + i);
File file = new File(gdbserverSocket);
if (file.exists()) {
file.setReadable(true, false);
file.setWritable(true, false);
file.setExecutable(true, false);
break;
} }
Thread.sleep(napTime);
} }
if (i == maxAttempts) { if (usePong) {
debugLog("time out when waiting for debug socket"); debugLog("removing pong file " + pongFile);
return false; File pong = new File(pongFile);
if (pong.exists()) {
if (!pong.delete())
debugLog("pong file cannot be deleted");
}
} }
debugLog("socket ok"); debugLog("starting " + gdbserverCommand);
} else { m_debuggerProcess = Runtime.getRuntime().exec(gdbserverCommand);
debugLog("socket not used"); debugLog("gdbserver started");
}
if (usePingSocket) { if (useSocket) {
DebugWaitRunnable runnable = new DebugWaitRunnable(pingSocket); int i;
Thread waitThread = new Thread(runnable); for (i = 0; i < maxAttempts; ++i) {
waitThread.start(); debugLog("waiting for socket at " + gdbserverSocket + ", attempt " + i);
File file = new File(gdbserverSocket);
if (file.exists()) {
file.setReadable(true, false);
file.setWritable(true, false);
file.setExecutable(true, false);
break;
}
Thread.sleep(napTime);
}
int i; if (i == maxAttempts) {
for (i = 0; i < maxAttempts && waitThread.isAlive(); ++i) { debugLog("time out when waiting for debug socket");
debugLog("Waiting for debug socket connect"); return false;
debugLog("go to sleep"); }
Thread.sleep(napTime);
}
if (i == maxAttempts) { debugLog("socket ok");
debugLog("time out when waiting for ping socket");
runnable.shutdown();
return false;
}
if (runnable.wasFailure) {
debugLog("Could not connect to debug client");
return false;
} else { } else {
debugLog("Got pid acknowledgment"); debugLog("socket not used");
} }
}
if (usePing) { if (usePingSocket) {
// Tell we are ready. DebugWaitRunnable runnable = new DebugWaitRunnable(pingSocket);
debugLog("writing ping at " + pingFile); Thread waitThread = new Thread(runnable);
FileWriter writer = new FileWriter(pingFile); waitThread.start();
writer.write("" + android.os.Process.myPid());
writer.close();
File file = new File(pingFile);
file.setReadable(true, false);
file.setWritable(true, false);
file.setExecutable(true, false);
debugLog("wrote ping");
} else {
debugLog("ping not requested");
}
// Wait until other side is ready. int i;
if (usePong) { for (i = 0; i < maxAttempts && waitThread.isAlive(); ++i) {
int i; debugLog("Waiting for debug socket connect");
for (i = 0; i < maxAttempts; ++i) { debugLog("go to sleep");
debugLog("waiting for pong at " + pongFile + ", attempt " + i); Thread.sleep(napTime);
File file = new File(pongFile);
if (file.exists()) {
file.delete();
break;
} }
debugLog("go to sleep");
Thread.sleep(napTime);
}
debugLog("Removing pingFile " + pingFile);
new File(pingFile).delete();
if (i == maxAttempts) { if (i == maxAttempts) {
debugLog("time out when waiting for pong file"); debugLog("time out when waiting for ping socket");
return false; runnable.shutdown();
return false;
}
if (runnable.wasFailure) {
debugLog("Could not connect to debug client");
return false;
} else {
debugLog("Got pid acknowledgment");
}
} }
debugLog("got pong " + pongFile); if (usePing) {
} else { // Tell we are ready.
debugLog("pong not requested"); debugLog("writing ping at " + pingFile);
FileWriter writer = new FileWriter(pingFile);
writer.write("" + android.os.Process.myPid());
writer.close();
File file = new File(pingFile);
file.setReadable(true, false);
file.setWritable(true, false);
file.setExecutable(true, false);
debugLog("wrote ping");
} else {
debugLog("ping not requested");
}
// Wait until other side is ready.
if (usePong) {
int i;
for (i = 0; i < maxAttempts; ++i) {
debugLog("waiting for pong at " + pongFile + ", attempt " + i);
File file = new File(pongFile);
if (file.exists()) {
file.delete();
break;
}
debugLog("go to sleep");
Thread.sleep(napTime);
}
debugLog("Removing pingFile " + pingFile);
new File(pingFile).delete();
if (i == maxAttempts) {
debugLog("time out when waiting for pong file");
return false;
}
debugLog("got pong " + pongFile);
} else {
debugLog("pong not requested");
}
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (SecurityException se) {
se.printStackTrace();
} }
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (SecurityException se) {
se.printStackTrace();
} }
}
if (/*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0 if (/*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0
&&*/ extras.containsKey("qml_debug") &&*/ extras.containsKey("qml_debug")
&& extras.getString("qml_debug").equals("true")) { && extras.getString("qml_debug").equals("true")) {
String qmljsdebugger; String qmljsdebugger;
if (extras.containsKey("qmljsdebugger")) { if (extras.containsKey("qmljsdebugger")) {
qmljsdebugger = extras.getString("qmljsdebugger"); qmljsdebugger = extras.getString("qmljsdebugger");
qmljsdebugger.replaceAll("\\s", ""); // remove whitespace for security qmljsdebugger.replaceAll("\\s", ""); // remove whitespace for security
} else { } else {
qmljsdebugger = "port:3768"; qmljsdebugger = "port:3768";
}
m_applicationParameters += "\t-qmljsdebugger=" + qmljsdebugger;
} }
m_applicationParameters += "\t-qmljsdebugger=" + qmljsdebugger;
}
if (extras.containsKey("extraenvvars")) { if (extras.containsKey("extraenvvars")) {
try { try {
m_environmentVariables += "\t" + new String(Base64.decode(extras.getString("extraenvvars"), Base64.DEFAULT), "UTF-8"); m_environmentVariables += "\t" + new String(Base64.decode(extras.getString("extraenvvars"), Base64.DEFAULT), "UTF-8");
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
}
} }
}
if (extras.containsKey("extraappparams")) { if (extras.containsKey("extraappparams")) {
try { try {
m_applicationParameters += "\t" + new String(Base64.decode(extras.getString("extraappparams"), Base64.DEFAULT), "UTF-8"); m_applicationParameters += "\t" + new String(Base64.decode(extras.getString("extraappparams"), Base64.DEFAULT), "UTF-8");
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
}
} }
} catch (Exception e) {
// This is not an error, so keep it silent
// e.printStackTrace();
} }
} // extras != null } // extras != null

View File

@ -150,7 +150,7 @@ public:
Q_DECL_CONSTEXPR inline bool testFlag(Enum f) const Q_DECL_NOTHROW { return (i & Int(f)) == Int(f) && (Int(f) != 0 || i == Int(f) ); } Q_DECL_CONSTEXPR inline bool testFlag(Enum f) const Q_DECL_NOTHROW { return (i & Int(f)) == Int(f) && (Int(f) != 0 || i == Int(f) ); }
Q_DECL_RELAXED_CONSTEXPR inline QFlags &setFlag(Enum f, bool on = true) Q_DECL_NOTHROW Q_DECL_RELAXED_CONSTEXPR inline QFlags &setFlag(Enum f, bool on = true) Q_DECL_NOTHROW
{ {
return on ? (*this |= f) : (*this &= ~f); return on ? (*this |= f) : (*this &= ~Int(f));
} }
private: private:

View File

@ -255,6 +255,7 @@ void QLoggingSettingsParser::parseNextLine(QStringRef line)
QLoggingRegistry::QLoggingRegistry() QLoggingRegistry::QLoggingRegistry()
: categoryFilter(defaultCategoryFilter) : categoryFilter(defaultCategoryFilter)
{ {
initalizeRules(); // Init on first use
} }
static bool qtLoggingDebug() static bool qtLoggingDebug()
@ -283,7 +284,7 @@ static QVector<QLoggingRule> loadRulesFromFile(const QString &filePath)
Initializes the rules database by loading Initializes the rules database by loading
$QT_LOGGING_CONF, $QT_LOGGING_RULES, and .config/QtProject/qtlogging.ini. $QT_LOGGING_CONF, $QT_LOGGING_RULES, and .config/QtProject/qtlogging.ini.
*/ */
void QLoggingRegistry::init() void QLoggingRegistry::initalizeRules()
{ {
QVector<QLoggingRule> er, qr, cr; QVector<QLoggingRule> er, qr, cr;
// get rules from environment // get rules from environment

View File

@ -113,7 +113,7 @@ class Q_AUTOTEST_EXPORT QLoggingRegistry
public: public:
QLoggingRegistry(); QLoggingRegistry();
void init(); void initalizeRules();
void registerCategory(QLoggingCategory *category, QtMsgType enableForLevel); void registerCategory(QLoggingCategory *category, QtMsgType enableForLevel);
void unregisterCategory(QLoggingCategory *category); void unregisterCategory(QLoggingCategory *category);

View File

@ -802,8 +802,6 @@ void QCoreApplicationPrivate::init()
if (!coreappdata()->applicationVersionSet) if (!coreappdata()->applicationVersionSet)
coreappdata()->applicationVersion = appVersion(); coreappdata()->applicationVersion = appVersion();
QLoggingRegistry::instance()->init();
#if QT_CONFIG(library) #if QT_CONFIG(library)
// Reset the lib paths, so that they will be recomputed, taking the availability of argv[0] // Reset the lib paths, so that they will be recomputed, taking the availability of argv[0]
// into account. If necessary, recompute right away and replay the manual changes on top of the // into account. If necessary, recompute right away and replay the manual changes on top of the

View File

@ -217,13 +217,15 @@ bool QSemaphore::tryAcquire(int n)
bool QSemaphore::tryAcquire(int n, int timeout) bool QSemaphore::tryAcquire(int n, int timeout)
{ {
Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative"); Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative");
if (timeout < 0)
return tryAcquire(n); // We're documented to accept any negative value as "forever"
// but QDeadlineTimer only accepts -1.
timeout = qMax(timeout, -1);
QDeadlineTimer timer(timeout); QDeadlineTimer timer(timeout);
QMutexLocker locker(&d->mutex); QMutexLocker locker(&d->mutex);
qint64 remainingTime = timer.remainingTime(); qint64 remainingTime = timer.remainingTime();
while (n > d->avail && remainingTime > 0) { while (n > d->avail && remainingTime != 0) {
if (!d->cond.wait(locker.mutex(), remainingTime)) if (!d->cond.wait(locker.mutex(), remainingTime))
return false; return false;
remainingTime = timer.remainingTime(); remainingTime = timer.remainingTime();

View File

@ -1231,20 +1231,20 @@ void QHttpNetworkConnectionPrivate::_q_hostLookupFinished(const QHostInfo &info)
if (dequeueRequest(channels[0].socket)) { if (dequeueRequest(channels[0].socket)) {
emitReplyError(channels[0].socket, channels[0].reply, QNetworkReply::HostNotFoundError); emitReplyError(channels[0].socket, channels[0].reply, QNetworkReply::HostNotFoundError);
networkLayerState = QHttpNetworkConnectionPrivate::Unknown; networkLayerState = QHttpNetworkConnectionPrivate::Unknown;
} } else if (connectionType == QHttpNetworkConnection::ConnectionTypeSPDY
#ifndef QT_NO_SSL || connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2) {
else if (connectionType == QHttpNetworkConnection::ConnectionTypeSPDY) {
for (const HttpMessagePair &spdyPair : qAsConst(channels[0].spdyRequestsToSend)) { for (const HttpMessagePair &spdyPair : qAsConst(channels[0].spdyRequestsToSend)) {
// emit error for all replies // emit error for all replies
QHttpNetworkReply *currentReply = spdyPair.second; QHttpNetworkReply *currentReply = spdyPair.second;
Q_ASSERT(currentReply); Q_ASSERT(currentReply);
emitReplyError(channels[0].socket, currentReply, QNetworkReply::HostNotFoundError); emitReplyError(channels[0].socket, currentReply, QNetworkReply::HostNotFoundError);
} }
} } else {
#endif // QT_NO_SSL // Should not happen: we start a host lookup before sending a request,
else { // so it's natural to have requests either in SPDY/HTTP/2 queue,
// Should not happen // or in low/high priority queues.
qWarning("QHttpNetworkConnectionPrivate::_q_hostLookupFinished could not de-queue request"); qWarning("QHttpNetworkConnectionPrivate::_q_hostLookupFinished"
" could not de-queue request, failed to report HostNotFoundError");
networkLayerState = QHttpNetworkConnectionPrivate::Unknown; networkLayerState = QHttpNetworkConnectionPrivate::Unknown;
} }
} }

View File

@ -1213,10 +1213,8 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL
msg.dwBufferCount = 1; msg.dwBufferCount = 1;
msg.name = reinterpret_cast<LPSOCKADDR>(&aa); msg.name = reinterpret_cast<LPSOCKADDR>(&aa);
msg.namelen = sizeof(aa); msg.namelen = sizeof(aa);
if (options & (QAbstractSocketEngine::WantDatagramHopLimit | QAbstractSocketEngine::WantDatagramDestination)) { msg.Control.buf = cbuf;
msg.Control.buf = cbuf; msg.Control.len = sizeof(cbuf);
msg.Control.len = sizeof(cbuf);
}
DWORD flags = 0; DWORD flags = 0;
DWORD bytesRead = 0; DWORD bytesRead = 0;

View File

@ -290,6 +290,18 @@ void tst_QFlags::testSetFlags()
btn.setFlag(Qt::LeftButton, false); btn.setFlag(Qt::LeftButton, false);
QVERIFY(!btn.testFlag(Qt::LeftButton)); QVERIFY(!btn.testFlag(Qt::LeftButton));
QVERIFY(!btn.testFlag(Qt::MidButton)); QVERIFY(!btn.testFlag(Qt::MidButton));
MyStrictFlags flags;
flags.setFlag(MyStrictEnum::StrictOne);
flags.setFlag(MyStrictEnum::StrictTwo, true);
QVERIFY(flags.testFlag(MyStrictEnum::StrictOne));
QVERIFY(flags.testFlag(MyStrictEnum::StrictTwo));
QVERIFY(!flags.testFlag(MyStrictEnum::StrictFour));
flags.setFlag(MyStrictEnum::StrictTwo, false);
QVERIFY(flags.testFlag(MyStrictEnum::StrictOne));
QVERIFY(!flags.testFlag(MyStrictEnum::StrictTwo));
QVERIFY(!flags.testFlag(MyStrictEnum::StrictFour));
} }
// (statically) check QTypeInfo for QFlags instantiations: // (statically) check QTypeInfo for QFlags instantiations:

View File

@ -197,10 +197,22 @@ private slots:
// Check whether QT_LOGGING_CONF is picked up from environment // Check whether QT_LOGGING_CONF is picked up from environment
// //
qputenv("QT_LOGGING_CONF", QFINDTESTDATA("qtlogging.ini").toLocal8Bit()); Q_ASSERT(!qApp); // Rules should not require an app to resolve
QLoggingRegistry registry; qputenv("QT_LOGGING_RULES", "qt.foo.bar=true");
registry.init(); QLoggingCategory qtEnabledByLoggingRule("qt.foo.bar");
QCOMPARE(qtEnabledByLoggingRule.isDebugEnabled(), true);
QLoggingCategory qtDisabledByDefault("qt.foo.baz");
QCOMPARE(qtDisabledByDefault.isDebugEnabled(), false);
QLoggingRegistry &registry = *QLoggingRegistry::instance();
QCOMPARE(registry.ruleSets[QLoggingRegistry::ApiRules].size(), 0);
QCOMPARE(registry.ruleSets[QLoggingRegistry::ConfigRules].size(), 0);
QCOMPARE(registry.ruleSets[QLoggingRegistry::EnvironmentRules].size(), 1);
qunsetenv("QT_LOGGING_RULES");
qputenv("QT_LOGGING_CONF", QFINDTESTDATA("qtlogging.ini").toLocal8Bit());
registry.initalizeRules();
QCOMPARE(registry.ruleSets[QLoggingRegistry::ApiRules].size(), 0); QCOMPARE(registry.ruleSets[QLoggingRegistry::ApiRules].size(), 0);
QCOMPARE(registry.ruleSets[QLoggingRegistry::ConfigRules].size(), 0); QCOMPARE(registry.ruleSets[QLoggingRegistry::ConfigRules].size(), 0);
@ -208,7 +220,7 @@ private slots:
// check that QT_LOGGING_RULES take precedence // check that QT_LOGGING_RULES take precedence
qputenv("QT_LOGGING_RULES", "Digia.*=true"); qputenv("QT_LOGGING_RULES", "Digia.*=true");
registry.init(); registry.initalizeRules();
QCOMPARE(registry.ruleSets[QLoggingRegistry::EnvironmentRules].size(), 2); QCOMPARE(registry.ruleSets[QLoggingRegistry::EnvironmentRules].size(), 2);
QCOMPARE(registry.ruleSets[QLoggingRegistry::EnvironmentRules].at(1).enabled, true); QCOMPARE(registry.ruleSets[QLoggingRegistry::EnvironmentRules].at(1).enabled, true);
} }
@ -234,7 +246,7 @@ private slots:
file.close(); file.close();
QLoggingRegistry registry; QLoggingRegistry registry;
registry.init(); registry.initalizeRules();
QCOMPARE(registry.ruleSets[QLoggingRegistry::ConfigRules].size(), 1); QCOMPARE(registry.ruleSets[QLoggingRegistry::ConfigRules].size(), 1);
// remove file again // remove file again
@ -300,6 +312,6 @@ private slots:
} }
}; };
QTEST_MAIN(tst_QLoggingRegistry) QTEST_APPLESS_MAIN(tst_QLoggingRegistry)
#include "tst_qloggingregistry.moc" #include "tst_qloggingregistry.moc"

View File

@ -41,6 +41,8 @@ private slots:
void tryAcquireWithTimeout_data(); void tryAcquireWithTimeout_data();
void tryAcquireWithTimeout(); void tryAcquireWithTimeout();
void tryAcquireWithTimeoutStarvation(); void tryAcquireWithTimeoutStarvation();
void tryAcquireWithTimeoutForever_data();
void tryAcquireWithTimeoutForever();
void producerConsumer(); void producerConsumer();
void raii(); void raii();
}; };
@ -156,21 +158,25 @@ void tst_QSemaphore::tryAcquire()
semaphore.release(); semaphore.release();
QCOMPARE(semaphore.available(), 1); QCOMPARE(semaphore.available(), 1);
QVERIFY(!semaphore.tryAcquire(2)); QVERIFY(!semaphore.tryAcquire(2));
QVERIFY(!semaphore.tryAcquire(2, 0));
QCOMPARE(semaphore.available(), 1); QCOMPARE(semaphore.available(), 1);
semaphore.release(); semaphore.release();
QCOMPARE(semaphore.available(), 2); QCOMPARE(semaphore.available(), 2);
QVERIFY(!semaphore.tryAcquire(3)); QVERIFY(!semaphore.tryAcquire(3));
QVERIFY(!semaphore.tryAcquire(3, 0));
QCOMPARE(semaphore.available(), 2); QCOMPARE(semaphore.available(), 2);
semaphore.release(10); semaphore.release(10);
QCOMPARE(semaphore.available(), 12); QCOMPARE(semaphore.available(), 12);
QVERIFY(!semaphore.tryAcquire(100)); QVERIFY(!semaphore.tryAcquire(100));
QVERIFY(!semaphore.tryAcquire(100, 0));
QCOMPARE(semaphore.available(), 12); QCOMPARE(semaphore.available(), 12);
semaphore.release(10); semaphore.release(10);
QCOMPARE(semaphore.available(), 22); QCOMPARE(semaphore.available(), 22);
QVERIFY(!semaphore.tryAcquire(100)); QVERIFY(!semaphore.tryAcquire(100));
QVERIFY(!semaphore.tryAcquire(100, 0));
QCOMPARE(semaphore.available(), 22); QCOMPARE(semaphore.available(), 22);
QVERIFY(semaphore.tryAcquire()); QVERIFY(semaphore.tryAcquire());
@ -179,23 +185,38 @@ void tst_QSemaphore::tryAcquire()
QVERIFY(semaphore.tryAcquire()); QVERIFY(semaphore.tryAcquire());
QCOMPARE(semaphore.available(), 20); QCOMPARE(semaphore.available(), 20);
semaphore.release(2);
QVERIFY(semaphore.tryAcquire(1, 0));
QCOMPARE(semaphore.available(), 21);
QVERIFY(semaphore.tryAcquire(1, 0));
QCOMPARE(semaphore.available(), 20);
QVERIFY(semaphore.tryAcquire(10)); QVERIFY(semaphore.tryAcquire(10));
QCOMPARE(semaphore.available(), 10); QCOMPARE(semaphore.available(), 10);
semaphore.release(10);
QVERIFY(semaphore.tryAcquire(10, 0));
QCOMPARE(semaphore.available(), 10);
QVERIFY(semaphore.tryAcquire(10)); QVERIFY(semaphore.tryAcquire(10));
QCOMPARE(semaphore.available(), 0); QCOMPARE(semaphore.available(), 0);
// should not be able to acquire more // should not be able to acquire more
QVERIFY(!semaphore.tryAcquire()); QVERIFY(!semaphore.tryAcquire());
QVERIFY(!semaphore.tryAcquire(1, 0));
QCOMPARE(semaphore.available(), 0); QCOMPARE(semaphore.available(), 0);
QVERIFY(!semaphore.tryAcquire()); QVERIFY(!semaphore.tryAcquire());
QVERIFY(!semaphore.tryAcquire(1, 0));
QCOMPARE(semaphore.available(), 0); QCOMPARE(semaphore.available(), 0);
QVERIFY(!semaphore.tryAcquire(10)); QVERIFY(!semaphore.tryAcquire(10));
QVERIFY(!semaphore.tryAcquire(10, 0));
QCOMPARE(semaphore.available(), 0); QCOMPARE(semaphore.available(), 0);
QVERIFY(!semaphore.tryAcquire(10)); QVERIFY(!semaphore.tryAcquire(10));
QVERIFY(!semaphore.tryAcquire(10, 0));
QCOMPARE(semaphore.available(), 0); QCOMPARE(semaphore.available(), 0);
} }
@ -345,6 +366,48 @@ void tst_QSemaphore::tryAcquireWithTimeoutStarvation()
QVERIFY(consumer.wait()); QVERIFY(consumer.wait());
} }
void tst_QSemaphore::tryAcquireWithTimeoutForever_data()
{
QTest::addColumn<int>("timeout");
QTest::newRow("-1") << -1;
// tryAcquire is documented to take any negative value as "forever"
QTest::newRow("INT_MIN") << INT_MIN;
}
void tst_QSemaphore::tryAcquireWithTimeoutForever()
{
enum { WaitTime = 1000 };
struct Thread : public QThread {
QSemaphore sem;
void run() override
{
QTest::qWait(WaitTime);
sem.release(2);
}
};
QFETCH(int, timeout);
Thread t;
// sanity check it works if we can immediately acquire
t.sem.release(11);
QVERIFY(t.sem.tryAcquire(1, timeout));
QVERIFY(t.sem.tryAcquire(10, timeout));
// verify that we do wait for at least WaitTime if we can't acquire immediately
QElapsedTimer timer;
timer.start();
t.start();
QVERIFY(t.sem.tryAcquire(1, timeout));
QVERIFY(timer.elapsed() >= WaitTime);
QVERIFY(t.wait());
QCOMPARE(t.sem.available(), 1);
}
const char alphabet[] = "ACGTH"; const char alphabet[] = "ACGTH";
const int AlphabetSize = sizeof(alphabet) - 1; const int AlphabetSize = sizeof(alphabet) - 1;

View File

@ -43,7 +43,7 @@ private slots:
void tst_QDnsLookup_Appless::noApplication() void tst_QDnsLookup_Appless::noApplication()
{ {
QTest::ignoreMessage(QtWarningMsg, "QDnsLookup requires a QCoreApplication"); QTest::ignoreMessage(QtWarningMsg, "QDnsLookup requires a QCoreApplication");
QDnsLookup dns(QDnsLookup::A, "a-single.test.macieira.org"); QDnsLookup dns(QDnsLookup::A, "a-single.test.qt-project.org");
dns.lookup(); dns.lookup();
} }
@ -53,7 +53,7 @@ void tst_QDnsLookup_Appless::recreateApplication()
char **argv = 0; char **argv = 0;
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);
QDnsLookup dns(QDnsLookup::A, "a-single.test.macieira.org"); QDnsLookup dns(QDnsLookup::A, "a-single.test.qt-project.org");
dns.lookup(); dns.lookup();
if (!dns.isFinished()) { if (!dns.isFinished()) {
QObject::connect(&dns, SIGNAL(finished()), QObject::connect(&dns, SIGNAL(finished()),

View File

@ -72,7 +72,7 @@
#include "../../../network-settings.h" #include "../../../network-settings.h"
#define TEST_DOMAIN ".test.macieira.org" #define TEST_DOMAIN ".test.qt-project.org"
class tst_QHostInfo : public QObject class tst_QHostInfo : public QObject

View File

@ -6,8 +6,6 @@ windows
windows windows
[invalidProxy:socks5-on-http] [invalidProxy:socks5-on-http]
windows windows
[disconnectWhileLookingUp]
windows
[timeoutConnect:ip] [timeoutConnect:ip]
windows windows
] ]

View File

@ -1445,8 +1445,15 @@ void tst_QTcpSocket::disconnectWhileLookingUp()
} }
// let anything queued happen // let anything queued happen
QEventLoop loop; QEventLoop loop;
QTimer::singleShot(50, &loop, SLOT(quit())); // If 'doClose' is false then we called '::waitForDisconnected' earlier, meaning
// we are already 'Unconnected'. So we don't need to wait for any potentially slow host lookups.
QTimer::singleShot(doClose ? 4000 : 50, &loop, SLOT(quit()));
connect(socket, &QTcpSocket::stateChanged, [&loop](QAbstractSocket::SocketState state) {
if (state == QAbstractSocket::UnconnectedState)
loop.exit(); // we don't need to wait for the timer to expire; we're done.
});
loop.exec(); loop.exec();
// recheck // recheck