diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c index e55ef47683..3bf7fc3deb 100644 --- a/src/3rdparty/forkfd/forkfd.c +++ b/src/3rdparty/forkfd/forkfd.c @@ -61,6 +61,9 @@ #if _POSIX_VERSION-0 >= 200809L || _XOPEN_VERSION-0 >= 500 # define HAVE_WAITID 1 #endif +#if !defined(WEXITED) || !defined(WNOWAIT) +# undef HAVE_WAITID +#endif #if defined(__FreeBSD__) # define HAVE_PIPE2 1 diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index 371e4e4a61..1b7ec8abbb 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -107,13 +107,15 @@ public class QtNative } } - public static boolean openURL(String url) + public static boolean openURL(String url, String mime) { boolean ok = true; try { Uri uri = Uri.parse(url); Intent intent = new Intent(Intent.ACTION_VIEW, uri); + if (!mime.isEmpty()) + intent.setDataAndType(uri, mime); activity().startActivity(intent); } catch (Exception e) { e.printStackTrace(); diff --git a/src/angle/src/compiler/preprocessor/preprocessor.pro b/src/angle/src/compiler/preprocessor/preprocessor.pro index 759a3399b4..12f644870d 100644 --- a/src/angle/src/compiler/preprocessor/preprocessor.pro +++ b/src/angle/src/compiler/preprocessor/preprocessor.pro @@ -41,15 +41,15 @@ SOURCES += \ $$ANGLE_DIR/src/compiler/preprocessor/Token.cpp # NOTE: 'flex' and 'bison' can be found in qt5/gnuwin32/bin -flex.commands = $$addGnuPath(flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME} -flex.output = ${QMAKE_FILE_BASE}.cpp +flex.commands = $$addGnuPath(flex) --noline --nounistd --outfile=${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} +flex.output = $${BUILDSUBDIR}${QMAKE_FILE_BASE}.cpp flex.input = FLEX_SOURCES flex.dependency_type = TYPE_C flex.variable_out = GENERATED_SOURCES QMAKE_EXTRA_COMPILERS += flex -bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME} -bison.output = ${QMAKE_FILE_BASE}.cpp +bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} +bison.output = $${BUILDSUBDIR}${QMAKE_FILE_BASE}.cpp bison.input = BISON_SOURCES bison.dependency_type = TYPE_C bison.variable_out = GENERATED_SOURCES diff --git a/src/angle/src/compiler/translator.pro b/src/angle/src/compiler/translator.pro index 9572a51ad4..b40aa96319 100644 --- a/src/angle/src/compiler/translator.pro +++ b/src/angle/src/compiler/translator.pro @@ -163,16 +163,18 @@ SOURCES += \ # NOTE: 'flex' and 'bison' can be found in qt5/gnuwin32/bin -flex.commands = $$addGnuPath(flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME} -flex.output = ${QMAKE_FILE_BASE}_lex.cpp +flex.commands = $$addGnuPath(flex) --noline --nounistd --outfile=${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} +flex.output = $${BUILDSUBDIR}${QMAKE_FILE_BASE}_lex.cpp flex.input = FLEX_SOURCES flex.dependency_type = TYPE_C flex.variable_out = GENERATED_SOURCES QMAKE_EXTRA_COMPILERS += flex -bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \ - --output=${QMAKE_FILE_BASE}_tab.cpp ${QMAKE_FILE_NAME} -bison.output = ${QMAKE_FILE_BASE}_tab.h +defineReplace(myDirName) { return($$dirname(1)) } +bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_OUT} \ + --output=${QMAKE_FUNC_FILE_OUT_myDirName}$$QMAKE_DIR_SEP${QMAKE_FILE_OUT_BASE}.cpp \ + ${QMAKE_FILE_NAME} +bison.output = $${BUILDSUBDIR}${QMAKE_FILE_BASE}_tab.h bison.input = BISON_SOURCES bison.dependency_type = TYPE_C bison.variable_out = GENERATED_SOURCES @@ -182,10 +184,10 @@ QMAKE_EXTRA_COMPILERS += bison # have one output file even if the command generates two. MAKEFILE_NOOP_COMMAND = @echo -n msvc: MAKEFILE_NOOP_COMMAND = @echo >NUL -bison_impl.output = ${QMAKE_FILE_BASE}_tab.cpp +bison_impl.output = $${BUILDSUBDIR}${QMAKE_FILE_BASE}_tab.cpp bison_impl.input = BISON_SOURCES bison_impl.commands = $$MAKEFILE_NOOP_COMMAND -bison_impl.depends = ${QMAKE_FILE_BASE}_tab.h -bison_impl.output = ${QMAKE_FILE_BASE}_tab.cpp +bison_impl.depends = $${BUILDSUBDIR}${QMAKE_FILE_BASE}_tab.h +bison_impl.output = $${BUILDSUBDIR}${QMAKE_FILE_BASE}_tab.cpp bison_impl.variable_out = GENERATED_SOURCES QMAKE_EXTRA_COMPILERS += bison_impl diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri index 0d75245ec5..085913ac83 100644 --- a/src/angle/src/config.pri +++ b/src/angle/src/config.pri @@ -53,6 +53,8 @@ CONFIG(debug, debug|release) { DEFINES += NDEBUG } +!isEmpty(BUILD_PASS): BUILDSUBDIR = $$lower($$BUILD_PASS)/ + # c++11 is needed by MinGW to get support for unordered_map. CONFIG += stl exceptions c++11 diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index 262703b9e6..e365d8d7e6 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -68,8 +68,8 @@ #if defined(Q_OS_BSD4) # if defined(Q_OS_NETBSD) - define QT_STATFSBUF struct statvfs - define QT_STATFS ::statvfs +# define QT_STATFSBUF struct statvfs +# define QT_STATFS ::statvfs # else # define QT_STATFSBUF struct statfs # define QT_STATFS ::statfs @@ -507,9 +507,15 @@ void QStorageInfoPrivate::retrieveVolumeInfo() valid = true; ready = true; +#if defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD) + bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize; + bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize; + bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize; +#else bytesTotal = statfs_buf.f_blocks * statfs_buf.f_frsize; bytesFree = statfs_buf.f_bfree * statfs_buf.f_frsize; bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize; +#endif blockSize = statfs_buf.f_bsize; #if defined(Q_OS_ANDROID) || defined (Q_OS_BSD4) #if defined(_STATFS_F_FLAGS) diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index a49fcdaf9f..f0d6417483 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -186,6 +186,10 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode, case ERROR_PIPE_NOT_CONNECTED: pipeBroken = true; break; + case ERROR_OPERATION_ABORTED: + if (stopped) + break; + // fall through default: emit winError(errorCode, QLatin1String("QWindowsPipeReader::notified")); pipeBroken = true; diff --git a/src/corelib/io/qwinoverlappedionotifier.cpp b/src/corelib/io/qwinoverlappedionotifier.cpp index 083feb4a20..c6ce15c2c9 100644 --- a/src/corelib/io/qwinoverlappedionotifier.cpp +++ b/src/corelib/io/qwinoverlappedionotifier.cpp @@ -33,6 +33,7 @@ #include "qwinoverlappedionotifier_p.h" #include +#include #include #include #include @@ -99,6 +100,7 @@ public: { } + OVERLAPPED *waitForAnyNotified(int msecs); void notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped); OVERLAPPED *_q_notified(); @@ -108,6 +110,7 @@ public: HANDLE hHandle; HANDLE hSemaphore; HANDLE hResultsMutex; + QAtomicInt waiting; QQueue results; }; @@ -286,6 +289,47 @@ void QWinOverlappedIoNotifier::setEnabled(bool enabled) d->iocp->unregisterNotifier(d); } +OVERLAPPED *QWinOverlappedIoNotifierPrivate::waitForAnyNotified(int msecs) +{ + if (!iocp->isRunning()) { + qWarning("Called QWinOverlappedIoNotifier::waitForAnyNotified on inactive notifier."); + return 0; + } + + if (msecs == 0) + iocp->drainQueue(); + + const DWORD wfso = WaitForSingleObject(hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs)); + switch (wfso) { + case WAIT_OBJECT_0: + ReleaseSemaphore(hSemaphore, 1, NULL); + return _q_notified(); + case WAIT_TIMEOUT: + return 0; + default: + qErrnoWarning("QWinOverlappedIoNotifier::waitForAnyNotified: WaitForSingleObject failed."); + return 0; + } +} + +class QScopedAtomicIntIncrementor +{ +public: + QScopedAtomicIntIncrementor(QAtomicInt &i) + : m_int(i) + { + ++m_int; + } + + ~QScopedAtomicIntIncrementor() + { + --m_int; + } + +private: + QAtomicInt &m_int; +}; + /*! * Wait synchronously for any notified signal. * @@ -296,24 +340,9 @@ void QWinOverlappedIoNotifier::setEnabled(bool enabled) OVERLAPPED *QWinOverlappedIoNotifier::waitForAnyNotified(int msecs) { Q_D(QWinOverlappedIoNotifier); - if (!d->iocp->isRunning()) { - qWarning("Called QWinOverlappedIoNotifier::waitForAnyNotified on inactive notifier."); - return 0; - } - - if (msecs == 0) - d->iocp->drainQueue(); - - switch (WaitForSingleObject(d->hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs))) { - case WAIT_OBJECT_0: - ReleaseSemaphore(d->hSemaphore, 1, NULL); - return d->_q_notified(); - case WAIT_TIMEOUT: - return 0; - default: - qErrnoWarning("QWinOverlappedIoNotifier::waitForAnyNotified: WaitForSingleObject failed."); - return 0; - } + QScopedAtomicIntIncrementor saii(d->waiting); + OVERLAPPED *result = d->waitForAnyNotified(msecs); + return result; } /*! @@ -324,6 +353,8 @@ OVERLAPPED *QWinOverlappedIoNotifier::waitForAnyNotified(int msecs) */ bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped) { + Q_D(QWinOverlappedIoNotifier); + QScopedAtomicIntIncrementor saii(d->waiting); int t = msecs; QElapsedTimer stopWatch; stopWatch.start(); @@ -350,7 +381,8 @@ void QWinOverlappedIoNotifierPrivate::notify(DWORD numberOfBytes, DWORD errorCod results.enqueue(IOResult(numberOfBytes, errorCode, overlapped)); ReleaseMutex(hResultsMutex); ReleaseSemaphore(hSemaphore, 1, NULL); - emit q->_q_notify(); + if (!waiting) + emit q->_q_notify(); } OVERLAPPED *QWinOverlappedIoNotifierPrivate::_q_notified() diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index c29b132217..ad8a5321b4 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -1784,8 +1784,9 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation() #endif } else { #ifndef QT_NO_BEARERMANAGEMENT - QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)), - q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); + if (session) + QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)), + q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); #endif } diff --git a/src/plugins/platforms/android/qandroidplatformservices.cpp b/src/plugins/platforms/android/qandroidplatformservices.cpp index 2dba6c78e1..412e3e0466 100644 --- a/src/plugins/platforms/android/qandroidplatformservices.cpp +++ b/src/plugins/platforms/android/qandroidplatformservices.cpp @@ -33,8 +33,9 @@ #include "qandroidplatformservices.h" #include -#include +#include #include +#include #include QT_BEGIN_NAMESPACE @@ -43,13 +44,27 @@ QAndroidPlatformServices::QAndroidPlatformServices() { } -bool QAndroidPlatformServices::openUrl(const QUrl &url) +bool QAndroidPlatformServices::openUrl(const QUrl &theUrl) { + QString mime; + QUrl url(theUrl); + + // if the file is local, we need to pass the MIME type, otherwise Android + // does not start an Intent to view this file + if ((url.scheme().isEmpty() && QFile::exists(url.path())) || url.isLocalFile()) { + // a real URL including the scheme is needed, else the Intent can not be started + url.setScheme(QLatin1String("file")); + + QMimeDatabase mimeDb; + mime = mimeDb.mimeTypeForUrl(url).name(); + } + QJNIObjectPrivate urlString = QJNIObjectPrivate::fromString(url.toString()); + QJNIObjectPrivate mimeString = QJNIObjectPrivate::fromString(mime); return QJNIObjectPrivate::callStaticMethod(QtAndroid::applicationClass(), "openURL", - "(Ljava/lang/String;)Z", - urlString.object()); + "(Ljava/lang/String;Ljava/lang/String;)Z", + urlString.object(), mimeString.object()); } bool QAndroidPlatformServices::openDocument(const QUrl &url) diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 28f3b2af84..b55393c7dc 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -56,6 +56,14 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of do { curStart = curEnd; text->textAtOffset(curStart, QAccessible::LineBoundary, &curStart, &curEnd); + // If the text is empty then we just return + if (curStart == -1 || curEnd == -1) { + if (start) + *start = 0; + if (end) + *end = 0; + return; + } ++curLine; { // check for a case where a single word longer than the text edit's width and gets wrapped diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 4d18e7ea58..02accfae01 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -201,12 +201,14 @@ void QWindowsUser32DLL::init() bool QWindowsUser32DLL::initTouch() { - QSystemLibrary library(QStringLiteral("user32")); - isTouchWindow = (IsTouchWindow)(library.resolve("IsTouchWindow")); - registerTouchWindow = (RegisterTouchWindow)(library.resolve("RegisterTouchWindow")); - unregisterTouchWindow = (UnregisterTouchWindow)(library.resolve("UnregisterTouchWindow")); - getTouchInputInfo = (GetTouchInputInfo)(library.resolve("GetTouchInputInfo")); - closeTouchInputHandle = (CloseTouchInputHandle)(library.resolve("CloseTouchInputHandle")); + if (!isTouchWindow && QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) { + QSystemLibrary library(QStringLiteral("user32")); + isTouchWindow = (IsTouchWindow)(library.resolve("IsTouchWindow")); + registerTouchWindow = (RegisterTouchWindow)(library.resolve("RegisterTouchWindow")); + unregisterTouchWindow = (UnregisterTouchWindow)(library.resolve("UnregisterTouchWindow")); + getTouchInputInfo = (GetTouchInputInfo)(library.resolve("GetTouchInputInfo")); + closeTouchInputHandle = (CloseTouchInputHandle)(library.resolve("CloseTouchInputHandle")); + } return isTouchWindow && registerTouchWindow && unregisterTouchWindow && getTouchInputInfo && closeTouchInputHandle; } @@ -359,6 +361,36 @@ QWindowsContext::~QWindowsContext() m_instance = 0; } +bool QWindowsContext::initTouch() +{ + return initTouch(QWindowsIntegration::instance()->options()); +} + +bool QWindowsContext::initTouch(unsigned integrationOptions) +{ + if (d->m_systemInfo & QWindowsContext::SI_SupportsTouch) + return true; + + QTouchDevice *touchDevice = d->m_mouseHandler.ensureTouchDevice(); + if (!touchDevice) + return false; + +#ifndef Q_OS_WINCE + if (!QWindowsContext::user32dll.initTouch()) { + delete touchDevice; + return false; + } +#endif // !Q_OS_WINCE + + if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)) + touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation); + + QWindowSystemInterface::registerTouchDevice(touchDevice); + + d->m_systemInfo |= QWindowsContext::SI_SupportsTouch; + return true; +} + void QWindowsContext::setTabletAbsoluteRange(int a) { #if !defined(QT_NO_TABLETEVENT) && !defined(Q_OS_WINCE) diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index d2a3481b28..641e3ed41f 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -170,6 +170,9 @@ public: explicit QWindowsContext(); ~QWindowsContext(); + bool initTouch(); + bool initTouch(unsigned integrationOptions); // For calls from QWindowsIntegration::QWindowsIntegration() only. + int defaultDPI() const; QString registerWindowClass(const QWindow *w); diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index bbb1f68a52..b67e0b859f 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -226,17 +226,7 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList ¶mL qCDebug(lcQpaWindows) << __FUNCTION__ << "DpiAwareness=" << dpiAwareness; - QTouchDevice *touchDevice = m_context.touchDevice(); - if (touchDevice) { -#ifdef Q_OS_WINCE - touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation); -#else - if (!(m_options & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)) { - touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation); - } -#endif - QWindowSystemInterface::registerTouchDevice(touchDevice); - } + m_context.initTouch(m_options); } QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate() diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 90cb6fe195..e26010b5c4 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -150,12 +150,19 @@ static inline QTouchDevice *createTouchDevice() QWindowsMouseHandler::QWindowsMouseHandler() : m_windowUnderMouse(0), m_trackedWindow(0), - m_touchDevice(createTouchDevice()), + m_touchDevice(Q_NULLPTR), m_leftButtonDown(false), m_previousCaptureWindow(0) { } +QTouchDevice *QWindowsMouseHandler::ensureTouchDevice() +{ + if (!m_touchDevice) + m_touchDevice = createTouchDevice(); + return m_touchDevice; +} + Qt::MouseButtons QWindowsMouseHandler::queryMouseButtons() { Qt::MouseButtons result = 0; @@ -476,7 +483,11 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, typedef QWindowSystemInterface::TouchPoint QTouchPoint; typedef QList QTouchPointList; - Q_ASSERT(m_touchDevice); + if (!QWindowsContext::instance()->initTouch()) { + qWarning("Unable to initialize touch handling."); + return true; + } + const QScreen *screen = window->screen(); if (!screen) screen = QGuiApplication::primaryScreen(); @@ -492,8 +503,6 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, touchPoints.reserve(winTouchPointCount); Qt::TouchPointStates allStates = 0; - Q_ASSERT(QWindowsContext::user32dll.getTouchInputInfo); - QWindowsContext::user32dll.getTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT)); for (int i = 0; i < winTouchPointCount; ++i) { const TOUCHINPUT &winTouchInput = winTouchInputs[i]; diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h index 61aa8d6084..4b5078567d 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.h +++ b/src/plugins/platforms/windows/qwindowsmousehandler.h @@ -52,6 +52,7 @@ public: QWindowsMouseHandler(); QTouchDevice *touchDevice() const { return m_touchDevice; } + QTouchDevice *ensureTouchDevice(); bool translateMouseEvent(QWindow *widget, HWND hwnd, QtWindows::WindowsEventType t, MSG msg, diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp index 847e065aa8..56728432f8 100644 --- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp @@ -98,6 +98,7 @@ private slots: void removeServer(); void recycleServer(); + void recycleClientSocket(); void multiConnect(); void writeOnlySocket(); @@ -954,6 +955,34 @@ void tst_QLocalSocket::recycleServer() QVERIFY(server.nextPendingConnection() != 0); } +void tst_QLocalSocket::recycleClientSocket() +{ + const QByteArrayList lines = QByteArrayList() << "Have you heard of that new band" + << "\"1023 Megabytes\"?" + << "They haven't made it to a gig yet."; + QLocalServer server; + const QString serverName = QStringLiteral("recycleClientSocket"); + QVERIFY(server.listen(serverName)); + QLocalSocket client; + QSignalSpy clientReadyReadSpy(&client, SIGNAL(readyRead())); + QSignalSpy clientErrorSpy(&client, SIGNAL(error(QLocalSocket::LocalSocketError))); + for (int i = 0; i < lines.count(); ++i) { + client.abort(); + clientReadyReadSpy.clear(); + client.connectToServer(serverName); + QVERIFY(client.waitForConnected()); + QVERIFY(server.waitForNewConnection()); + QLocalSocket *serverSocket = server.nextPendingConnection(); + QVERIFY(serverSocket); + connect(serverSocket, &QLocalSocket::disconnected, &QLocalSocket::deleteLater); + serverSocket->write(lines.at(i)); + serverSocket->flush(); + QVERIFY(clientReadyReadSpy.wait()); + QCOMPARE(client.readAll(), lines.at(i)); + QVERIFY(clientErrorSpy.isEmpty()); + } +} + void tst_QLocalSocket::multiConnect() { QLocalServer server;