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

View File

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

View File

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

View File

@ -802,8 +802,6 @@ void QCoreApplicationPrivate::init()
if (!coreappdata()->applicationVersionSet)
coreappdata()->applicationVersion = appVersion();
QLoggingRegistry::instance()->init();
#if QT_CONFIG(library)
// 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

View File

@ -217,13 +217,15 @@ bool QSemaphore::tryAcquire(int n)
bool QSemaphore::tryAcquire(int n, int timeout)
{
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);
QMutexLocker locker(&d->mutex);
qint64 remainingTime = timer.remainingTime();
while (n > d->avail && remainingTime > 0) {
while (n > d->avail && remainingTime != 0) {
if (!d->cond.wait(locker.mutex(), remainingTime))
return false;
remainingTime = timer.remainingTime();

View File

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

View File

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

View File

@ -290,6 +290,18 @@ void tst_QFlags::testSetFlags()
btn.setFlag(Qt::LeftButton, false);
QVERIFY(!btn.testFlag(Qt::LeftButton));
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:

View File

@ -197,10 +197,22 @@ private slots:
// 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;
registry.init();
qputenv("QT_LOGGING_RULES", "qt.foo.bar=true");
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::ConfigRules].size(), 0);
@ -208,7 +220,7 @@ private slots:
// check that QT_LOGGING_RULES take precedence
qputenv("QT_LOGGING_RULES", "Digia.*=true");
registry.init();
registry.initalizeRules();
QCOMPARE(registry.ruleSets[QLoggingRegistry::EnvironmentRules].size(), 2);
QCOMPARE(registry.ruleSets[QLoggingRegistry::EnvironmentRules].at(1).enabled, true);
}
@ -234,7 +246,7 @@ private slots:
file.close();
QLoggingRegistry registry;
registry.init();
registry.initalizeRules();
QCOMPARE(registry.ruleSets[QLoggingRegistry::ConfigRules].size(), 1);
// remove file again
@ -300,6 +312,6 @@ private slots:
}
};
QTEST_MAIN(tst_QLoggingRegistry)
QTEST_APPLESS_MAIN(tst_QLoggingRegistry)
#include "tst_qloggingregistry.moc"

View File

@ -41,6 +41,8 @@ private slots:
void tryAcquireWithTimeout_data();
void tryAcquireWithTimeout();
void tryAcquireWithTimeoutStarvation();
void tryAcquireWithTimeoutForever_data();
void tryAcquireWithTimeoutForever();
void producerConsumer();
void raii();
};
@ -156,21 +158,25 @@ void tst_QSemaphore::tryAcquire()
semaphore.release();
QCOMPARE(semaphore.available(), 1);
QVERIFY(!semaphore.tryAcquire(2));
QVERIFY(!semaphore.tryAcquire(2, 0));
QCOMPARE(semaphore.available(), 1);
semaphore.release();
QCOMPARE(semaphore.available(), 2);
QVERIFY(!semaphore.tryAcquire(3));
QVERIFY(!semaphore.tryAcquire(3, 0));
QCOMPARE(semaphore.available(), 2);
semaphore.release(10);
QCOMPARE(semaphore.available(), 12);
QVERIFY(!semaphore.tryAcquire(100));
QVERIFY(!semaphore.tryAcquire(100, 0));
QCOMPARE(semaphore.available(), 12);
semaphore.release(10);
QCOMPARE(semaphore.available(), 22);
QVERIFY(!semaphore.tryAcquire(100));
QVERIFY(!semaphore.tryAcquire(100, 0));
QCOMPARE(semaphore.available(), 22);
QVERIFY(semaphore.tryAcquire());
@ -179,23 +185,38 @@ void tst_QSemaphore::tryAcquire()
QVERIFY(semaphore.tryAcquire());
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));
QCOMPARE(semaphore.available(), 10);
semaphore.release(10);
QVERIFY(semaphore.tryAcquire(10, 0));
QCOMPARE(semaphore.available(), 10);
QVERIFY(semaphore.tryAcquire(10));
QCOMPARE(semaphore.available(), 0);
// should not be able to acquire more
QVERIFY(!semaphore.tryAcquire());
QVERIFY(!semaphore.tryAcquire(1, 0));
QCOMPARE(semaphore.available(), 0);
QVERIFY(!semaphore.tryAcquire());
QVERIFY(!semaphore.tryAcquire(1, 0));
QCOMPARE(semaphore.available(), 0);
QVERIFY(!semaphore.tryAcquire(10));
QVERIFY(!semaphore.tryAcquire(10, 0));
QCOMPARE(semaphore.available(), 0);
QVERIFY(!semaphore.tryAcquire(10));
QVERIFY(!semaphore.tryAcquire(10, 0));
QCOMPARE(semaphore.available(), 0);
}
@ -345,6 +366,48 @@ void tst_QSemaphore::tryAcquireWithTimeoutStarvation()
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 int AlphabetSize = sizeof(alphabet) - 1;

View File

@ -43,7 +43,7 @@ private slots:
void tst_QDnsLookup_Appless::noApplication()
{
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();
}
@ -53,7 +53,7 @@ void tst_QDnsLookup_Appless::recreateApplication()
char **argv = 0;
for (int i = 0; i < 10; ++i) {
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();
if (!dns.isFinished()) {
QObject::connect(&dns, SIGNAL(finished()),

View File

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

View File

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

View File

@ -1445,8 +1445,15 @@ void tst_QTcpSocket::disconnectWhileLookingUp()
}
// let anything queued happen
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();
// recheck