From 36de36e5695744e3c5d7dc839011b7b593737be5 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 16 Apr 2010 10:34:35 +0200 Subject: Finish renaming --- .../network_stresstest/network_stresstest.pro | 12 + .../network_stresstest/qtcpsocket_stresstest.pro | 12 - .../network_stresstest/tst_network_stresstest.cpp | 736 ++++++++++++++++++++ .../tst_qtcpsocket_stresstest.cpp | 739 --------------------- 4 files changed, 748 insertions(+), 751 deletions(-) create mode 100644 tests/manual/network_stresstest/network_stresstest.pro delete mode 100644 tests/manual/network_stresstest/qtcpsocket_stresstest.pro create mode 100644 tests/manual/network_stresstest/tst_network_stresstest.cpp delete mode 100644 tests/manual/network_stresstest/tst_qtcpsocket_stresstest.cpp diff --git a/tests/manual/network_stresstest/network_stresstest.pro b/tests/manual/network_stresstest/network_stresstest.pro new file mode 100644 index 0000000..0e272d1 --- /dev/null +++ b/tests/manual/network_stresstest/network_stresstest.pro @@ -0,0 +1,12 @@ +load(qttest_p4) + +QT = core network + +SOURCES += tst_network_stresstest.cpp \ + minihttpserver.cpp + +HEADERS += \ + minihttpserver.h + +RESOURCES += wwwfiles.qrc +QMAKE_RESOURCE_FLAGS += -no-compress diff --git a/tests/manual/network_stresstest/qtcpsocket_stresstest.pro b/tests/manual/network_stresstest/qtcpsocket_stresstest.pro deleted file mode 100644 index 47b2682..0000000 --- a/tests/manual/network_stresstest/qtcpsocket_stresstest.pro +++ /dev/null @@ -1,12 +0,0 @@ -load(qttest_p4) - -QT = core network - -SOURCES += tst_qtcpsocket_stresstest.cpp \ - minihttpserver.cpp - -HEADERS += \ - minihttpserver.h - -RESOURCES += wwwfiles.qrc -QMAKE_RESOURCE_FLAGS += -no-compress diff --git a/tests/manual/network_stresstest/tst_network_stresstest.cpp b/tests/manual/network_stresstest/tst_network_stresstest.cpp new file mode 100644 index 0000000..7c94972 --- /dev/null +++ b/tests/manual/network_stresstest/tst_network_stresstest.cpp @@ -0,0 +1,736 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef QT_BUILD_INTERNAL +# include +#endif + +#include "minihttpserver.h" +#include "../../auto/network-settings.h" + +#include +#ifdef Q_OS_UNIX +# include +# include +# include +# include +# include +# include +# include +# include +# include + +typedef int SOCKET; +# define INVALID_SOCKET -1 +# define SOCKET_ERROR -1 + +#elif defined(Q_OS_WIN) +# include +#endif + +class tst_QTcpSocket_stresstest : public QObject +{ + Q_OBJECT +public: + enum { AttemptCount = 100 }; + tst_QTcpSocket_stresstest(); + MiniHttpServer server; + + qint64 byteCounter; + QNetworkAccessManager manager; + bool intermediateDebug; + +private: + void clearManager(); + +public slots: + void initTestCase_data(); + void init(); + + void slotReadAll() { byteCounter += static_cast(sender())->readAll().size(); } + +private Q_SLOTS: + void nativeBlockingConnectDisconnect(); + void nativeNonBlockingConnectDisconnect(); + void blockingConnectDisconnect(); + void blockingPipelined(); + void blockingMultipleRequests(); + void connectDisconnect(); + void parallelConnectDisconnect_data(); + void parallelConnectDisconnect(); + void namGet_data(); + void namGet(); +}; + +tst_QTcpSocket_stresstest::tst_QTcpSocket_stresstest() + : intermediateDebug(qgetenv("STRESSDEBUG").toInt() > 0) +{ +#ifdef Q_OS_WIN + WSAData wsadata; + + // IPv6 requires Winsock v2.0 or better. + WSAStartup(MAKEWORD(2,0), &wsadata); +#elif defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) + ::signal(SIGALRM, SIG_IGN); +#endif +} + +void tst_QTcpSocket_stresstest::initTestCase_data() +{ + QTest::addColumn("isLocalhost"); + QTest::addColumn("hostname"); + QTest::addColumn("port"); + + QTest::newRow("localhost") << true << "localhost" << server.port(); +// QTest::newRow("remote") << false << QtNetworkSettings::serverName() << 80; +} + +void tst_QTcpSocket_stresstest::init() +{ + // clear the internal cache +#ifndef QT_BUILD_INTERNAL + if (strncmp(QTest::currentTestFunction(), "nam") == 0) + QSKIP("QNetworkAccessManager tests disabled", SkipAll); +#endif +} + +void tst_QTcpSocket_stresstest::clearManager() +{ +#ifdef QT_BUILD_INTERNAL + QNetworkAccessManagerPrivate::clearCache(&manager); + manager.setProxy(QNetworkProxy()); + manager.setCache(0); +#endif +} + +bool nativeLookup(const char *hostname, int port, QByteArray &buf) +{ +#if !defined(QT_NO_GETADDRINFO) && 0 + addrinfo *res = 0; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + + int result = getaddrinfo(QUrl::toAce(hostname).constData(), QByteArray::number(port).constData(), &hints, &res); + if (!result) + return false; + for (addrinfo *node = res; node; node = node->ai_next) { + if (node->ai_family == AF_INET) { + buf = QByteArray((char *)node->ai_addr, node->ai_addrlen); + break; + } + } + freeaddrinfo(res); +#else + hostent *result = gethostbyname(hostname); + if (!result || result->h_addrtype != AF_INET) + return false; + + struct sockaddr_in s; + s.sin_family = AF_INET; + s.sin_port = htons(port); + s.sin_addr = *(struct in_addr *) result->h_addr_list[0]; + + buf = QByteArray((char *)&s, sizeof s); +#endif + + return !buf.isEmpty(); +} + +bool nativeSelect(int fd, int timeout, bool selectForWrite) +{ + if (timeout < 0) + return false; + + // wait for connected + fd_set fds, fde; + FD_ZERO(&fds); + FD_ZERO(&fde); + FD_SET(fd, &fds); + FD_SET(fd, &fde); + + int ret; + do { + struct timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = timeout % 1000; + if (selectForWrite) + ret = ::select(fd + 1, 0, &fds, &fde, &tv); + else + ret = ::select(fd + 1, &fds, 0, &fde, &tv); + } while (ret == -1 && errno == EINTR); + return ret != 0; +} + +void tst_QTcpSocket_stresstest::nativeBlockingConnectDisconnect() +{ + QFETCH_GLOBAL(QString, hostname); + QFETCH_GLOBAL(int, port); + + double avg = 0; + for (int i = 0; i < AttemptCount; ++i) { + QElapsedTimer timeout; + byteCounter = 0; + timeout.start(); + +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) + alarm(10); +#endif + + // look up the host + QByteArray addr; + if (!nativeLookup(QUrl::toAce(hostname).constData(), port, addr)) + QFAIL("Lookup failed"); + + // connect + SOCKET fd = ::socket(AF_INET, SOCK_STREAM, 0); + QVERIFY(fd != INVALID_SOCKET); + QVERIFY(::connect(fd, (sockaddr *)addr.data(), addr.size()) != SOCKET_ERROR); + + // send request + { + QByteArray request = "GET /qtest/mediumfile HTTP/1.1\r\n" + "Connection: close\r\n" + "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" + "Host: " + hostname.toLatin1() + "\r\n" + "\r\n"; + qint64 bytesWritten = 0; + while (bytesWritten < request.size()) { + qint64 ret = ::send(fd, request.constData() + bytesWritten, request.size() - bytesWritten, 0); + if (ret == -1) { + ::close(fd); + QFAIL("Timeout"); + } + bytesWritten += ret; + } + } + + // receive reply + char buf[16384]; + while (true) { + qint64 ret = ::recv(fd, buf, sizeof buf, 0); + if (ret == -1) { + ::close(fd); + QFAIL("Timeout"); + } else if (ret == 0) { + break; // EOF + } + byteCounter += ret; + } + ::close(fd); + + double rate = (byteCounter / timeout.elapsed()); + avg = (i * avg + rate) / (i + 1); + if (intermediateDebug) + qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" + << (rate / 1024.0 / 1024 * 1000) << "MB/s"; + } + qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; + +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) + alarm(0); +#endif +} + +void tst_QTcpSocket_stresstest::nativeNonBlockingConnectDisconnect() +{ + QFETCH_GLOBAL(QString, hostname); + QFETCH_GLOBAL(int, port); + + double avg = 0; + for (int i = 0; i < AttemptCount; ++i) { + QElapsedTimer timeout; + byteCounter = 0; + timeout.start(); + + // look up the host + QByteArray addr; + if (!nativeLookup(QUrl::toAce(hostname).constData(), port, addr)) + QFAIL("Lookup failed"); + + SOCKET fd; + + { +#if defined(Q_OS_UNIX) + fd = ::socket(AF_INET, SOCK_STREAM, 0); + QVERIFY(fd != INVALID_SOCKET); + + // set the socket to non-blocking and start connecting +# if !defined(Q_OS_VXWORKS) + int flags = ::fcntl(fd, F_GETFL, 0); + QVERIFY(flags != -1); + QVERIFY(::fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1); +# else // Q_OS_VXWORKS + int onoff = 1; + QVERIFY(::ioctl(socketDescriptor, FIONBIO, &onoff) >= 0); +# endif // Q_OS_VXWORKS + while (true) { + if (::connect(fd, (sockaddr *)addr.data(), addr.size()) == -1) { + QVERIFY2(errno == EINPROGRESS, QByteArray("Error connecting: ").append(strerror(errno)).constData()); + QVERIFY2(nativeSelect(fd, 10000 - timeout.elapsed(), true), "Timeout"); + } else { + break; // connected + } + } +#elif defined(Q_OS_WIN) + fd = ::WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); + QVERIFY(fd != INVALID_SOCKET); + + // set the socket to non-blocking and start connecting + unsigned long buf = v; + unsigned long outBuf; + DWORD sizeWritten = 0; + QVERIFY(::WSAIoctl(fd, FIONBIO, &buf, sizeof(unsigned long), &outBuf, sizeof(unsigned long), &sizeWritten, 0,0) != SOCKET_ERROR); + + while (true) { + int connectResult = ::WSAConnect(fd, sockAddrPtr, sockAddrSize, 0,0,0,0); + if (connectResult == 0 || WSAGetLastError() == WSAEISCONN) { + break; // connected + } else { + QVERIFY2(WSAGetLastError() == WSAEINPROGRESS, "Unexpected error"); + QVERIFY2(nativeSelect(fd, 10000 - timeout.elapsed(), true), "Timeout"); + } + } +#endif + } + + // send request + { + QByteArray request = "GET /qtest/mediumfile HTTP/1.1\r\n" + "Connection: close\r\n" + "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" + "Host: " + hostname.toLatin1() + "\r\n" + "\r\n"; + qint64 bytesWritten = 0; + while (bytesWritten < request.size()) { + qint64 ret = ::send(fd, request.constData() + bytesWritten, request.size() - bytesWritten, 0); + if (ret == -1 && errno != EWOULDBLOCK) { + ::close(fd); + QFAIL(QByteArray("Error writing: ").append(strerror(errno)).constData()); + } else if (ret == -1) { + // wait for writing + QVERIFY2(nativeSelect(fd, 10000 - timeout.elapsed(), true), "Timeout"); + continue; + } + bytesWritten += ret; + } + } + + // receive reply + char buf[16384]; + while (true) { + qint64 ret = ::recv(fd, buf, sizeof buf, 0); + if (ret == -1 && errno != EWOULDBLOCK) { + ::close(fd); + QFAIL("Timeout"); + } else if (ret == -1) { + // wait for reading + QVERIFY2(nativeSelect(fd, 10000 - timeout.elapsed(), false), "Timeout"); + } else if (ret == 0) { + break; // EOF + } + byteCounter += ret; + } + ::close(fd); + + double rate = (byteCounter / timeout.elapsed()); + avg = (i * avg + rate) / (i + 1); + if (intermediateDebug) + qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" + << (rate / 1024.0 / 1024 * 1000) << "MB/s"; + } + qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; +} + +void tst_QTcpSocket_stresstest::blockingConnectDisconnect() +{ + QFETCH_GLOBAL(QString, hostname); + QFETCH_GLOBAL(int, port); + + double avg = 0; + for (int i = 0; i < AttemptCount; ++i) { + QElapsedTimer timeout; + byteCounter = 0; + timeout.start(); + + QTcpSocket socket; + socket.connectToHost(hostname, port); + QVERIFY2(socket.waitForConnected(), "Timeout"); + + socket.write("GET /qtest/mediumfile HTTP/1.1\r\n" + "Connection: close\r\n" + "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" + "Host: " + hostname.toLatin1() + "\r\n" + "\r\n"); + while (socket.bytesToWrite()) + QVERIFY2(socket.waitForBytesWritten(), "Timeout"); + + while (socket.state() == QAbstractSocket::ConnectedState && !timeout.hasExpired(10000)) { + socket.waitForReadyRead(); + byteCounter += socket.readAll().size(); // discard + } + double rate = (byteCounter / timeout.elapsed()); + avg = (i * avg + rate) / (i + 1); + if (intermediateDebug) + qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" + << (rate / 1024.0 / 1024 * 1000) << "MB/s"; + } + qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; +} + +void tst_QTcpSocket_stresstest::blockingPipelined() +{ + QFETCH_GLOBAL(QString, hostname); + QFETCH_GLOBAL(int, port); + + double avg = 0; + for (int i = 0; i < AttemptCount / 2; ++i) { + QElapsedTimer timeout; + byteCounter = 0; + timeout.start(); + + QTcpSocket socket; + socket.connectToHost(hostname, port); + QVERIFY2(socket.waitForConnected(), "Timeout"); + + for (int j = 0 ; j < 3; ++j) { + if (intermediateDebug) + qDebug("Attempt %d%c", i, 'a' + j); + socket.write("GET /qtest/mediumfile HTTP/1.1\r\n" + "Connection: " + QByteArray(j == 2 ? "close" : "keep-alive") + "\r\n" + "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" + "Host: " + hostname.toLatin1() + "\r\n" + "\r\n"); + while (socket.bytesToWrite()) + QVERIFY2(socket.waitForBytesWritten(), "Timeout"); + } + + while (socket.state() == QAbstractSocket::ConnectedState && !timeout.hasExpired(10000)) { + socket.waitForReadyRead(); + byteCounter += socket.readAll().size(); // discard + } + + double rate = (byteCounter / timeout.elapsed()); + avg = (i * avg + rate) / (i + 1); + if (intermediateDebug) + qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" + << (rate / 1024.0 / 1024 * 1000) << "MB/s"; + } + qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; +} + +void tst_QTcpSocket_stresstest::blockingMultipleRequests() +{ + QFETCH_GLOBAL(QString, hostname); + QFETCH_GLOBAL(int, port); + + double avg = 0; + for (int i = 0; i < AttemptCount / 5; ++i) { + QTcpSocket socket; + socket.connectToHost(hostname, port); + QVERIFY2(socket.waitForConnected(), "Timeout"); + + for (int j = 0 ; j < 5; ++j) { + QElapsedTimer timeout; + byteCounter = 0; + timeout.start(); + + socket.write("GET /qtest/mediumfile HTTP/1.1\r\n" + "Connection: keep-alive\r\n" + "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" + "Host: " + hostname.toLatin1() + "\r\n" + "\r\n"); + while (socket.bytesToWrite()) + QVERIFY2(socket.waitForBytesWritten(), "Timeout"); + + qint64 bytesRead = 0; + qint64 bytesExpected = -1; + QByteArray buffer; + while (socket.state() == QAbstractSocket::ConnectedState && !timeout.hasExpired(10000)) { + socket.waitForReadyRead(); + buffer += socket.readAll(); + byteCounter += buffer.size(); + int pos = buffer.indexOf("\r\n\r\n"); + if (pos == -1) + continue; + + bytesRead = buffer.length() - pos - 4; + + buffer.truncate(pos + 2); + buffer = buffer.toLower(); + pos = buffer.indexOf("\r\ncontent-length: "); + if (pos == -1) { + qWarning() << "no content-length:" << QString(buffer); + break; + } + pos += strlen("\r\ncontent-length: "); + + int eol = buffer.indexOf("\r\n", pos + 2); + if (eol == -1) { + qWarning() << "invalid header"; + break; + } + + bytesExpected = buffer.mid(pos, eol - pos).toLongLong(); + break; + } + QVERIFY(bytesExpected > 0); + QVERIFY2(!timeout.hasExpired(10000), "Timeout"); + + while (socket.state() == QAbstractSocket::ConnectedState && !timeout.hasExpired(10000) && bytesExpected > bytesRead) { + socket.waitForReadyRead(); + int blocklen = socket.read(bytesExpected - bytesRead).length(); // discard + bytesRead += blocklen; + byteCounter += blocklen; + } + QVERIFY2(!timeout.hasExpired(10000), "Timeout"); + QCOMPARE(bytesRead, bytesExpected); + + double rate = (byteCounter / timeout.elapsed()); + avg = (i * avg + rate) / (i + 1); + if (intermediateDebug) + qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" + << (rate / 1024.0 / 1024 * 1000) << "MB/s"; + } + + socket.disconnectFromHost(); + QVERIFY(socket.state() == QAbstractSocket::UnconnectedState); + } + qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; +} + +void tst_QTcpSocket_stresstest::connectDisconnect() +{ + QFETCH_GLOBAL(QString, hostname); + QFETCH_GLOBAL(int, port); + + double avg = 0; + for (int i = 0; i < AttemptCount; ++i) { + QElapsedTimer timeout; + byteCounter = 0; + timeout.start(); + + QTcpSocket socket; + socket.connectToHost(hostname, port); + + socket.write("GET /qtest/mediumfile HTTP/1.1\r\n" + "Connection: close\r\n" + "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" + "Host: " + hostname.toLatin1() + "\r\n" + "\r\n"); + connect(&socket, SIGNAL(readyRead()), SLOT(slotReadAll())); + + QTestEventLoop::instance().connect(&socket, SIGNAL(disconnected()), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(30); + QVERIFY2(!QTestEventLoop::instance().timeout(), "Timeout"); + double rate = (byteCounter / timeout.elapsed()); + avg = (i * avg + rate) / (i + 1); + if (intermediateDebug) + qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" + << (rate / 1024.0 / 1024 * 1000) << "MB/s"; + } + qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; +} + +void tst_QTcpSocket_stresstest::parallelConnectDisconnect_data() +{ + QTest::addColumn("parallelAttempts"); + QTest::newRow("1") << 1; + QTest::newRow("2") << 2; + QTest::newRow("4") << 4; + QTest::newRow("5") << 5; + QTest::newRow("6") << 6; + QTest::newRow("8") << 8; + QTest::newRow("10") << 10; + QTest::newRow("25") << 25; + QTest::newRow("100") << 100; + QTest::newRow("500") << 500; +} + +void tst_QTcpSocket_stresstest::parallelConnectDisconnect() +{ + QFETCH_GLOBAL(QString, hostname); + QFETCH_GLOBAL(int, port); + QFETCH(int, parallelAttempts); + + if (parallelAttempts > 100) { + QFETCH_GLOBAL(bool, isLocalhost); + if (!isLocalhost) + QSKIP("Localhost-only test", SkipSingle); + } + + double avg = 0; + for (int i = 0; i < qMax(2, AttemptCount/qMax(2, parallelAttempts/4)); ++i) { + QElapsedTimer timeout; + byteCounter = 0; + timeout.start(); + + QTcpSocket *socket = new QTcpSocket[parallelAttempts]; + for (int j = 0; j < parallelAttempts; ++j) { + socket[j].connectToHost(hostname, port); + + socket[j].write("GET /qtest/mediumfile HTTP/1.1\r\n" + "Connection: close\r\n" + "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" + "Host: " + hostname.toLatin1() + "\r\n" + "\r\n"); + connect(&socket[j], SIGNAL(readyRead()), SLOT(slotReadAll())); + + QTestEventLoop::instance().connect(&socket[j], SIGNAL(disconnected()), SLOT(exitLoop())); + } + + while (!timeout.hasExpired(30000)) { + QTestEventLoop::instance().enterLoop(10); + int done = 0; + for (int j = 0; j < parallelAttempts; ++j) + done += socket[j].state() == QAbstractSocket::UnconnectedState ? 1 : 0; + if (done == parallelAttempts) + break; + } + delete[] socket; + QVERIFY2(!timeout.hasExpired(30000), "Timeout"); + double rate = (byteCounter / timeout.elapsed()); + avg = (i * avg + rate) / (i + 1); + if (intermediateDebug) + qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" + << (rate / 1024.0 / 1024 * 1000) << "MB/s"; + } + qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; +} + +void tst_QTcpSocket_stresstest::namGet_data() +{ + QTest::addColumn("parallelAttempts"); + QTest::addColumn("pipelineAllowed"); + + QTest::newRow("1") << 1 << false; + QTest::newRow("1p") << 1 << true; + QTest::newRow("2") << 2 << false; + QTest::newRow("2p") << 2 << true; + QTest::newRow("4") << 4 << false; + QTest::newRow("4p") << 4 << true; + QTest::newRow("5") << 5 << false; + QTest::newRow("5p") << 5 << true; + QTest::newRow("6") << 6 << false; + QTest::newRow("6p") << 6 << true; + QTest::newRow("8") << 8 << false; + QTest::newRow("8p") << 8 << true; + QTest::newRow("10") << 10 << false; + QTest::newRow("10p") << 10 << true; + QTest::newRow("25") << 25 << false; + QTest::newRow("25p") << 25 << true; + QTest::newRow("100") << 100 << false; + QTest::newRow("100p") << 100 << true; + QTest::newRow("500") << 500 << false; + QTest::newRow("500p") << 500 << true; +} + +void tst_QTcpSocket_stresstest::namGet() +{ + QFETCH_GLOBAL(QString, hostname); + QFETCH_GLOBAL(int, port); + QFETCH(int, parallelAttempts); + QFETCH(bool, pipelineAllowed); + + if (parallelAttempts > 100) { + QFETCH_GLOBAL(bool, isLocalhost); + if (!isLocalhost) + QSKIP("Localhost-only test", SkipSingle); + } + + double avg = 0; + for (int i = 0; i < qMax(2, AttemptCount/qMax(2, parallelAttempts/4)); ++i) { + QElapsedTimer timeout; + byteCounter = 0; + timeout.start(); + + QUrl url; + url.setScheme("http"); + url.setHost(hostname); + url.setPort(port); + url.setEncodedPath("/qtest/mediumfile"); + QNetworkRequest req(url); + req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, pipelineAllowed); + + QVector > replies; + replies.resize(parallelAttempts); + for (int j = 0; j < parallelAttempts; ++j) { + QNetworkReply *r = manager.get(req); + + connect(r, SIGNAL(readyRead()), SLOT(slotReadAll())); + QTestEventLoop::instance().connect(r, SIGNAL(finished()), SLOT(exitLoop())); + + replies[j] = QSharedPointer(r); + } + + while (!timeout.hasExpired(30000)) { + QTestEventLoop::instance().enterLoop(10); + int done = 0; + for (int j = 0; j < parallelAttempts; ++j) + done += replies[j]->isFinished() ? 1 : 0; + if (done == parallelAttempts) + break; + } + replies.clear(); + + QVERIFY2(!timeout.hasExpired(30000), "Timeout"); + double rate = (byteCounter / timeout.elapsed()); + avg = (i * avg + rate) / (i + 1); + if (intermediateDebug) + qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" + << (rate / 1024.0 / 1024 * 1000) << "MB/s"; + } + qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; +} + +QTEST_MAIN(tst_QTcpSocket_stresstest); + +#include "tst_network_stresstest.moc" diff --git a/tests/manual/network_stresstest/tst_qtcpsocket_stresstest.cpp b/tests/manual/network_stresstest/tst_qtcpsocket_stresstest.cpp deleted file mode 100644 index 20ae9c0..0000000 --- a/tests/manual/network_stresstest/tst_qtcpsocket_stresstest.cpp +++ /dev/null @@ -1,739 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef QT_BUILD_INTERNAL -# include -#endif - -#include "minihttpserver.h" -#include "../network-settings.h" - -#include -#ifdef Q_OS_UNIX -# include -# include -# include -# include -# include -# include -# include -# include -# include - -typedef int SOCKET; -# define INVALID_SOCKET -1 -# define SOCKET_ERROR -1 - -#elif defined(Q_OS_WIN) -# include -#endif - -class tst_QTcpSocket_stresstest : public QObject -{ - Q_OBJECT -public: - enum { AttemptCount = 100 }; - tst_QTcpSocket_stresstest(); - MiniHttpServer server; - - qint64 byteCounter; - QNetworkAccessManager manager; - bool intermediateDebug; - -private: - void clearManager(); - -public slots: - void initTestCase_data(); - void init(); - - void slotReadAll() { byteCounter += static_cast(sender())->readAll().size(); } - -private Q_SLOTS: - void nativeBlockingConnectDisconnect(); - void nativeNonBlockingConnectDisconnect(); - void blockingConnectDisconnect(); - void blockingPipelined(); - void blockingMultipleRequests(); - void connectDisconnect(); - void parallelConnectDisconnect_data(); - void parallelConnectDisconnect(); - void namGet_data(); - void namGet(); -}; - -tst_QTcpSocket_stresstest::tst_QTcpSocket_stresstest() - : intermediateDebug(qgetenv("QTCPSOCKET_STRESSTEST").toInt() > 1) -{ -#ifdef Q_OS_WIN - WSAData wsadata; - - // IPv6 requires Winsock v2.0 or better. - WSAStartup(MAKEWORD(2,0), &wsadata); -#elif defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) - ::signal(SIGALRM, SIG_IGN); -#endif -} - -void tst_QTcpSocket_stresstest::initTestCase_data() -{ - QTest::addColumn("isLocalhost"); - QTest::addColumn("hostname"); - QTest::addColumn("port"); - - QTest::newRow("localhost") << true << "localhost" << server.port(); -// QTest::newRow("remote") << false << QtNetworkSettings::serverName() << 80; -} - -void tst_QTcpSocket_stresstest::init() -{ - if (qgetenv("QTCPSOCKET_STRESSTEST").toInt() == 0) - QSKIP("Stress test disabled", SkipAll); - - // clear the internal cache -#ifndef QT_BUILD_INTERNAL - if (strncmp(QTest::currentTestFunction(), "nam") == 0) - QSKIP("QNetworkAccessManager tests disabled", SkipAll); -#endif -} - -void tst_QTcpSocket_stresstest::clearManager() -{ -#ifdef QT_BUILD_INTERNAL - QNetworkAccessManagerPrivate::clearCache(&manager); - manager.setProxy(QNetworkProxy()); - manager.setCache(0); -#endif -} - -bool nativeLookup(const char *hostname, int port, QByteArray &buf) -{ -#if !defined(QT_NO_GETADDRINFO) && 0 - addrinfo *res = 0; - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - - int result = getaddrinfo(QUrl::toAce(hostname).constData(), QByteArray::number(port).constData(), &hints, &res); - if (!result) - return false; - for (addrinfo *node = res; node; node = node->ai_next) { - if (node->ai_family == AF_INET) { - buf = QByteArray((char *)node->ai_addr, node->ai_addrlen); - break; - } - } - freeaddrinfo(res); -#else - hostent *result = gethostbyname(hostname); - if (!result || result->h_addrtype != AF_INET) - return false; - - struct sockaddr_in s; - s.sin_family = AF_INET; - s.sin_port = htons(port); - s.sin_addr = *(struct in_addr *) result->h_addr_list[0]; - - buf = QByteArray((char *)&s, sizeof s); -#endif - - return !buf.isEmpty(); -} - -bool nativeSelect(int fd, int timeout, bool selectForWrite) -{ - if (timeout < 0) - return false; - - // wait for connected - fd_set fds, fde; - FD_ZERO(&fds); - FD_ZERO(&fde); - FD_SET(fd, &fds); - FD_SET(fd, &fde); - - int ret; - do { - struct timeval tv; - tv.tv_sec = timeout / 1000; - tv.tv_usec = timeout % 1000; - if (selectForWrite) - ret = ::select(fd + 1, 0, &fds, &fde, &tv); - else - ret = ::select(fd + 1, &fds, 0, &fde, &tv); - } while (ret == -1 && errno == EINTR); - return ret != 0; -} - -void tst_QTcpSocket_stresstest::nativeBlockingConnectDisconnect() -{ - QFETCH_GLOBAL(QString, hostname); - QFETCH_GLOBAL(int, port); - - double avg = 0; - for (int i = 0; i < AttemptCount; ++i) { - QElapsedTimer timeout; - byteCounter = 0; - timeout.start(); - -#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) - alarm(10); -#endif - - // look up the host - QByteArray addr; - if (!nativeLookup(QUrl::toAce(hostname).constData(), port, addr)) - QFAIL("Lookup failed"); - - // connect - SOCKET fd = ::socket(AF_INET, SOCK_STREAM, 0); - QVERIFY(fd != INVALID_SOCKET); - QVERIFY(::connect(fd, (sockaddr *)addr.data(), addr.size()) != SOCKET_ERROR); - - // send request - { - QByteArray request = "GET /qtest/mediumfile HTTP/1.1\r\n" - "Connection: close\r\n" - "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" - "Host: " + hostname.toLatin1() + "\r\n" - "\r\n"; - qint64 bytesWritten = 0; - while (bytesWritten < request.size()) { - qint64 ret = ::send(fd, request.constData() + bytesWritten, request.size() - bytesWritten, 0); - if (ret == -1) { - ::close(fd); - QFAIL("Timeout"); - } - bytesWritten += ret; - } - } - - // receive reply - char buf[16384]; - while (true) { - qint64 ret = ::recv(fd, buf, sizeof buf, 0); - if (ret == -1) { - ::close(fd); - QFAIL("Timeout"); - } else if (ret == 0) { - break; // EOF - } - byteCounter += ret; - } - ::close(fd); - - double rate = (byteCounter / timeout.elapsed()); - avg = (i * avg + rate) / (i + 1); - if (intermediateDebug) - qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" - << (rate / 1024.0 / 1024 * 1000) << "MB/s"; - } - qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; - -#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) - alarm(0); -#endif -} - -void tst_QTcpSocket_stresstest::nativeNonBlockingConnectDisconnect() -{ - QFETCH_GLOBAL(QString, hostname); - QFETCH_GLOBAL(int, port); - - double avg = 0; - for (int i = 0; i < AttemptCount; ++i) { - QElapsedTimer timeout; - byteCounter = 0; - timeout.start(); - - // look up the host - QByteArray addr; - if (!nativeLookup(QUrl::toAce(hostname).constData(), port, addr)) - QFAIL("Lookup failed"); - - SOCKET fd; - - { -#if defined(Q_OS_UNIX) - fd = ::socket(AF_INET, SOCK_STREAM, 0); - QVERIFY(fd != INVALID_SOCKET); - - // set the socket to non-blocking and start connecting -# if !defined(Q_OS_VXWORKS) - int flags = ::fcntl(fd, F_GETFL, 0); - QVERIFY(flags != -1); - QVERIFY(::fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1); -# else // Q_OS_VXWORKS - int onoff = 1; - QVERIFY(::ioctl(socketDescriptor, FIONBIO, &onoff) >= 0); -# endif // Q_OS_VXWORKS - while (true) { - if (::connect(fd, (sockaddr *)addr.data(), addr.size()) == -1) { - QVERIFY2(errno == EINPROGRESS, QByteArray("Error connecting: ").append(strerror(errno)).constData()); - QVERIFY2(nativeSelect(fd, 10000 - timeout.elapsed(), true), "Timeout"); - } else { - break; // connected - } - } -#elif defined(Q_OS_WIN) - fd = ::WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); - QVERIFY(fd != INVALID_SOCKET); - - // set the socket to non-blocking and start connecting - unsigned long buf = v; - unsigned long outBuf; - DWORD sizeWritten = 0; - QVERIFY(::WSAIoctl(fd, FIONBIO, &buf, sizeof(unsigned long), &outBuf, sizeof(unsigned long), &sizeWritten, 0,0) != SOCKET_ERROR); - - while (true) { - int connectResult = ::WSAConnect(fd, sockAddrPtr, sockAddrSize, 0,0,0,0); - if (connectResult == 0 || WSAGetLastError() == WSAEISCONN) { - break; // connected - } else { - QVERIFY2(WSAGetLastError() == WSAEINPROGRESS, "Unexpected error"); - QVERIFY2(nativeSelect(fd, 10000 - timeout.elapsed(), true), "Timeout"); - } - } -#endif - } - - // send request - { - QByteArray request = "GET /qtest/mediumfile HTTP/1.1\r\n" - "Connection: close\r\n" - "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" - "Host: " + hostname.toLatin1() + "\r\n" - "\r\n"; - qint64 bytesWritten = 0; - while (bytesWritten < request.size()) { - qint64 ret = ::send(fd, request.constData() + bytesWritten, request.size() - bytesWritten, 0); - if (ret == -1 && errno != EWOULDBLOCK) { - ::close(fd); - QFAIL(QByteArray("Error writing: ").append(strerror(errno)).constData()); - } else if (ret == -1) { - // wait for writing - QVERIFY2(nativeSelect(fd, 10000 - timeout.elapsed(), true), "Timeout"); - continue; - } - bytesWritten += ret; - } - } - - // receive reply - char buf[16384]; - while (true) { - qint64 ret = ::recv(fd, buf, sizeof buf, 0); - if (ret == -1 && errno != EWOULDBLOCK) { - ::close(fd); - QFAIL("Timeout"); - } else if (ret == -1) { - // wait for reading - QVERIFY2(nativeSelect(fd, 10000 - timeout.elapsed(), false), "Timeout"); - } else if (ret == 0) { - break; // EOF - } - byteCounter += ret; - } - ::close(fd); - - double rate = (byteCounter / timeout.elapsed()); - avg = (i * avg + rate) / (i + 1); - if (intermediateDebug) - qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" - << (rate / 1024.0 / 1024 * 1000) << "MB/s"; - } - qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; -} - -void tst_QTcpSocket_stresstest::blockingConnectDisconnect() -{ - QFETCH_GLOBAL(QString, hostname); - QFETCH_GLOBAL(int, port); - - double avg = 0; - for (int i = 0; i < AttemptCount; ++i) { - QElapsedTimer timeout; - byteCounter = 0; - timeout.start(); - - QTcpSocket socket; - socket.connectToHost(hostname, port); - QVERIFY2(socket.waitForConnected(), "Timeout"); - - socket.write("GET /qtest/mediumfile HTTP/1.1\r\n" - "Connection: close\r\n" - "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" - "Host: " + hostname.toLatin1() + "\r\n" - "\r\n"); - while (socket.bytesToWrite()) - QVERIFY2(socket.waitForBytesWritten(), "Timeout"); - - while (socket.state() == QAbstractSocket::ConnectedState && !timeout.hasExpired(10000)) { - socket.waitForReadyRead(); - byteCounter += socket.readAll().size(); // discard - } - double rate = (byteCounter / timeout.elapsed()); - avg = (i * avg + rate) / (i + 1); - if (intermediateDebug) - qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" - << (rate / 1024.0 / 1024 * 1000) << "MB/s"; - } - qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; -} - -void tst_QTcpSocket_stresstest::blockingPipelined() -{ - QFETCH_GLOBAL(QString, hostname); - QFETCH_GLOBAL(int, port); - - double avg = 0; - for (int i = 0; i < AttemptCount / 2; ++i) { - QElapsedTimer timeout; - byteCounter = 0; - timeout.start(); - - QTcpSocket socket; - socket.connectToHost(hostname, port); - QVERIFY2(socket.waitForConnected(), "Timeout"); - - for (int j = 0 ; j < 3; ++j) { - if (intermediateDebug) - qDebug("Attempt %d%c", i, 'a' + j); - socket.write("GET /qtest/mediumfile HTTP/1.1\r\n" - "Connection: " + QByteArray(j == 2 ? "close" : "keep-alive") + "\r\n" - "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" - "Host: " + hostname.toLatin1() + "\r\n" - "\r\n"); - while (socket.bytesToWrite()) - QVERIFY2(socket.waitForBytesWritten(), "Timeout"); - } - - while (socket.state() == QAbstractSocket::ConnectedState && !timeout.hasExpired(10000)) { - socket.waitForReadyRead(); - byteCounter += socket.readAll().size(); // discard - } - - double rate = (byteCounter / timeout.elapsed()); - avg = (i * avg + rate) / (i + 1); - if (intermediateDebug) - qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" - << (rate / 1024.0 / 1024 * 1000) << "MB/s"; - } - qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; -} - -void tst_QTcpSocket_stresstest::blockingMultipleRequests() -{ - QFETCH_GLOBAL(QString, hostname); - QFETCH_GLOBAL(int, port); - - double avg = 0; - for (int i = 0; i < AttemptCount / 5; ++i) { - QTcpSocket socket; - socket.connectToHost(hostname, port); - QVERIFY2(socket.waitForConnected(), "Timeout"); - - for (int j = 0 ; j < 5; ++j) { - QElapsedTimer timeout; - byteCounter = 0; - timeout.start(); - - socket.write("GET /qtest/mediumfile HTTP/1.1\r\n" - "Connection: keep-alive\r\n" - "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" - "Host: " + hostname.toLatin1() + "\r\n" - "\r\n"); - while (socket.bytesToWrite()) - QVERIFY2(socket.waitForBytesWritten(), "Timeout"); - - qint64 bytesRead = 0; - qint64 bytesExpected = -1; - QByteArray buffer; - while (socket.state() == QAbstractSocket::ConnectedState && !timeout.hasExpired(10000)) { - socket.waitForReadyRead(); - buffer += socket.readAll(); - byteCounter += buffer.size(); - int pos = buffer.indexOf("\r\n\r\n"); - if (pos == -1) - continue; - - bytesRead = buffer.length() - pos - 4; - - buffer.truncate(pos + 2); - buffer = buffer.toLower(); - pos = buffer.indexOf("\r\ncontent-length: "); - if (pos == -1) { - qWarning() << "no content-length:" << QString(buffer); - break; - } - pos += strlen("\r\ncontent-length: "); - - int eol = buffer.indexOf("\r\n", pos + 2); - if (eol == -1) { - qWarning() << "invalid header"; - break; - } - - bytesExpected = buffer.mid(pos, eol - pos).toLongLong(); - break; - } - QVERIFY(bytesExpected > 0); - QVERIFY2(!timeout.hasExpired(10000), "Timeout"); - - while (socket.state() == QAbstractSocket::ConnectedState && !timeout.hasExpired(10000) && bytesExpected > bytesRead) { - socket.waitForReadyRead(); - int blocklen = socket.read(bytesExpected - bytesRead).length(); // discard - bytesRead += blocklen; - byteCounter += blocklen; - } - QVERIFY2(!timeout.hasExpired(10000), "Timeout"); - QCOMPARE(bytesRead, bytesExpected); - - double rate = (byteCounter / timeout.elapsed()); - avg = (i * avg + rate) / (i + 1); - if (intermediateDebug) - qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" - << (rate / 1024.0 / 1024 * 1000) << "MB/s"; - } - - socket.disconnectFromHost(); - QVERIFY(socket.state() == QAbstractSocket::UnconnectedState); - } - qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; -} - -void tst_QTcpSocket_stresstest::connectDisconnect() -{ - QFETCH_GLOBAL(QString, hostname); - QFETCH_GLOBAL(int, port); - - double avg = 0; - for (int i = 0; i < AttemptCount; ++i) { - QElapsedTimer timeout; - byteCounter = 0; - timeout.start(); - - QTcpSocket socket; - socket.connectToHost(hostname, port); - - socket.write("GET /qtest/mediumfile HTTP/1.1\r\n" - "Connection: close\r\n" - "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" - "Host: " + hostname.toLatin1() + "\r\n" - "\r\n"); - connect(&socket, SIGNAL(readyRead()), SLOT(slotReadAll())); - - QTestEventLoop::instance().connect(&socket, SIGNAL(disconnected()), SLOT(exitLoop())); - QTestEventLoop::instance().enterLoop(30); - QVERIFY2(!QTestEventLoop::instance().timeout(), "Timeout"); - double rate = (byteCounter / timeout.elapsed()); - avg = (i * avg + rate) / (i + 1); - if (intermediateDebug) - qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" - << (rate / 1024.0 / 1024 * 1000) << "MB/s"; - } - qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; -} - -void tst_QTcpSocket_stresstest::parallelConnectDisconnect_data() -{ - QTest::addColumn("parallelAttempts"); - QTest::newRow("1") << 1; - QTest::newRow("2") << 2; - QTest::newRow("4") << 4; - QTest::newRow("5") << 5; - QTest::newRow("6") << 6; - QTest::newRow("8") << 8; - QTest::newRow("10") << 10; - QTest::newRow("25") << 25; - QTest::newRow("100") << 100; - QTest::newRow("500") << 500; -} - -void tst_QTcpSocket_stresstest::parallelConnectDisconnect() -{ - QFETCH_GLOBAL(QString, hostname); - QFETCH_GLOBAL(int, port); - QFETCH(int, parallelAttempts); - - if (parallelAttempts > 100) { - QFETCH_GLOBAL(bool, isLocalhost); - if (!isLocalhost) - QSKIP("Localhost-only test", SkipSingle); - } - - double avg = 0; - for (int i = 0; i < qMax(2, AttemptCount/qMax(2, parallelAttempts/4)); ++i) { - QElapsedTimer timeout; - byteCounter = 0; - timeout.start(); - - QTcpSocket *socket = new QTcpSocket[parallelAttempts]; - for (int j = 0; j < parallelAttempts; ++j) { - socket[j].connectToHost(hostname, port); - - socket[j].write("GET /qtest/mediumfile HTTP/1.1\r\n" - "Connection: close\r\n" - "User-Agent: tst_QTcpSocket_stresstest/1.0\r\n" - "Host: " + hostname.toLatin1() + "\r\n" - "\r\n"); - connect(&socket[j], SIGNAL(readyRead()), SLOT(slotReadAll())); - - QTestEventLoop::instance().connect(&socket[j], SIGNAL(disconnected()), SLOT(exitLoop())); - } - - while (!timeout.hasExpired(30000)) { - QTestEventLoop::instance().enterLoop(10); - int done = 0; - for (int j = 0; j < parallelAttempts; ++j) - done += socket[j].state() == QAbstractSocket::UnconnectedState ? 1 : 0; - if (done == parallelAttempts) - break; - } - delete[] socket; - QVERIFY2(!timeout.hasExpired(30000), "Timeout"); - double rate = (byteCounter / timeout.elapsed()); - avg = (i * avg + rate) / (i + 1); - if (intermediateDebug) - qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" - << (rate / 1024.0 / 1024 * 1000) << "MB/s"; - } - qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; -} - -void tst_QTcpSocket_stresstest::namGet_data() -{ - QTest::addColumn("parallelAttempts"); - QTest::addColumn("pipelineAllowed"); - - QTest::newRow("1") << 1 << false; - QTest::newRow("1p") << 1 << true; - QTest::newRow("2") << 2 << false; - QTest::newRow("2p") << 2 << true; - QTest::newRow("4") << 4 << false; - QTest::newRow("4p") << 4 << true; - QTest::newRow("5") << 5 << false; - QTest::newRow("5p") << 5 << true; - QTest::newRow("6") << 6 << false; - QTest::newRow("6p") << 6 << true; - QTest::newRow("8") << 8 << false; - QTest::newRow("8p") << 8 << true; - QTest::newRow("10") << 10 << false; - QTest::newRow("10p") << 10 << true; - QTest::newRow("25") << 25 << false; - QTest::newRow("25p") << 25 << true; - QTest::newRow("100") << 100 << false; - QTest::newRow("100p") << 100 << true; - QTest::newRow("500") << 500 << false; - QTest::newRow("500p") << 500 << true; -} - -void tst_QTcpSocket_stresstest::namGet() -{ - QFETCH_GLOBAL(QString, hostname); - QFETCH_GLOBAL(int, port); - QFETCH(int, parallelAttempts); - QFETCH(bool, pipelineAllowed); - - if (parallelAttempts > 100) { - QFETCH_GLOBAL(bool, isLocalhost); - if (!isLocalhost) - QSKIP("Localhost-only test", SkipSingle); - } - - double avg = 0; - for (int i = 0; i < qMax(2, AttemptCount/qMax(2, parallelAttempts/4)); ++i) { - QElapsedTimer timeout; - byteCounter = 0; - timeout.start(); - - QUrl url; - url.setScheme("http"); - url.setHost(hostname); - url.setPort(port); - url.setEncodedPath("/qtest/mediumfile"); - QNetworkRequest req(url); - req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, pipelineAllowed); - - QVector > replies; - replies.resize(parallelAttempts); - for (int j = 0; j < parallelAttempts; ++j) { - QNetworkReply *r = manager.get(req); - - connect(r, SIGNAL(readyRead()), SLOT(slotReadAll())); - QTestEventLoop::instance().connect(r, SIGNAL(finished()), SLOT(exitLoop())); - - replies[j] = QSharedPointer(r); - } - - while (!timeout.hasExpired(30000)) { - QTestEventLoop::instance().enterLoop(10); - int done = 0; - for (int j = 0; j < parallelAttempts; ++j) - done += replies[j]->isFinished() ? 1 : 0; - if (done == parallelAttempts) - break; - } - replies.clear(); - - QVERIFY2(!timeout.hasExpired(30000), "Timeout"); - double rate = (byteCounter / timeout.elapsed()); - avg = (i * avg + rate) / (i + 1); - if (intermediateDebug) - qDebug() << i << byteCounter << "bytes in" << timeout.elapsed() << "ms:" - << (rate / 1024.0 / 1024 * 1000) << "MB/s"; - } - qDebug() << "Average transfer rate was" << (avg / 1024.0 / 1024 * 1000) << "MB/s"; -} - -QTEST_MAIN(tst_QTcpSocket_stresstest); - -#include "tst_qtcpsocket_stresstest.moc" -- cgit v0.12