diff options
author | Oswald Buddenhagen <oswald.buddenhagen@qt.io> | 2017-11-20 13:48:33 +0100 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@qt.io> | 2017-11-20 13:48:33 +0100 |
commit | bb3872d60975724a50ff910b6dd108d1944db597 (patch) | |
tree | ce1c96729a1a4691a322b36cfd5429c020403ccc /tests/auto/network | |
parent | b72b5cd76004e54dc00c0f1133f4d59192ef154a (diff) | |
parent | 8e387e7fa758ded3f0d096dcf5fe13a22521dad7 (diff) |
Merge 5.10 into 5.10.0
Change-Id: Ibfbaa8ef89cf45b87a2c65f1da4a708e5464f259
Diffstat (limited to 'tests/auto/network')
12 files changed, 240 insertions, 80 deletions
diff --git a/tests/auto/network/access/hpack/tst_hpack.cpp b/tests/auto/network/access/hpack/tst_hpack.cpp index bd337c9f5f..810745a065 100644 --- a/tests/auto/network/access/hpack/tst_hpack.cpp +++ b/tests/auto/network/access/hpack/tst_hpack.cpp @@ -273,13 +273,13 @@ void tst_Hpack::bitstreamCompression() std::vector<uchar> buffer; BitOStream out(buffer); for (unsigned i = 0; i < nValues; ++i) { - const bool isString = std::rand() % 1000 > 500; + const bool isString = QRandomGenerator::global()->bounded(1000) > 500; isA.push_back(isString); if (!isString) { - integers.push_back(std::rand() % 1000); + integers.push_back(QRandomGenerator::global()->bounded(1000u)); out.write(integers.back()); } else { - const auto start = std::rand() % (bytes.length() / 2); + const auto start = QRandomGenerator::global()->bounded(uint(bytes.length()) / 2); auto end = start * 2; if (!end) end = bytes.length() / 2; @@ -287,7 +287,7 @@ void tst_Hpack::bitstreamCompression() const auto &s = strings.back(); totalStringBytes += s.size(); QByteArray data(s.c_str(), int(s.size())); - const bool compressed(std::rand() % 1000 > 500); + const bool compressed(QRandomGenerator::global()->bounded(1000) > 500); out.write(data, compressed); } } @@ -442,8 +442,8 @@ void tst_Hpack::lookupTableDynamic() // Strings are repeating way too often, I want to // have at least some items really evicted and not found, // therefore these weird dances with start/len. - const quint32 start = std::rand() % (dataSize - 10); - quint32 len = std::rand() % (dataSize - start); + const quint32 start = QRandomGenerator::global()->bounded(dataSize - 10); + quint32 len = QRandomGenerator::global()->bounded(dataSize - start); if (!len) len = 1; diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp index 7b453ca635..51e1849512 100644 --- a/tests/auto/network/access/http2/tst_http2.cpp +++ b/tests/auto/network/access/http2/tst_http2.cpp @@ -224,7 +224,7 @@ void tst_Http2::multipleRequests() }; for (int i = 0; i < nRequests; ++i) - sendRequest(i, priorities[std::rand() % 3]); + sendRequest(i, priorities[QRandomGenerator::global()->bounded(3)]); runEventLoop(); diff --git a/tests/auto/network/access/qftp/tst_qftp.cpp b/tests/auto/network/access/qftp/tst_qftp.cpp index fba0508f04..4bc43f068c 100644 --- a/tests/auto/network/access/qftp/tst_qftp.cpp +++ b/tests/auto/network/access/qftp/tst_qftp.cpp @@ -276,8 +276,7 @@ void tst_QFtp::init() inFileDirExistsFunction = false; - srand(time(0)); - uniqueExtension = QString::number((quintptr)this) + QString::number(rand()) + uniqueExtension = QString::number((quintptr)this) + QString::number(QRandomGenerator::global()->generate()) + QString::number((qulonglong)time(0)); } diff --git a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp index e996347a9a..856033fb63 100644 --- a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp +++ b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp @@ -30,6 +30,7 @@ #include <QtTest/QtTest> #include <QtNetwork/QtNetwork> #include <qnetworkdiskcache.h> +#include <qrandom.h> #include <algorithm> @@ -693,25 +694,25 @@ public: if (write) { QNetworkCacheMetaData m; - if (qrand() % 2 == 0) + if (QRandomGenerator::global()->bounded(2) == 0) m = metaData; else m = metaData2; - if (qrand() % 20 == 1) { + if (QRandomGenerator::global()->bounded(20) == 1) { //qDebug() << "write update"; cache.updateMetaData(m); continue; } QIODevice *device = cache.prepare(m); - if (qrand() % 20 == 1) { + if (QRandomGenerator::global()->bounded(20) == 1) { //qDebug() << "write remove"; cache.remove(url); continue; } QVERIFY(device); - if (qrand() % 2 == 0) + if (QRandomGenerator::global()->bounded(2) == 0) device->write(longString); else device->write(longString2); @@ -740,9 +741,9 @@ public: delete d; } } - if (qrand() % 5 == 1) + if (QRandomGenerator::global()->bounded(5) == 1) cache.remove(url); - if (qrand() % 5 == 1) + if (QRandomGenerator::global()->bounded(5) == 1) cache.clear(); sleep(0); } @@ -791,7 +792,6 @@ void tst_QNetworkDiskCache::sync() return; QTime midnight(0, 0, 0); - qsrand(midnight.secsTo(QTime::currentTime())); Runner reader(tempDir.path()); reader.dt = QDateTime::currentDateTime(); reader.write = false; diff --git a/tests/auto/network/access/qnetworkreply/BLACKLIST b/tests/auto/network/access/qnetworkreply/BLACKLIST index 1d56c78bbc..d6fc717e37 100644 --- a/tests/auto/network/access/qnetworkreply/BLACKLIST +++ b/tests/auto/network/access/qnetworkreply/BLACKLIST @@ -1,5 +1,7 @@ # See qtbase/src/testlib/qtestblacklist.cpp for format osx +[authenticationCacheAfterCancel] +windows [ioGetFromBuiltinHttp:http+limited] ubuntu-14.04 [ioGetFromBuiltinHttp:https+limited] @@ -8,3 +10,33 @@ ubuntu-14.04 * [backgroundRequestInterruption:ftp, bg, nobg] * +[getErrors:ftp-host] +linux +[getFromHttpIntoBuffer] +windows +[getFromHttpIntoBuffer2] +windows +[headFromHttp] +windows +[ioGetFromHttpWithSocksProxy] +windows +[ioPostToHttpFromSocket] +windows +[ioHttpRedirectMultipartPost] +linux +[ioHttpRedirectPolicy] +b2qt 64bit +linux +[ioHttpRedirectPostPut] +linux +windows +[putToFtp] +windows ci +[putWithServerClosingConnectionImmediately] +windows +[qtbug28035browserDoesNotLoadQtProjectOrgCorrectly] +windows +[getFromUnreachableIp] +windows msvc-2017 +[ioHttpRedirectErrors:too-many-redirects] +rhel-6.6 ci diff --git a/tests/auto/network/access/qnetworkreply/test/test.pro b/tests/auto/network/access/qnetworkreply/test/test.pro index 0dcf5a250c..1f45ac0c49 100644 --- a/tests/auto/network/access/qnetworkreply/test/test.pro +++ b/tests/auto/network/access/qnetworkreply/test/test.pro @@ -13,7 +13,4 @@ RESOURCES += ../qnetworkreply.qrc TESTDATA += ../empty ../rfc3252.txt ../resource ../bigfile ../*.jpg ../certs \ ../index.html ../smb-file.txt -qtConfig(xcb): CONFIG+=insignificant_test # unstable, QTBUG-21102 -win32:CONFIG += insignificant_test # QTBUG-24226 - !winrt: TEST_HELPER_INSTALLS = ../echo/echo diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 93afca3d48..fffe853c14 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -33,6 +33,7 @@ #include <QtCore/QUrl> #include <QtCore/QEventLoop> #include <QtCore/QFile> +#include <QtCore/QRandomGenerator> #include <QtCore/QSharedPointer> #include <QtCore/QScopedPointer> #include <QtCore/QTemporaryFile> @@ -120,12 +121,11 @@ class tst_QNetworkReply: public QObject static QString createUniqueExtension() { if (!seedCreated) { - qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()) + QCoreApplication::applicationPid()); seedCreated = true; // not thread-safe, but who cares } return QString::number(QTime(0, 0, 0).msecsTo(QTime::currentTime())) + QLatin1Char('-') + QString::number(QCoreApplication::applicationPid()) - + QLatin1Char('-') + QString::number(qrand()); + + QLatin1Char('-') + QString::number(QRandomGenerator::global()->generate()); } static QString tempRedirectReplyStr() { @@ -1994,6 +1994,16 @@ void tst_QNetworkReply::getErrors_data() << int(QNetworkReply::AuthenticationRequiredError) << 401 << false; } +static QByteArray msgGetErrors(int waitResult, const QNetworkReplyPtr &reply) +{ + QByteArray result ="waitResult=" + QByteArray::number(waitResult); + if (reply->isFinished()) + result += ", finished"; + if (reply->error() != QNetworkReply::NoError) + result += ", error: " + QByteArray::number(int(reply->error())); + return result; +} + void tst_QNetworkReply::getErrors() { QFETCH(QString, url); @@ -2023,7 +2033,8 @@ void tst_QNetworkReply::getErrors() QCOMPARE(reply->error(), QNetworkReply::NoError); // now run the request: - QVERIFY(waitForFinish(reply) != Timeout); + const int waitResult = waitForFinish(reply); + QVERIFY2(waitResult != Timeout, msgGetErrors(waitResult, reply)); QFETCH(int, error); QEXPECT_FAIL("ftp-is-dir", "QFtp cannot provide enough detail", Abort); @@ -4852,7 +4863,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress() // server send the data much faster than expected. // So better provide random data that cannot be compressed. for (int i = 0; i < wantedSize; ++i) - sourceFile += (char)qrand(); + sourceFile += (char)QRandomGenerator::global()->generate(); // emulate a minimal https server SslServer server; @@ -4932,7 +4943,7 @@ void tst_QNetworkReply::ioGetFromBuiltinHttp() // server send the data much faster than expected. // So better provide random data that cannot be compressed. for (int i = 0; i < wantedSize; ++i) - testData += (char)qrand(); + testData += (char)QRandomGenerator::global()->generate(); QByteArray httpResponse = QByteArray("HTTP/1.0 200 OK\r\nContent-Length: "); httpResponse += QByteArray::number(testData.size()); @@ -6755,6 +6766,48 @@ void tst_QNetworkReply::getFromUnreachableIp() { QNetworkAccessManager manager; +#ifdef Q_OS_WIN + // This test assumes that attempt to connect to 255.255.255.255 fails more + // or less fast/immediately. This is not what we observe on Windows: + // WSAConnect on non-blocking socket returns SOCKET_ERROR, WSAGetLastError + // returns WSAEWOULDBLOCK (expected) and getsockopt most of the time returns + // NOERROR; so socket engine starts a timer (30 s.) and waits for a timeout/ + // error/success. Unfortunately, the test itself is waiting only for 5 s. + // So we have to adjust the connection timeout or skip the test completely + // if the 'bearermanagement' feature is not available. +#if QT_CONFIG(bearermanagement) + class ConfigurationGuard + { + public: + explicit ConfigurationGuard(QNetworkAccessManager *m) + : manager(m) + { + Q_ASSERT(m); + auto conf = manager->configuration(); + previousTimeout = conf.connectTimeout(); + conf.setConnectTimeout(1500); + manager->setConfiguration(conf); + } + ~ConfigurationGuard() + { + Q_ASSERT(manager); + auto conf = manager->configuration(); + conf.setConnectTimeout(previousTimeout); + manager->setConfiguration(conf); + } + private: + QNetworkAccessManager *manager = nullptr; + int previousTimeout = 0; + + Q_DISABLE_COPY(ConfigurationGuard) + }; + + const ConfigurationGuard restorer(&manager); +#else // bearermanagement + QSKIP("This test is non-deterministic on Windows x86"); +#endif // !bearermanagement +#endif // Q_OS_WIN + QNetworkRequest request(QUrl("http://255.255.255.255/42/23/narf/narf/narf")); QNetworkReplyPtr reply(manager.get(request)); @@ -8748,7 +8801,7 @@ public slots: m_receivedData += data; if (!m_parsedHeaders && m_receivedData.contains("\r\n\r\n")) { m_parsedHeaders = true; - QTimer::singleShot(qrand()%60, this, SLOT(closeDelayed())); // simulate random network latency + QTimer::singleShot(QRandomGenerator::global()->bounded(60), this, SLOT(closeDelayed())); // simulate random network latency // This server simulates a web server connection closing, e.g. because of Apaches MaxKeepAliveRequests or KeepAliveTimeout // In this case QNAM needs to re-send the upload data but it had a bug which then corrupts the upload // This test catches that. diff --git a/tests/auto/network/socket/qtcpsocket/qtcpsocket.pro b/tests/auto/network/socket/qtcpsocket/qtcpsocket.pro index 1183b23556..1f13a396dd 100644 --- a/tests/auto/network/socket/qtcpsocket/qtcpsocket.pro +++ b/tests/auto/network/socket/qtcpsocket/qtcpsocket.pro @@ -1,6 +1,8 @@ TEMPLATE = subdirs SUBDIRS = test -!vxworks: SUBDIRS += stressTest - +!vxworks{ +SUBDIRS += stressTest +test.depends = stressTest +} requires(qtConfig(private_tests)) diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 7340817ade..d7c8c8c378 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -57,6 +57,7 @@ #if QT_CONFIG(process) # include <QProcess> #endif +#include <QRandomGenerator> #include <QStringList> #include <QTcpServer> #include <QTcpSocket> @@ -305,8 +306,6 @@ public: tst_QTcpSocket::tst_QTcpSocket() : firstFailName("qt-test-server-first-fail") { - qsrand(time(NULL)); - tmpSocket = 0; //This code relates to the socketsConstructedBeforeEventLoop test case @@ -581,8 +580,7 @@ void tst_QTcpSocket::bind() // try to get a random port number // we do this to ensure we're not trying to bind to the same port as we've just used in // a previous run - race condition with the OS actually freeing the port - Q_STATIC_ASSERT(RAND_MAX > 1024); - port = qrand() & USHRT_MAX; + port = QRandomGenerator::global()->generate() & USHRT_MAX; if (port < 1024) continue; } diff --git a/tests/auto/network/socket/qudpsocket/qudpsocket.pro b/tests/auto/network/socket/qudpsocket/qudpsocket.pro index 4ddb7178a4..b267d5f249 100644 --- a/tests/auto/network/socket/qudpsocket/qudpsocket.pro +++ b/tests/auto/network/socket/qudpsocket/qudpsocket.pro @@ -1,4 +1,3 @@ TEMPLATE = subdirs SUBDIRS = test clientserver - - +test.depends = clientserver diff --git a/tests/auto/network/socket/qudpsocket/test/test.pro b/tests/auto/network/socket/qudpsocket/test/test.pro index 73486a2bc3..e856776ddc 100644 --- a/tests/auto/network/socket/qudpsocket/test/test.pro +++ b/tests/auto/network/socket/qudpsocket/test/test.pro @@ -1,6 +1,7 @@ CONFIG += testcase testcase.timeout = 800 # this test is slow SOURCES += ../tst_qudpsocket.cpp +INCLUDEPATH += ../../../../../shared/ QT = core network testlib MOC_DIR=tmp diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index aeb6e61cd2..0f46caa7c2 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -45,6 +45,7 @@ #include <qstringlist.h> #include "../../../network-settings.h" +#include "emulationdetector.h" #ifndef QT_NO_BEARERMANAGEMENT #include <QtNetwork/qnetworkconfigmanager.h> @@ -227,6 +228,9 @@ void tst_QUdpSocket::initTestCase() QSKIP("No network test server available"); allAddresses = QNetworkInterface::allAddresses(); m_skipUnsupportedIPv6Tests = shouldSkipIpv6TestsForBrokenSetsockopt(); + + if (EmulationDetector::isRunningArmOnX86()) + QSKIP("This test is unreliable due to QEMU emulation shortcomings."); } void tst_QUdpSocket::init() @@ -445,31 +449,58 @@ void tst_QUdpSocket::loop() paul.setProperty("_q_networksession", QVariant::fromValue(networkSession)); #endif - QVERIFY2(peter.bind(), peter.errorString().toLatin1().constData()); - QVERIFY2(paul.bind(), paul.errorString().toLatin1().constData()); + // make sure we bind to IPv4 + QHostAddress localhost = QHostAddress::LocalHost; + QVERIFY2(peter.bind(localhost), peter.errorString().toLatin1().constData()); + QVERIFY2(paul.bind(localhost), paul.errorString().toLatin1().constData()); QHostAddress peterAddress = makeNonAny(peter.localAddress()); - QHostAddress pualAddress = makeNonAny(paul.localAddress()); + QHostAddress paulAddress = makeNonAny(paul.localAddress()); QCOMPARE(peter.writeDatagram(peterMessage.data(), peterMessage.length(), - pualAddress, paul.localPort()), qint64(peterMessage.length())); + paulAddress, paul.localPort()), qint64(peterMessage.length())); QCOMPARE(paul.writeDatagram(paulMessage.data(), paulMessage.length(), peterAddress, peter.localPort()), qint64(paulMessage.length())); QVERIFY2(peter.waitForReadyRead(9000), QtNetworkSettings::msgSocketError(peter).constData()); QVERIFY2(paul.waitForReadyRead(9000), QtNetworkSettings::msgSocketError(paul).constData()); - char peterBuffer[16*1024]; - char paulBuffer[16*1024]; + + QNetworkDatagram peterDatagram = peter.receiveDatagram(paulMessage.length() * 2); + QNetworkDatagram paulDatagram = paul.receiveDatagram(peterMessage.length() * 2); if (success) { - QCOMPARE(peter.readDatagram(peterBuffer, sizeof(peterBuffer)), qint64(paulMessage.length())); - QCOMPARE(paul.readDatagram(paulBuffer, sizeof(peterBuffer)), qint64(peterMessage.length())); + QCOMPARE(peterDatagram.data().length(), qint64(paulMessage.length())); + QCOMPARE(paulDatagram.data().length(), qint64(peterMessage.length())); } else { - QVERIFY(peter.readDatagram(peterBuffer, sizeof(peterBuffer)) != paulMessage.length()); - QVERIFY(paul.readDatagram(paulBuffer, sizeof(peterBuffer)) != peterMessage.length()); + // this code path seems to never be executed + QVERIFY(peterDatagram.data().length() != paulMessage.length()); + QVERIFY(paulDatagram.data().length() != peterMessage.length()); } - QCOMPARE(QByteArray(peterBuffer, paulMessage.length()), paulMessage); - QCOMPARE(QByteArray(paulBuffer, peterMessage.length()), peterMessage); + QCOMPARE(peterDatagram.data().left(paulMessage.length()), paulMessage); + QCOMPARE(paulDatagram.data().left(peterMessage.length()), peterMessage); + + QCOMPARE(peterDatagram.senderAddress(), paulAddress); + QCOMPARE(paulDatagram.senderAddress(), peterAddress); + QCOMPARE(paulDatagram.senderPort(), int(peter.localPort())); + QCOMPARE(peterDatagram.senderPort(), int(paul.localPort())); + + // Unlike for IPv6 with IPV6_PKTINFO, IPv4 has no standardized way of + // obtaining the packet's destination addresses. The destinationAddress and + // destinationPort calls could fail, so whitelist the OSes for which we + // know we have an implementation. +#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) || defined(Q_OS_WIN) + QVERIFY(peterDatagram.destinationPort() != -1); + QVERIFY(paulDatagram.destinationPort() != -1); +#endif + if (peterDatagram.destinationPort() == -1) { + QCOMPARE(peterDatagram.destinationAddress().protocol(), QAbstractSocket::UnknownNetworkLayerProtocol); + QCOMPARE(paulDatagram.destinationAddress().protocol(), QAbstractSocket::UnknownNetworkLayerProtocol); + } else { + QCOMPARE(peterDatagram.destinationAddress(), makeNonAny(peter.localAddress())); + QCOMPARE(paulDatagram.destinationAddress(), makeNonAny(paul.localAddress())); + QVERIFY(peterDatagram.destinationAddress().isEqual(makeNonAny(peter.localAddress()))); + QVERIFY(paulDatagram.destinationAddress().isEqual(makeNonAny(paul.localAddress()))); + } } //---------------------------------------------------------------------------------- @@ -492,8 +523,8 @@ void tst_QUdpSocket::ipv6Loop() paul.setProperty("_q_networksession", QVariant::fromValue(networkSession)); #endif - quint16 peterPort; - quint16 paulPort; + int peterPort; + int paulPort; if (!peter.bind(QHostAddress(QHostAddress::LocalHostIPv6), 0)) { QCOMPARE(peter.error(), QUdpSocket::UnsupportedSocketOperationError); @@ -502,6 +533,8 @@ void tst_QUdpSocket::ipv6Loop() QVERIFY(paul.bind(QHostAddress(QHostAddress::LocalHostIPv6), 0)); + QHostAddress peterAddress = makeNonAny(peter.localAddress()); + QHostAddress paulAddress = makeNonAny(paul.localAddress()); peterPort = peter.localPort(); paulPort = paul.localPort(); @@ -510,20 +543,33 @@ void tst_QUdpSocket::ipv6Loop() QCOMPARE(paul.writeDatagram(paulMessage.data(), paulMessage.length(), QHostAddress("::1"), peterPort), qint64(paulMessage.length())); - char peterBuffer[16*1024]; - char paulBuffer[16*1024]; QVERIFY(peter.waitForReadyRead(5000)); QVERIFY(paul.waitForReadyRead(5000)); + QNetworkDatagram peterDatagram = peter.receiveDatagram(paulMessage.length() * 2); + QNetworkDatagram paulDatagram = paul.receiveDatagram(peterMessage.length() * 2); + if (success) { - QCOMPARE(peter.readDatagram(peterBuffer, sizeof(peterBuffer)), qint64(paulMessage.length())); - QCOMPARE(paul.readDatagram(paulBuffer, sizeof(peterBuffer)), qint64(peterMessage.length())); + QCOMPARE(peterDatagram.data().length(), qint64(paulMessage.length())); + QCOMPARE(paulDatagram.data().length(), qint64(peterMessage.length())); } else { - QVERIFY(peter.readDatagram(peterBuffer, sizeof(peterBuffer)) != paulMessage.length()); - QVERIFY(paul.readDatagram(paulBuffer, sizeof(peterBuffer)) != peterMessage.length()); + // this code path seems to never be executed + QVERIFY(peterDatagram.data().length() != paulMessage.length()); + QVERIFY(paulDatagram.data().length() != peterMessage.length()); } - QCOMPARE(QByteArray(peterBuffer, paulMessage.length()), paulMessage); - QCOMPARE(QByteArray(paulBuffer, peterMessage.length()), peterMessage); + QCOMPARE(peterDatagram.data().left(paulMessage.length()), paulMessage); + QCOMPARE(paulDatagram.data().left(peterMessage.length()), peterMessage); + + QCOMPARE(peterDatagram.senderAddress(), paulAddress); + QCOMPARE(paulDatagram.senderAddress(), peterAddress); + QCOMPARE(paulDatagram.senderPort(), peterPort); + QCOMPARE(peterDatagram.senderPort(), paulPort); + + // For IPv6, IPV6_PKTINFO is a mandatory feature (RFC 3542). + QCOMPARE(peterDatagram.destinationAddress(), makeNonAny(peter.localAddress())); + QCOMPARE(paulDatagram.destinationAddress(), makeNonAny(paul.localAddress())); + QCOMPARE(peterDatagram.destinationPort(), peterPort); + QCOMPARE(paulDatagram.destinationPort(), paulPort); } void tst_QUdpSocket::dualStack() @@ -539,17 +585,23 @@ void tst_QUdpSocket::dualStack() QByteArray v4Data("v4"); QVERIFY(v4Sock.bind(QHostAddress(QHostAddress::AnyIPv4), 0)); - QHostAddress from; - quint16 port; - QByteArray buffer; //test v4 -> dual QCOMPARE((int)v4Sock.writeDatagram(v4Data.constData(), v4Data.length(), QHostAddress(QHostAddress::LocalHost), dualSock.localPort()), v4Data.length()); QVERIFY2(dualSock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(dualSock).constData()); - buffer.reserve(100); - qint64 size = dualSock.readDatagram(buffer.data(), 100, &from, &port); - QCOMPARE((int)size, v4Data.length()); - buffer.resize(size); - QCOMPARE(buffer, v4Data); + QNetworkDatagram dgram = dualSock.receiveDatagram(100); + QVERIFY(dgram.isValid()); + QCOMPARE(dgram.data(), v4Data); + QCOMPARE(dgram.senderPort(), int(v4Sock.localPort())); + // receiving v4 on dual stack will receive as IPv6, so use isEqual() + QVERIFY(dgram.senderAddress().isEqual(makeNonAny(v4Sock.localAddress(), QHostAddress::Null))); + if (dualSock.localAddress().protocol() == QAbstractSocket::IPv4Protocol) + QCOMPARE(dgram.senderAddress(), makeNonAny(v4Sock.localAddress(), QHostAddress::Null)); + if (dgram.destinationPort() != -1) { + QCOMPARE(dgram.destinationPort(), int(dualSock.localPort())); + QVERIFY(dgram.destinationAddress().isEqual(dualSock.localAddress())); + } else { + qInfo("Getting IPv4 destination address failed."); + } if (QtNetworkSettings::hasIPv6()) { QUdpSocket v6Sock; @@ -559,30 +611,41 @@ void tst_QUdpSocket::dualStack() //test v6 -> dual QCOMPARE((int)v6Sock.writeDatagram(v6Data.constData(), v6Data.length(), QHostAddress(QHostAddress::LocalHostIPv6), dualSock.localPort()), v6Data.length()); QVERIFY2(dualSock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(dualSock).constData()); - buffer.reserve(100); - size = dualSock.readDatagram(buffer.data(), 100, &from, &port); - QCOMPARE((int)size, v6Data.length()); - buffer.resize(size); - QCOMPARE(buffer, v6Data); + dgram = dualSock.receiveDatagram(100); + QVERIFY(dgram.isValid()); + QCOMPARE(dgram.data(), v6Data); + QCOMPARE(dgram.senderPort(), int(v6Sock.localPort())); + QCOMPARE(dgram.senderAddress(), makeNonAny(v6Sock.localAddress(), QHostAddress::LocalHostIPv6)); + QCOMPARE(dgram.destinationPort(), int(dualSock.localPort())); + QCOMPARE(dgram.destinationAddress(), makeNonAny(dualSock.localAddress(), QHostAddress::LocalHostIPv6)); //test dual -> v6 QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHostIPv6), v6Sock.localPort()), dualData.length()); QVERIFY2(v6Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v6Sock).constData()); - buffer.reserve(100); - size = v6Sock.readDatagram(buffer.data(), 100, &from, &port); - QCOMPARE((int)size, dualData.length()); - buffer.resize(size); - QCOMPARE(buffer, dualData); + dgram = v6Sock.receiveDatagram(100); + QVERIFY(dgram.isValid()); + QCOMPARE(dgram.data(), dualData); + QCOMPARE(dgram.senderPort(), int(dualSock.localPort())); + QCOMPARE(dgram.senderAddress(), makeNonAny(dualSock.localAddress(), QHostAddress::LocalHostIPv6)); + QCOMPARE(dgram.destinationPort(), int(v6Sock.localPort())); + QCOMPARE(dgram.destinationAddress(), makeNonAny(v6Sock.localAddress(), QHostAddress::LocalHostIPv6)); } //test dual -> v4 QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHost), v4Sock.localPort()), dualData.length()); QVERIFY2(v4Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v4Sock).constData()); - buffer.reserve(100); - size = v4Sock.readDatagram(buffer.data(), 100, &from, &port); - QCOMPARE((int)size, dualData.length()); - buffer.resize(size); - QCOMPARE(buffer, dualData); + dgram = v4Sock.receiveDatagram(100); + QVERIFY(dgram.isValid()); + QCOMPARE(dgram.data(), dualData); + QCOMPARE(dgram.senderPort(), int(dualSock.localPort())); + QCOMPARE(dgram.senderAddress(), makeNonAny(dualSock.localAddress(), QHostAddress::LocalHost)); +#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) || defined(Q_OS_WIN) + QVERIFY(dgram.destinationPort() != -1); +#endif + if (dgram.destinationPort() != -1) { + QCOMPARE(dgram.destinationPort(), int(v4Sock.localPort())); + QCOMPARE(dgram.destinationAddress(), makeNonAny(v4Sock.localAddress(), QHostAddress::LocalHost)); + } } void tst_QUdpSocket::dualStackAutoBinding() @@ -1603,6 +1666,8 @@ void tst_QUdpSocket::linkLocalIPv6() QVERIFY(dgram.isValid()); QCOMPARE(dgram.senderAddress(), s->localAddress()); QCOMPARE(dgram.senderPort(), int(s->localPort())); + QCOMPARE(dgram.destinationAddress(), s->localAddress()); + QCOMPARE(dgram.destinationPort(), int(neutral.localPort())); QCOMPARE(dgram.data().length(), testData.length()); QCOMPARE(dgram.data(), testData); @@ -1684,6 +1749,20 @@ void tst_QUdpSocket::linkLocalIPv4() QCOMPARE(dgram.data().length(), testData.length()); QCOMPARE(dgram.data(), testData); + // Unlike for IPv6 with IPV6_PKTINFO, IPv4 has no standardized way of + // obtaining the packet's destination addresses. The destinationAddress + // and destinationPort calls could fail, so whitelist the OSes we know + // we have an implementation. +#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) || defined(Q_OS_WIN) + QVERIFY(dgram.destinationPort() != -1); +#endif + if (dgram.destinationPort() == -1) { + QCOMPARE(dgram.destinationAddress().protocol(), QAbstractSocket::UnknownNetworkLayerProtocol); + } else { + QCOMPARE(dgram.destinationAddress(), s->localAddress()); + QCOMPARE(dgram.destinationPort(), int(neutral.localPort())); + } + QVERIFY(neutral.writeDatagram(dgram.makeReply(testData))); dgram = s->receiveDatagram(testData.length() * 2); |