summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/io/qfsfileengine.cpp168
-rw-r--r--src/network/kernel/qhostinfo_p.h6
-rw-r--r--src/src.pro33
-rw-r--r--src/tools/tools.pro70
-rw-r--r--tests/auto/qfile/tst_qfile.cpp166
-rw-r--r--tests/auto/qlocalsocket/tst_qlocalsocket.cpp10
-rw-r--r--tests/auto/qnetworkreply/tst_qnetworkreply.cpp479
-rw-r--r--tests/benchmarks/qnetworkreply/tst_qnetworkreply.cpp530
-rw-r--r--tools/configure/configureapp.cpp5
9 files changed, 829 insertions, 638 deletions
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index d376dc7..9ab831f 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -76,17 +76,6 @@ QT_BEGIN_NAMESPACE
# endif
#endif
-#ifdef Q_OS_SYMBIAN
- // Using default 4k block in symbian is highly inefficient due to
- // the fact that each file operation requires slow IPC calls, so
- // use somewhat larger block size.
-# define FDFH_BLOCK_SIZE 16384
-#else
- // Read/write in blocks of 4k to avoid platform limitations (Windows
- // commonly bails out if you read or write too large blocks at once).
-# define FDFH_BLOCK_SIZE 4096
-#endif
-
/*! \class QFSFileEngine
\brief The QFSFileEngine class implements Qt's default file engine.
\since 4.1
@@ -633,67 +622,55 @@ qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len)
{
Q_Q(QFSFileEngine);
- // Buffered stdlib mode.
+ if (len < 0 || len != qint64(size_t(len))) {
+ q->setError(QFile::ReadError, qt_error_string(EINVAL));
+ return -1;
+ }
+
+ qint64 readBytes = 0;
+ bool eof = false;
+
if (fh) {
- qint64 readBytes = 0;
- qint64 read = 0;
- int retry = 0;
+ // Buffered stdlib mode.
- qint64 bytesToRead;
+ size_t result;
+ bool retry = true;
do {
- if (retry == 1)
- retry = 2;
-
- bytesToRead = qMin<qint64>(FDFH_BLOCK_SIZE, len - read);
- do {
- readBytes = fread(data + read, 1, size_t(bytesToRead), fh);
- } while (readBytes == 0 && !feof(fh) && errno == EINTR);
-
- if (readBytes > 0) {
- read += readBytes;
- } else if (!retry && feof(fh)) {
- // Synchronize and try again (just once though).
- if (++retry == 1)
- QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET);
+ result = fread(data + readBytes, 1, size_t(len - readBytes), fh);
+ eof = feof(fh);
+ if (retry && eof && result == 0) {
+ // On Mac OS, this is needed, e.g., if a file was written to
+ // through another stream since our last read. See test
+ // tst_QFile::appendAndRead
+ QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET); // re-sync stream.
+ retry = false;
+ continue;
}
- } while (retry == 1 || (readBytes == bytesToRead && read < len));
+ readBytes += result;
+ } while (!eof && (result == 0 ? errno == EINTR : readBytes < len));
- // Return the number of bytes read, or if nothing was read, return -1
- // if an error occurred, or 0 if we detected EOF.
- if (read == 0) {
- q->setError(QFile::ReadError, qt_error_string(int(errno)));
- if (!feof(fh))
- read = -1;
- }
- return read;
- }
+ } else if (fd != -1) {
+ // Unbuffered stdio mode.
- // Unbuffered stdio mode.
- qint64 ret = 0;
- if (len) {
+#ifdef Q_OS_WIN
int result;
- qint64 read = 0;
- errno = 0;
-
+#else
+ ssize_t result;
+#endif
do {
- qint64 bytesToRead = qMin<qint64>(FDFH_BLOCK_SIZE, len - read);
- do {
- result = QT_READ(fd, data + read, int(bytesToRead));
- } while (result == -1 && errno == EINTR);
- if (result > 0)
- read += result;
- } while (result > 0 && read < len);
-
- // Return the number of bytes read, or if nothing was read, return -1
- // if an error occurred.
- if (read > 0) {
- ret += read;
- } else if (read == 0 && result < 0) {
- ret = -1;
- q->setError(QFile::ReadError, qt_error_string(errno));
- }
+ result = QT_READ(fd, data + readBytes, size_t(len - readBytes));
+ } while ((result == -1 && errno == EINTR)
+ || (result > 0 && (readBytes += result) < len));
+
+ eof = !(result == -1);
}
- return ret;
+
+ if (!eof && readBytes == 0) {
+ readBytes = -1;
+ q->setError(QFile::ReadError, qt_error_string(errno));
+ }
+
+ return readBytes;
}
/*!
@@ -773,34 +750,45 @@ qint64 QFSFileEngine::write(const char *data, qint64 len)
qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len)
{
Q_Q(QFSFileEngine);
- qint64 result;
- qint64 written = 0;
- do {
- qint64 bytesToWrite = qMin<qint64>(FDFH_BLOCK_SIZE, len - written);
- if (fh) {
- do {
- // Buffered stdlib mode.
- result = qint64(fwrite(data + written, 1, size_t(bytesToWrite), fh));
- } while (result == 0 && errno == EINTR);
- if (bytesToWrite > 0 && result == 0)
- result = -1;
- } else {
- do {
- // Unbuffered stdio mode.
- result = QT_WRITE(fd, data + written, bytesToWrite);
- } while (result == -1 && errno == EINTR);
- }
- if (result > 0)
- written += qint64(result);
- } while (written < len && result > 0);
-
- // If we read anything, return that with success. Otherwise, set an error,
- // and return the last return value.
- if (result > 0)
- return written;
- q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError, qt_error_string(errno));
- return result;
+ if (len < 0 || len != qint64(size_t(len))) {
+ q->setError(QFile::WriteError, qt_error_string(EINVAL));
+ return -1;
+ }
+
+ qint64 writtenBytes = 0;
+
+ if (fh) {
+ // Buffered stdlib mode.
+
+ size_t result;
+ bool eof;
+ do {
+ result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh);
+ writtenBytes += result;
+ eof = feof(fh);
+ } while (!eof && (result == 0 ? errno == EINTR : writtenBytes < len));
+
+ } else if (fd != -1) {
+ // Unbuffered stdio mode.
+
+#ifdef Q_OS_WIN
+ int result;
+#else
+ ssize_t result;
+#endif
+ do {
+ result = QT_WRITE(fd, data + writtenBytes, size_t(len - writtenBytes));
+ } while ((result == -1 && errno == EINTR)
+ || (result > 0 && (writtenBytes += result) < len));
+ }
+
+ if (writtenBytes == 0) {
+ writtenBytes = -1;
+ q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError, qt_error_string(errno));
+ }
+
+ return writtenBytes;
}
/*!
diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h
index 64c5152..afd3570 100644
--- a/src/network/kernel/qhostinfo_p.h
+++ b/src/network/kernel/qhostinfo_p.h
@@ -161,9 +161,11 @@ public Q_SLOTS:
cond.wakeOne();
}
#ifndef QT_NO_THREAD
- if (!wait(QHOSTINFO_THREAD_WAIT))
+ if (!wait(QHOSTINFO_THREAD_WAIT)) {
terminate();
- wait();
+ // Don't wait forever; see QTBUG-5296.
+ wait(QHOSTINFO_THREAD_WAIT);
+ }
#endif
}
diff --git a/src/src.pro b/src/src.pro
index 5307612..7cab6c9 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -8,17 +8,12 @@ wince*:{
} else:symbian {
SRC_SUBDIRS += src_s60main src_corelib src_xml src_gui src_network src_sql src_testlib src_s60installs
} else {
- SRC_SUBDIRS += src_tools_bootstrap src_tools_moc src_tools_rcc src_tools_uic src_corelib src_xml src_network src_gui src_sql src_testlib
+ SRC_SUBDIRS += src_corelib src_xml src_network src_gui src_sql src_testlib
!vxworks:contains(QT_CONFIG, qt3support): SRC_SUBDIRS += src_qt3support
+ include(tools/tools.pro)
contains(QT_CONFIG, dbus):SRC_SUBDIRS += src_dbus
- !cross_compile {
- contains(QT_CONFIG, qt3support): SRC_SUBDIRS += src_tools_uic3
- }
-}
-win32:{
- SRC_SUBDIRS += src_activeqt
- !wince*: SRC_SUBDIRS += src_tools_idc
}
+win32:SRC_SUBDIRS += src_activeqt
contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles2): SRC_SUBDIRS += src_opengl
contains(QT_CONFIG, openvg): SRC_SUBDIRS += src_openvg
@@ -41,14 +36,6 @@ src_s60installs.subdir = $$QT_SOURCE_TREE/src/s60installs
src_s60installs.target = sub-s60installs
src_winmain.subdir = $$QT_SOURCE_TREE/src/winmain
src_winmain.target = sub-winmain
-src_tools_bootstrap.subdir = $$QT_SOURCE_TREE/src/tools/bootstrap
-src_tools_bootstrap.target = sub-tools-bootstrap
-src_tools_moc.subdir = $$QT_SOURCE_TREE/src/tools/moc
-src_tools_moc.target = sub-moc
-src_tools_rcc.subdir = $$QT_SOURCE_TREE/src/tools/rcc
-src_tools_rcc.target = sub-rcc
-src_tools_uic.subdir = $$QT_SOURCE_TREE/src/tools/uic
-src_tools_uic.target = sub-uic
src_corelib.subdir = $$QT_SOURCE_TREE/src/corelib
src_corelib.target = sub-corelib
src_xml.subdir = $$QT_SOURCE_TREE/src/xml
@@ -79,12 +66,8 @@ src_phonon.subdir = $$QT_SOURCE_TREE/src/phonon
src_phonon.target = sub-phonon
src_multimedia.subdir = $$QT_SOURCE_TREE/src/multimedia
src_multimedia.target = sub-multimedia
-src_tools_uic3.subdir = $$QT_SOURCE_TREE/src/tools/uic3
-src_tools_uic3.target = sub-uic3
src_activeqt.subdir = $$QT_SOURCE_TREE/src/activeqt
src_activeqt.target = sub-activeqt
-src_tools_idc.subdir = $$QT_SOURCE_TREE/src/tools/idc
-src_tools_idc.target = sub-idc
src_plugins.subdir = $$QT_SOURCE_TREE/src/plugins
src_plugins.target = sub-plugins
src_testlib.subdir = $$QT_SOURCE_TREE/src/testlib
@@ -98,9 +81,6 @@ src_declarative.target = sub-declarative
#CONFIG += ordered
!wince*:!symbian:!ordered {
- src_tools_moc.depends = src_tools_bootstrap
- src_tools_rcc.depends = src_tools_bootstrap
- src_tools_uic.depends = src_tools_bootstrap
src_corelib.depends = src_tools_moc src_tools_rcc
src_gui.depends = src_corelib src_tools_uic
embedded: src_gui.depends += src_network
@@ -116,10 +96,10 @@ src_declarative.target = sub-declarative
src_sql.depends = src_corelib
src_testlib.depends = src_corelib
src_qt3support.depends = src_gui src_xml src_network src_sql
+ src_tools_idc.depends = src_corelib # target defined in tools.pro
+ src_tools_uic3.depends = src_qt3support src_xml # target defined in tools.pro
src_phonon.depends = src_gui
src_multimedia.depends = src_gui
- src_tools_uic3.depends = src_qt3support src_xml
- src_tools_idc.depends = src_corelib
src_tools_activeqt.depends = src_tools_idc src_gui
src_declarative.depends = src_xml src_gui src_script src_network src_svg
src_plugins.depends = src_gui src_sql src_svg
@@ -146,8 +126,6 @@ sub_src_target.recurse_target =
QMAKE_EXTRA_TARGETS += sub_src_target
# This gives us a top level debug/release
-EXTRA_DEBUG_TARGETS =
-EXTRA_RELEASE_TARGETS =
for(subname, SRC_SUBDIRS) {
subdir = $$subname
!isEmpty($${subname}.subdir):subdir = $$eval($${subname}.subdir)
@@ -189,4 +167,3 @@ QMAKE_EXTRA_TARGETS += debug release
}
SUBDIRS += $$SRC_SUBDIRS
-
diff --git a/src/tools/tools.pro b/src/tools/tools.pro
new file mode 100644
index 0000000..7c8fb47
--- /dev/null
+++ b/src/tools/tools.pro
@@ -0,0 +1,70 @@
+TEMPLATE = subdirs
+
+TOOLS_SUBDIRS = src_tools_bootstrap src_tools_moc src_tools_rcc src_tools_uic
+!cross_compile {
+ contains(QT_CONFIG, qt3support): SRC_SUBDIRS += src_tools_uic3
+ win32:!wince*: SRC_SUBDIRS += src_tools_idc
+}
+
+# Set subdir and respective target name
+src_tools_bootstrap.subdir = $$QT_SOURCE_TREE/src/tools/bootstrap
+src_tools_bootstrap.target = sub-tools-bootstrap
+src_tools_moc.subdir = $$QT_SOURCE_TREE/src/tools/moc
+src_tools_moc.target = sub-moc
+src_tools_rcc.subdir = $$QT_SOURCE_TREE/src/tools/rcc
+src_tools_rcc.target = sub-rcc
+src_tools_uic.subdir = $$QT_SOURCE_TREE/src/tools/uic
+src_tools_uic.target = sub-uic
+src_tools_uic3.subdir = $$QT_SOURCE_TREE/src/tools/uic3
+src_tools_uic3.target = sub-uic3
+src_tools_idc.subdir = $$QT_SOURCE_TREE/src/tools/idc
+src_tools_idc.target = sub-idc
+
+# Set dependencies for each subdir
+src_tools_moc.depends = src_tools_bootstrap
+src_tools_rcc.depends = src_tools_bootstrap
+src_tools_uic.depends = src_tools_bootstrap
+
+# Special handling, depending on type of project, if it used debug/release or only has one configuration
+EXTRA_DEBUG_TARGETS =
+EXTRA_RELEASE_TARGETS =
+!symbian {
+ for(subname, TOOLS_SUBDIRS) {
+ subdir = $$subname
+ !isEmpty($${subname}.subdir):subdir = $$eval($${subname}.subdir)
+ subpro = $$subdir/$${basename(subdir)}.pro
+ !exists($$subpro):next()
+ subtarget = $$replace(subdir, [^A-Za-z0-9], _)
+ reg_src = $$replace(QT_SOURCE_TREE, \\\\, \\\\)
+ subdir = $$replace(subdir, $$reg_src, $$QT_BUILD_TREE)
+ subdir = $$replace(subdir, /, $$QMAKE_DIR_SEP)
+ subdir = $$replace(subdir, \\\\, $$QMAKE_DIR_SEP)
+ SUB_TEMPLATE = $$list($$fromfile($$subpro, TEMPLATE))
+ !isEqual(subname, src_tools_bootstrap):if(isEqual($$SUB_TEMPLATE, lib) | isEqual($$SUB_TEMPLATE, subdirs) | isEqual(subname, src_tools_idc) | isEqual(subname, src_tools_uic3)):!separate_debug_info {
+ #debug
+ eval(debug-$${subtarget}.depends = $${subdir}\$${QMAKE_DIR_SEP}$(MAKEFILE) $$EXTRA_DEBUG_TARGETS)
+ eval(debug-$${subtarget}.commands = (cd $$subdir && $(MAKE) -f $(MAKEFILE) debug))
+ EXTRA_DEBUG_TARGETS += debug-$${subtarget}
+ QMAKE_EXTRA_TARGETS += debug-$${subtarget}
+ #release
+ eval(release-$${subtarget}.depends = $${subdir}\$${QMAKE_DIR_SEP}$(MAKEFILE) $$EXTRA_RELEASE_TARGETS)
+ eval(release-$${subtarget}.commands = (cd $$subdir && $(MAKE) -f $(MAKEFILE) release))
+ EXTRA_RELEASE_TARGETS += release-$${subtarget}
+ QMAKE_EXTRA_TARGETS += release-$${subtarget}
+ } else { #do not have a real debug target/release
+ #debug
+ eval(debug-$${subtarget}.depends = $${subdir}\$${QMAKE_DIR_SEP}$(MAKEFILE) $$EXTRA_DEBUG_TARGETS)
+ eval(debug-$${subtarget}.commands = (cd $$subdir && $(MAKE) -f $(MAKEFILE) first))
+ EXTRA_DEBUG_TARGETS += debug-$${subtarget}
+ QMAKE_EXTRA_TARGETS += debug-$${subtarget}
+ #release
+ eval(release-$${subtarget}.depends = $${subdir}\$${QMAKE_DIR_SEP}$(MAKEFILE) $$EXTRA_RELEASE_TARGETS)
+ eval(release-$${subtarget}.commands = (cd $$subdir && $(MAKE) -f $(MAKEFILE) first))
+ EXTRA_RELEASE_TARGETS += release-$${subtarget}
+ QMAKE_EXTRA_TARGETS += release-$${subtarget}
+ }
+ }
+}
+
+SUBDIRS = $$TOOLS_SUBDIRS $$SUBDIRS
+isEqual(TARGET,tools): SUBDIRS += $$SRC_SUBDIRS
diff --git a/tests/auto/qfile/tst_qfile.cpp b/tests/auto/qfile/tst_qfile.cpp
index 55cc286..b3d6fd9 100644
--- a/tests/auto/qfile/tst_qfile.cpp
+++ b/tests/auto/qfile/tst_qfile.cpp
@@ -91,6 +91,10 @@
#define STDERR_FILENO 2
#endif
+#ifndef QT_OPEN_BINARY
+#define QT_OPEN_BINARY 0
+#endif
+
Q_DECLARE_METATYPE(QFile::FileError)
//TESTED_CLASS=
@@ -211,6 +215,81 @@ public:
// disabled this test for the moment... it hangs
void invalidFile_data();
void invalidFile();
+
+private:
+ enum FileType { OpenQFile, OpenFd, OpenStream };
+
+ bool openFd(QFile &file, QIODevice::OpenMode mode)
+ {
+ int fdMode = QT_OPEN_LARGEFILE | QT_OPEN_BINARY;
+
+ // File will be truncated if in Write mode.
+ if (mode & QIODevice::WriteOnly)
+ fdMode |= QT_OPEN_WRONLY | QT_OPEN_TRUNC;
+ if (mode & QIODevice::ReadOnly)
+ fdMode |= QT_OPEN_RDONLY;
+
+ fd_ = QT_OPEN(qPrintable(file.fileName()), fdMode);
+
+ return (-1 != fd_) && file.open(fd_, mode);
+ }
+
+ bool openStream(QFile &file, QIODevice::OpenMode mode)
+ {
+ char const *streamMode = "";
+
+ // File will be truncated if in Write mode.
+ if (mode & QIODevice::WriteOnly)
+ streamMode = "wb+";
+ else if (mode & QIODevice::ReadOnly)
+ streamMode = "rb";
+
+ stream_ = QT_FOPEN(qPrintable(file.fileName()), streamMode);
+
+ return stream_ && file.open(stream_, mode);
+ }
+
+ bool openFile(QFile &file, QIODevice::OpenMode mode, FileType type = OpenQFile)
+ {
+ if (mode & QIODevice::WriteOnly && !file.exists())
+ {
+ // Make sure the file exists
+ QFile createFile(file.fileName());
+ if (!createFile.open(QIODevice::ReadWrite))
+ return false;
+ }
+
+ // Note: openFd and openStream will truncate the file if write mode.
+ switch (type)
+ {
+ case OpenQFile:
+ return file.open(mode);
+
+ case OpenFd:
+ return openFd(file, mode);
+
+ case OpenStream:
+ return openStream(file, mode);
+ }
+
+ return false;
+ }
+
+ void closeFile(QFile &file)
+ {
+ file.close();
+
+ if (-1 != fd_)
+ QT_CLOSE(fd_);
+ if (stream_)
+ ::fclose(stream_);
+
+ fd_ = -1;
+ stream_ = 0;
+ }
+
+ int fd_;
+ FILE *stream_;
};
tst_QFile::tst_QFile()
@@ -226,6 +305,8 @@ void tst_QFile::init()
{
// TODO: Add initialization code here.
// This will be executed immediately before each test is run.
+ fd_ = -1;
+ stream_ = 0;
}
void tst_QFile::cleanup()
@@ -254,6 +335,11 @@ void tst_QFile::cleanup()
QFile::remove("existing-file.txt");
QFile::remove("file-renamed-once.txt");
QFile::remove("file-renamed-twice.txt");
+
+ if (-1 != fd_)
+ QT_CLOSE(fd_);
+ if (stream_)
+ ::fclose(stream_);
}
void tst_QFile::initTestCase()
@@ -1958,53 +2044,71 @@ void tst_QFile::fullDisk()
void tst_QFile::writeLargeDataBlock_data()
{
QTest::addColumn<QString>("fileName");
+ QTest::addColumn<int>("type");
+
+ QTest::newRow("localfile-QFile") << "./largeblockfile.txt" << (int)OpenQFile;
+ QTest::newRow("localfile-Fd") << "./largeblockfile.txt" << (int)OpenFd;
+ QTest::newRow("localfile-Stream") << "./largeblockfile.txt" << (int)OpenStream;
- QTest::newRow("localfile") << QString("./largeblockfile.txt");
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
// Some semi-randomness to avoid collisions.
QTest::newRow("unc file")
<< QString("//" + QtNetworkSettings::winServerName() + "/TESTSHAREWRITABLE/largefile-%1-%2.txt")
.arg(QHostInfo::localHostName())
- .arg(QTime::currentTime().msec());
+ .arg(QTime::currentTime().msec()) << (int)OpenQFile;
#endif
}
-void tst_QFile::writeLargeDataBlock()
+static QByteArray getLargeDataBlock()
{
- QFETCH(QString, fileName);
+ static QByteArray array;
- // Generate a 64MB array with well defined contents.
- QByteArray array;
+ if (array.isNull())
+ {
#if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
- int resizeSize = 1024 * 1024; // WinCE and Symbian do not have much space
+ int resizeSize = 1024 * 1024; // WinCE and Symbian do not have much space
#else
- int resizeSize = 64 * 1024 * 1024;
+ int resizeSize = 64 * 1024 * 1024;
#endif
- array.resize(resizeSize);
- for (int i = 0; i < array.size(); ++i)
- array[i] = uchar(i);
+ array.resize(resizeSize);
+ for (int i = 0; i < array.size(); ++i)
+ array[i] = uchar(i);
+ }
- // Remove and open the target file
- QFile file(fileName);
- file.remove();
- if (file.open(QFile::WriteOnly)) {
- QCOMPARE(file.write(array), qint64(array.size()));
- file.close();
- QVERIFY(file.open(QFile::ReadOnly));
- array.clear();
- array = file.readAll();
- file.remove();
- } else {
- QFAIL(qPrintable(QString("Couldn't open file for writing: [%1]").arg(fileName)));
- }
- // Check that we got the right content
- QCOMPARE(array.size(), resizeSize);
- for (int i = 0; i < array.size(); ++i) {
- if (array[i] != char(i)) {
- QFAIL(qPrintable(QString("Wrong contents! Char at %1 = %2, expected %3")
- .arg(i).arg(int(uchar(array[i]))).arg(int(uchar(i)))));
- }
+ return array;
+}
+
+void tst_QFile::writeLargeDataBlock()
+{
+ QFETCH(QString, fileName);
+ QFETCH( int, type );
+
+ QByteArray const originalData = getLargeDataBlock();
+
+ {
+ QFile file(fileName);
+
+ QVERIFY2( openFile(file, QIODevice::WriteOnly, (FileType)type),
+ qPrintable(QString("Couldn't open file for writing: [%1]").arg(fileName)) );
+ QCOMPARE( file.write(originalData), (qint64)originalData.size() );
+ QVERIFY( file.flush() );
+
+ closeFile(file);
+ }
+
+ QByteArray readData;
+
+ {
+ QFile file(fileName);
+
+ QVERIFY2( openFile(file, QIODevice::ReadOnly, (FileType)type),
+ qPrintable(QString("Couldn't open file for reading: [%1]").arg(fileName)) );
+ readData = file.readAll();
+ closeFile(file);
}
+
+ QCOMPARE( readData, originalData );
+ QVERIFY( QFile::remove(fileName) );
}
void tst_QFile::readFromWriteOnlyFile()
diff --git a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp
index ab7b0ac..5ead049 100644
--- a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp
+++ b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp
@@ -587,14 +587,16 @@ void tst_QLocalSocket::readBufferOverflow()
char buffer[dataBufferSize];
memset(buffer, 0, dataBufferSize);
serverSocket->write(buffer, dataBufferSize);
- serverSocket->flush();
+ serverSocket->waitForBytesWritten();
+ // wait until the first 128 bytes are ready to read
QVERIFY(client.waitForReadyRead());
QCOMPARE(client.read(buffer, readBufferSize), qint64(readBufferSize));
-#if defined(QT_LOCALSOCKET_TCP) || defined(Q_OS_SYMBIAN)
- QTest::qWait(250);
-#endif
+ // wait until the second 128 bytes are ready to read
+ QVERIFY(client.waitForReadyRead());
QCOMPARE(client.read(buffer, readBufferSize), qint64(readBufferSize));
+ // no more bytes available
+ QVERIFY(client.bytesAvailable() == 0);
}
// QLocalSocket/Server can take a name or path, check that it works as expected
diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
index 7adb67f..0b61dcd 100644
--- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
@@ -227,12 +227,6 @@ private Q_SLOTS:
void rateControl_data();
void rateControl();
- void downloadPerformance();
- void uploadPerformance();
- void performanceControlRate();
- void httpUploadPerformance();
- void httpDownloadPerformance_data();
- void httpDownloadPerformance();
void downloadProgress_data();
void downloadProgress();
@@ -413,93 +407,6 @@ public slots:
}
};
-class FixedSizeDataGenerator : public QIODevice
-{
- Q_OBJECT
- enum { Idle, Started, Stopped } state;
-public:
- FixedSizeDataGenerator(qint64 size) : state(Idle)
- { open(ReadOnly | Unbuffered);
- toBeGeneratedTotalCount = toBeGeneratedCount = size;
- }
-
- virtual qint64 bytesAvailable() const
- {
- return state == Started ? toBeGeneratedCount + QIODevice::bytesAvailable() : 0;
- }
-
- virtual bool isSequential() const{
- return false;
- }
-
- virtual bool reset() const{
- return false;
- }
-
- qint64 size() const {
- return toBeGeneratedTotalCount;
- }
-
-public slots:
- void start() { state = Started; emit readyRead(); }
-
-protected:
- virtual qint64 readData(char *data, qint64 maxlen)
- {
- memset(data, '@', maxlen);
-
- if (toBeGeneratedCount <= 0) {
- return -1;
- }
-
- qint64 n = qMin(maxlen, toBeGeneratedCount);
- toBeGeneratedCount -= n;
-
- if (toBeGeneratedCount <= 0) {
- // make sure this is a queued connection!
- emit readChannelFinished();
- }
-
- return n;
- }
- virtual qint64 writeData(const char *, qint64)
- { return -1; }
-
- qint64 toBeGeneratedCount;
- qint64 toBeGeneratedTotalCount;
-};
-
-
-class DataGenerator: public QIODevice
-{
- Q_OBJECT
- enum { Idle, Started, Stopped } state;
-public:
- DataGenerator() : state(Idle)
- { open(ReadOnly); }
-
- virtual bool isSequential() const { return true; }
- virtual qint64 bytesAvailable() const { return state == Started ? 1024*1024 : 0; }
-
-public slots:
- void start() { state = Started; emit readyRead(); }
- void stop() { state = Stopped; emit readyRead(); }
-
-protected:
- virtual qint64 readData(char *data, qint64 maxlen)
- {
- if (state == Stopped)
- return -1; // EOF
-
- // return as many bytes as are wanted
- memset(data, '@', maxlen);
- return maxlen;
- }
- virtual qint64 writeData(const char *, qint64)
- { return -1; }
-};
-
-
class SocketPair: public QObject
{
@@ -692,255 +599,6 @@ protected:
}
};
-class TimedSender: public QThread
-{
- Q_OBJECT
- qint64 totalBytes;
- QSemaphore ready;
- QByteArray dataToSend;
- QTcpSocket *client;
- int timeout;
- int port;
-public:
- int transferRate;
- TimedSender(int ms)
- : totalBytes(0), timeout(ms), port(-1), transferRate(-1)
- {
- dataToSend = QByteArray(16*1024, '@');
- start();
- ready.acquire();
- }
-
- inline int serverPort() const { return port; }
-
-private slots:
- void writeMore()
- {
- while (client->bytesToWrite() < 128 * 1024) {
- writePacket(dataToSend);
- }
- }
-
-protected:
- void run()
- {
- QTcpServer server;
- server.listen();
- port = server.serverPort();
- ready.release();
-
- server.waitForNewConnection(-1);
- client = server.nextPendingConnection();
-
- writeMore();
- connect(client, SIGNAL(bytesWritten(qint64)), SLOT(writeMore()), Qt::DirectConnection);
-
- QEventLoop eventLoop;
- QTimer::singleShot(timeout, &eventLoop, SLOT(quit()));
-
- QTime timer;
- timer.start();
- eventLoop.exec();
- disconnect(client, SIGNAL(bytesWritten(qint64)), this, 0);
-
- // wait for the connection to shut down
- client->disconnectFromHost();
- if (!client->waitForDisconnected(10000))
- return;
-
- transferRate = totalBytes * 1000 / timer.elapsed();
- qDebug() << "TimedSender::run" << "receive rate:" << (transferRate / 1024) << "kB/s in"
- << timer.elapsed() << "ms";
- }
-
- void writePacket(const QByteArray &array)
- {
- client->write(array);
- totalBytes += array.size();
- }
-};
-
-class ThreadedDataReader: public QThread
-{
- Q_OBJECT
- // used to make the constructor only return after the tcp server started listening
- QSemaphore ready;
- QTcpSocket *client;
- int timeout;
- int port;
-public:
- qint64 transferRate;
- ThreadedDataReader()
- : port(-1), transferRate(-1)
- {
- start();
- ready.acquire();
- }
-
- inline int serverPort() const { return port; }
-
-protected:
- void run()
- {
- QTcpServer server;
- server.listen();
- port = server.serverPort();
- ready.release();
-
- server.waitForNewConnection(-1);
- client = server.nextPendingConnection();
-
- QEventLoop eventLoop;
- DataReader reader(client, false);
- QObject::connect(client, SIGNAL(disconnected()), &eventLoop, SLOT(quit()));
-
- QTime timer;
- timer.start();
- eventLoop.exec();
- qint64 elapsed = timer.elapsed();
-
- transferRate = reader.totalBytes * 1000 / elapsed;
- qDebug() << "ThreadedDataReader::run" << "send rate:" << (transferRate / 1024) << "kB/s in" << elapsed << "msec";
- }
-};
-
-class ThreadedDataReaderHttpServer: public QThread
-{
- Q_OBJECT
- // used to make the constructor only return after the tcp server started listening
- QSemaphore ready;
- QTcpSocket *client;
- int timeout;
- int port;
-public:
- qint64 transferRate;
- ThreadedDataReaderHttpServer()
- : port(-1), transferRate(-1)
- {
- start();
- ready.acquire();
- }
-
- inline int serverPort() const { return port; }
-
-protected:
- void run()
- {
- QTcpServer server;
- server.listen();
- port = server.serverPort();
- ready.release();
-
- server.waitForNewConnection(-1);
- client = server.nextPendingConnection();
- client->write("HTTP/1.0 200 OK\r\n");
- client->write("Content-length: 0\r\n");
- client->write("\r\n");
- client->flush();
-
- QCoreApplication::processEvents();
-
- QEventLoop eventLoop;
- DataReader reader(client, false);
- QObject::connect(client, SIGNAL(disconnected()), &eventLoop, SLOT(quit()));
-
- QTime timer;
- timer.start();
- eventLoop.exec();
- qint64 elapsed = timer.elapsed();
-
- transferRate = reader.totalBytes * 1000 / elapsed;
- qDebug() << "ThreadedDataReaderHttpServer::run" << "send rate:" << (transferRate / 1024) << "kB/s in" << elapsed << "msec";
- }
-};
-
-class HttpDownloadPerformanceClient : QObject {
- Q_OBJECT;
- QIODevice *device;
- public:
- HttpDownloadPerformanceClient (QIODevice *dev) : device(dev){
- connect(dev, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
- }
-
- public slots:
- void readyReadSlot() {
- device->readAll();
- }
-
-};
-
-class HttpDownloadPerformanceServer : QObject {
- Q_OBJECT;
- qint64 dataSize;
- qint64 dataSent;
- QTcpServer server;
- QTcpSocket *client;
- bool serverSendsContentLength;
- bool chunkedEncoding;
-
-public:
- HttpDownloadPerformanceServer (qint64 ds, bool sscl, bool ce) : dataSize(ds), dataSent(0),
- client(0), serverSendsContentLength(sscl), chunkedEncoding(ce) {
- server.listen();
- connect(&server, SIGNAL(newConnection()), this, SLOT(newConnectionSlot()));
- }
-
- int serverPort() {
- return server.serverPort();
- }
-
-public slots:
-
- void newConnectionSlot() {
- client = server.nextPendingConnection();
- client->setParent(this);
- connect(client, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
- connect(client, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWrittenSlot(qint64)));
- }
-
- void readyReadSlot() {
- client->readAll();
- client->write("HTTP/1.0 200 OK\n");
- if (serverSendsContentLength)
- client->write(QString("Content-Length: " + QString::number(dataSize) + "\n").toAscii());
- if (chunkedEncoding)
- client->write(QString("Transfer-Encoding: chunked\n").toAscii());
- client->write("Connection: close\n\n");
- }
-
- void bytesWrittenSlot(qint64 amount) {
- Q_UNUSED(amount);
- if (dataSent == dataSize && client) {
- // close eventually
-
- // chunked encoding: we have to send a last "empty" chunk
- if (chunkedEncoding)
- client->write(QString("0\r\n\r\n").toAscii());
-
- client->disconnectFromHost();
- server.close();
- client = 0;
- return;
- }
-
- // send data
- if (client && client->bytesToWrite() < 100*1024 && dataSent < dataSize) {
- qint64 amount = qMin(qint64(16*1024), dataSize - dataSent);
- QByteArray data(amount, '@');
-
- if (chunkedEncoding) {
- client->write(QString(QString("%1").arg(amount,0,16).toUpper() + "\r\n").toAscii());
- client->write(data.constData(), amount);
- client->write(QString("\r\n").toAscii());
- } else {
- client->write(data.constData(), amount);
- }
-
- dataSent += amount;
- }
- }
-};
-
tst_QNetworkReply::tst_QNetworkReply()
{
@@ -3311,7 +2969,6 @@ void tst_QNetworkReply::ioPostToHttpEmtpyUploadProgress()
server.close();
}
-
void tst_QNetworkReply::rateControl_data()
{
QTest::addColumn<int>("rate");
@@ -3365,142 +3022,6 @@ void tst_QNetworkReply::rateControl()
QVERIFY(sender.transferRate <= maxRate);
}
-void tst_QNetworkReply::downloadPerformance()
-{
- // unlike the above function, this one tries to send as fast as possible
- // and measures how fast it was.
- TimedSender sender(5000);
- QNetworkRequest request("debugpipe://127.0.0.1:" + QString::number(sender.serverPort()) + "/?bare=1");
- QNetworkReplyPtr reply = manager.get(request);
- DataReader reader(reply, false);
-
- QTime loopTime;
- connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
- loopTime.start();
- QTestEventLoop::instance().enterLoop(40);
- int elapsedTime = loopTime.elapsed();
- sender.wait();
-
- qint64 receivedBytes = reader.totalBytes;
- qDebug() << "tst_QNetworkReply::downloadPerformance" << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and"
- << elapsedTime << "ms";
-}
-
-void tst_QNetworkReply::uploadPerformance()
-{
- ThreadedDataReader reader;
- DataGenerator generator;
-
-
- QNetworkRequest request("debugpipe://127.0.0.1:" + QString::number(reader.serverPort()) + "/?bare=1");
- QNetworkReplyPtr reply = manager.put(request, &generator);
- generator.start();
- connect(&reader, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
- QTimer::singleShot(5000, &generator, SLOT(stop()));
-
- QTestEventLoop::instance().enterLoop(30);
- QCOMPARE(reply->error(), QNetworkReply::NoError);
- QVERIFY(!QTestEventLoop::instance().timeout());
-}
-
-void tst_QNetworkReply::httpUploadPerformance()
-{
-#ifdef Q_OS_SYMBIAN
- // SHow some mercy for non-desktop platform/s
- enum {UploadSize = 4*1024*1024}; // 4 MB
-#else
- enum {UploadSize = 128*1024*1024}; // 128 MB
-#endif
- ThreadedDataReaderHttpServer reader;
- FixedSizeDataGenerator generator(UploadSize);
-
- QNetworkRequest request(QUrl("http://127.0.0.1:" + QString::number(reader.serverPort()) + "/?bare=1"));
- request.setHeader(QNetworkRequest::ContentLengthHeader,UploadSize);
-
- QNetworkReplyPtr reply = manager.put(request, &generator);
-
- connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
-
- QTime time;
- generator.start();
- time.start();
- QTestEventLoop::instance().enterLoop(40);
- QCOMPARE(reply->error(), QNetworkReply::NoError);
- QVERIFY(!QTestEventLoop::instance().timeout());
-
- qint64 elapsed = time.elapsed();
- qDebug() << "tst_QNetworkReply::httpUploadPerformance" << elapsed << "msec, "
- << ((UploadSize/1024.0)/(elapsed/1000.0)) << " kB/sec";
-
- reader.exit();
- reader.wait();
-}
-
-
-void tst_QNetworkReply::performanceControlRate()
-{
- // this is a control comparison for the other two above
- // it does the same thing, but instead bypasses the QNetworkAccess system
- qDebug() << "The following are the maximum transfer rates that we can get in this system"
- " (bypassing QNetworkAccess)";
-
- TimedSender sender(5000);
- QTcpSocket sink;
- sink.connectToHost("127.0.0.1", sender.serverPort());
- DataReader reader(&sink, false);
-
- QTime loopTime;
- connect(&sink, SIGNAL(disconnected()), &QTestEventLoop::instance(), SLOT(exitLoop()));
- loopTime.start();
- QTestEventLoop::instance().enterLoop(40);
- int elapsedTime = loopTime.elapsed();
- sender.wait();
-
- qint64 receivedBytes = reader.totalBytes;
- qDebug() << "tst_QNetworkReply::performanceControlRate" << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and"
- << elapsedTime << "ms";
-}
-
-void tst_QNetworkReply::httpDownloadPerformance_data()
-{
- QTest::addColumn<bool>("serverSendsContentLength");
- QTest::addColumn<bool>("chunkedEncoding");
-
- QTest::newRow("Server sends no Content-Length") << false << false;
- QTest::newRow("Server sends Content-Length") << true << false;
- QTest::newRow("Server uses chunked encoding") << false << true;
-
-}
-
-void tst_QNetworkReply::httpDownloadPerformance()
-{
- QFETCH(bool, serverSendsContentLength);
- QFETCH(bool, chunkedEncoding);
-#ifdef Q_OS_SYMBIAN
- // Show some mercy to non-desktop platform/s
- enum {UploadSize = 4*1024*1024}; // 4 MB
-#else
- enum {UploadSize = 128*1024*1024}; // 128 MB
-#endif
- HttpDownloadPerformanceServer server(UploadSize, serverSendsContentLength, chunkedEncoding);
-
- QNetworkRequest request(QUrl("http://127.0.0.1:" + QString::number(server.serverPort()) + "/?bare=1"));
- QNetworkReplyPtr reply = manager.get(request);
-
- connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection);
- HttpDownloadPerformanceClient client(reply);
-
- QTime time;
- time.start();
- QTestEventLoop::instance().enterLoop(40);
- QCOMPARE(reply->error(), QNetworkReply::NoError);
- QVERIFY(!QTestEventLoop::instance().timeout());
-
- qint64 elapsed = time.elapsed();
- qDebug() << "tst_QNetworkReply::httpDownloadPerformance" << elapsed << "msec, "
- << ((UploadSize/1024.0)/(elapsed/1000.0)) << " kB/sec";
-}
-
void tst_QNetworkReply::downloadProgress_data()
{
QTest::addColumn<int>("loopCount");
diff --git a/tests/benchmarks/qnetworkreply/tst_qnetworkreply.cpp b/tests/benchmarks/qnetworkreply/tst_qnetworkreply.cpp
index 993db52..1d50013 100644
--- a/tests/benchmarks/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/benchmarks/qnetworkreply/tst_qnetworkreply.cpp
@@ -46,11 +46,397 @@
#include <QtNetwork/qnetworkreply.h>
#include <QtNetwork/qnetworkrequest.h>
#include <QtNetwork/qnetworkaccessmanager.h>
+#include <QtNetwork/qtcpsocket.h>
+#include <QtNetwork/qtcpserver.h>
#include "../../auto/network-settings.h"
+
+class TimedSender: public QThread
+{
+ Q_OBJECT
+ qint64 totalBytes;
+ QSemaphore ready;
+ QByteArray dataToSend;
+ QTcpSocket *client;
+ int timeout;
+ int port;
+public:
+ int transferRate;
+ TimedSender(int ms)
+ : totalBytes(0), timeout(ms), port(-1), transferRate(-1)
+ {
+ dataToSend = QByteArray(16*1024, '@');
+ start();
+ ready.acquire();
+ }
+
+ inline int serverPort() const { return port; }
+
+private slots:
+ void writeMore()
+ {
+ while (client->bytesToWrite() < 128 * 1024) {
+ writePacket(dataToSend);
+ }
+ }
+
+protected:
+ void run()
+ {
+ QTcpServer server;
+ server.listen();
+ port = server.serverPort();
+ ready.release();
+
+ server.waitForNewConnection(-1);
+ client = server.nextPendingConnection();
+
+ writeMore();
+ connect(client, SIGNAL(bytesWritten(qint64)), SLOT(writeMore()), Qt::DirectConnection);
+
+ QEventLoop eventLoop;
+ QTimer::singleShot(timeout, &eventLoop, SLOT(quit()));
+
+ QTime timer;
+ timer.start();
+ eventLoop.exec();
+ disconnect(client, SIGNAL(bytesWritten(qint64)), this, 0);
+
+ // wait for the connection to shut down
+ client->disconnectFromHost();
+ if (!client->waitForDisconnected(10000))
+ return;
+
+ transferRate = totalBytes * 1000 / timer.elapsed();
+ qDebug() << "TimedSender::run" << "receive rate:" << (transferRate / 1024) << "kB/s in"
+ << timer.elapsed() << "ms";
+ }
+
+ void writePacket(const QByteArray &array)
+ {
+ client->write(array);
+ totalBytes += array.size();
+ }
+};
+
+
+class QNetworkReplyPtr: public QSharedPointer<QNetworkReply>
+{
+public:
+ inline QNetworkReplyPtr(QNetworkReply *ptr = 0)
+ : QSharedPointer<QNetworkReply>(ptr)
+ { }
+
+ inline operator QNetworkReply *() const { return data(); }
+};
+
+
+class DataReader: public QObject
+{
+ Q_OBJECT
+public:
+ qint64 totalBytes;
+ QByteArray data;
+ QIODevice *device;
+ bool accumulate;
+ DataReader(QIODevice *dev, bool acc = true) : totalBytes(0), device(dev), accumulate(acc)
+ {
+ connect(device, SIGNAL(readyRead()), SLOT(doRead()));
+ }
+
+public slots:
+ void doRead()
+ {
+ QByteArray buffer;
+ buffer.resize(device->bytesAvailable());
+ qint64 bytesRead = device->read(buffer.data(), device->bytesAvailable());
+ if (bytesRead == -1) {
+ QTestEventLoop::instance().exitLoop();
+ return;
+ }
+ buffer.truncate(bytesRead);
+ totalBytes += bytesRead;
+
+ if (accumulate)
+ data += buffer;
+ }
+};
+
+class ThreadedDataReader: public QThread
+{
+ Q_OBJECT
+ // used to make the constructor only return after the tcp server started listening
+ QSemaphore ready;
+ QTcpSocket *client;
+ int timeout;
+ int port;
+public:
+ qint64 transferRate;
+ ThreadedDataReader()
+ : port(-1), transferRate(-1)
+ {
+ start();
+ ready.acquire();
+ }
+
+ inline int serverPort() const { return port; }
+
+protected:
+ void run()
+ {
+ QTcpServer server;
+ server.listen();
+ port = server.serverPort();
+ ready.release();
+
+ server.waitForNewConnection(-1);
+ client = server.nextPendingConnection();
+
+ QEventLoop eventLoop;
+ DataReader reader(client, false);
+ QObject::connect(client, SIGNAL(disconnected()), &eventLoop, SLOT(quit()));
+
+ QTime timer;
+ timer.start();
+ eventLoop.exec();
+ qint64 elapsed = timer.elapsed();
+
+ transferRate = reader.totalBytes * 1000 / elapsed;
+ qDebug() << "ThreadedDataReader::run" << "send rate:" << (transferRate / 1024) << "kB/s in" << elapsed << "msec";
+ }
+};
+
+class DataGenerator: public QIODevice
+{
+ Q_OBJECT
+ enum { Idle, Started, Stopped } state;
+public:
+ DataGenerator() : state(Idle)
+ { open(ReadOnly); }
+
+ virtual bool isSequential() const { return true; }
+ virtual qint64 bytesAvailable() const { return state == Started ? 1024*1024 : 0; }
+
+public slots:
+ void start() { state = Started; emit readyRead(); }
+ void stop() { state = Stopped; emit readyRead(); }
+
+protected:
+ virtual qint64 readData(char *data, qint64 maxlen)
+ {
+ if (state == Stopped)
+ return -1; // EOF
+
+ // return as many bytes as are wanted
+ memset(data, '@', maxlen);
+ return maxlen;
+ }
+ virtual qint64 writeData(const char *, qint64)
+ { return -1; }
+};
+
+class ThreadedDataReaderHttpServer: public QThread
+{
+ Q_OBJECT
+ // used to make the constructor only return after the tcp server started listening
+ QSemaphore ready;
+ QTcpSocket *client;
+ int timeout;
+ int port;
+public:
+ qint64 transferRate;
+ ThreadedDataReaderHttpServer()
+ : port(-1), transferRate(-1)
+ {
+ start();
+ ready.acquire();
+ }
+
+ inline int serverPort() const { return port; }
+
+protected:
+ void run()
+ {
+ QTcpServer server;
+ server.listen();
+ port = server.serverPort();
+ ready.release();
+
+ server.waitForNewConnection(-1);
+ client = server.nextPendingConnection();
+ client->write("HTTP/1.0 200 OK\r\n");
+ client->write("Content-length: 0\r\n");
+ client->write("\r\n");
+ client->flush();
+
+ QCoreApplication::processEvents();
+
+ QEventLoop eventLoop;
+ DataReader reader(client, false);
+ QObject::connect(client, SIGNAL(disconnected()), &eventLoop, SLOT(quit()));
+
+ QTime timer;
+ timer.start();
+ eventLoop.exec();
+ qint64 elapsed = timer.elapsed();
+
+ transferRate = reader.totalBytes * 1000 / elapsed;
+ qDebug() << "ThreadedDataReaderHttpServer::run" << "send rate:" << (transferRate / 1024) << "kB/s in" << elapsed << "msec";
+ }
+};
+
+
+class FixedSizeDataGenerator : public QIODevice
+{
+ Q_OBJECT
+ enum { Idle, Started, Stopped } state;
+public:
+ FixedSizeDataGenerator(qint64 size) : state(Idle)
+ { open(ReadOnly | Unbuffered);
+ toBeGeneratedTotalCount = toBeGeneratedCount = size;
+ }
+
+ virtual qint64 bytesAvailable() const
+ {
+ return state == Started ? toBeGeneratedCount + QIODevice::bytesAvailable() : 0;
+ }
+
+ virtual bool isSequential() const{
+ return false;
+ }
+
+ virtual bool reset() const{
+ return false;
+ }
+
+ qint64 size() const {
+ return toBeGeneratedTotalCount;
+ }
+
+public slots:
+ void start() { state = Started; emit readyRead(); }
+
+protected:
+ virtual qint64 readData(char *data, qint64 maxlen)
+ {
+ memset(data, '@', maxlen);
+
+ if (toBeGeneratedCount <= 0) {
+ return -1;
+ }
+
+ qint64 n = qMin(maxlen, toBeGeneratedCount);
+ toBeGeneratedCount -= n;
+
+ if (toBeGeneratedCount <= 0) {
+ // make sure this is a queued connection!
+ emit readChannelFinished();
+ }
+
+ return n;
+ }
+ virtual qint64 writeData(const char *, qint64)
+ { return -1; }
+
+ qint64 toBeGeneratedCount;
+ qint64 toBeGeneratedTotalCount;
+};
+
+class HttpDownloadPerformanceServer : QObject {
+ Q_OBJECT;
+ qint64 dataSize;
+ qint64 dataSent;
+ QTcpServer server;
+ QTcpSocket *client;
+ bool serverSendsContentLength;
+ bool chunkedEncoding;
+
+public:
+ HttpDownloadPerformanceServer (qint64 ds, bool sscl, bool ce) : dataSize(ds), dataSent(0),
+ client(0), serverSendsContentLength(sscl), chunkedEncoding(ce) {
+ server.listen();
+ connect(&server, SIGNAL(newConnection()), this, SLOT(newConnectionSlot()));
+ }
+
+ int serverPort() {
+ return server.serverPort();
+ }
+
+public slots:
+
+ void newConnectionSlot() {
+ client = server.nextPendingConnection();
+ client->setParent(this);
+ connect(client, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
+ connect(client, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWrittenSlot(qint64)));
+ }
+
+ void readyReadSlot() {
+ client->readAll();
+ client->write("HTTP/1.0 200 OK\n");
+ if (serverSendsContentLength)
+ client->write(QString("Content-Length: " + QString::number(dataSize) + "\n").toAscii());
+ if (chunkedEncoding)
+ client->write(QString("Transfer-Encoding: chunked\n").toAscii());
+ client->write("Connection: close\n\n");
+ }
+
+ void bytesWrittenSlot(qint64 amount) {
+ Q_UNUSED(amount);
+ if (dataSent == dataSize && client) {
+ // close eventually
+
+ // chunked encoding: we have to send a last "empty" chunk
+ if (chunkedEncoding)
+ client->write(QString("0\r\n\r\n").toAscii());
+
+ client->disconnectFromHost();
+ server.close();
+ client = 0;
+ return;
+ }
+
+ // send data
+ if (client && client->bytesToWrite() < 100*1024 && dataSent < dataSize) {
+ qint64 amount = qMin(qint64(16*1024), dataSize - dataSent);
+ QByteArray data(amount, '@');
+
+ if (chunkedEncoding) {
+ client->write(QString(QString("%1").arg(amount,0,16).toUpper() + "\r\n").toAscii());
+ client->write(data.constData(), amount);
+ client->write(QString("\r\n").toAscii());
+ } else {
+ client->write(data.constData(), amount);
+ }
+
+ dataSent += amount;
+ }
+ }
+};
+
+class HttpDownloadPerformanceClient : QObject {
+ Q_OBJECT;
+ QIODevice *device;
+ public:
+ HttpDownloadPerformanceClient (QIODevice *dev) : device(dev){
+ connect(dev, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
+ }
+
+ public slots:
+ void readyReadSlot() {
+ device->readAll();
+ }
+
+};
+
+
+
+
class tst_qnetworkreply : public QObject
{
Q_OBJECT
+
+ QNetworkAccessManager manager;
private slots:
void httpLatency();
@@ -58,6 +444,14 @@ private slots:
void echoPerformance_data();
void echoPerformance();
#endif
+
+ void downloadPerformance();
+ void uploadPerformance();
+ void performanceControlRate();
+ void httpUploadPerformance();
+ void httpDownloadPerformance_data();
+ void httpDownloadPerformance();
+
};
void tst_qnetworkreply::httpLatency()
@@ -107,6 +501,142 @@ void tst_qnetworkreply::echoPerformance()
}
#endif
+void tst_qnetworkreply::downloadPerformance()
+{
+ // unlike the above function, this one tries to send as fast as possible
+ // and measures how fast it was.
+ TimedSender sender(5000);
+ QNetworkRequest request("debugpipe://127.0.0.1:" + QString::number(sender.serverPort()) + "/?bare=1");
+ QNetworkReplyPtr reply = manager.get(request);
+ DataReader reader(reply, false);
+
+ QTime loopTime;
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ loopTime.start();
+ QTestEventLoop::instance().enterLoop(40);
+ int elapsedTime = loopTime.elapsed();
+ sender.wait();
+
+ qint64 receivedBytes = reader.totalBytes;
+ qDebug() << "tst_QNetworkReply::downloadPerformance" << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and"
+ << elapsedTime << "ms";
+}
+
+void tst_qnetworkreply::uploadPerformance()
+{
+ ThreadedDataReader reader;
+ DataGenerator generator;
+
+
+ QNetworkRequest request("debugpipe://127.0.0.1:" + QString::number(reader.serverPort()) + "/?bare=1");
+ QNetworkReplyPtr reply = manager.put(request, &generator);
+ generator.start();
+ connect(&reader, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTimer::singleShot(5000, &generator, SLOT(stop()));
+
+ QTestEventLoop::instance().enterLoop(30);
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+}
+
+void tst_qnetworkreply::httpUploadPerformance()
+{
+#ifdef Q_OS_SYMBIAN
+ // SHow some mercy for non-desktop platform/s
+ enum {UploadSize = 4*1024*1024}; // 4 MB
+#else
+ enum {UploadSize = 128*1024*1024}; // 128 MB
+#endif
+ ThreadedDataReaderHttpServer reader;
+ FixedSizeDataGenerator generator(UploadSize);
+
+ QNetworkRequest request(QUrl("http://127.0.0.1:" + QString::number(reader.serverPort()) + "/?bare=1"));
+ request.setHeader(QNetworkRequest::ContentLengthHeader,UploadSize);
+
+ QNetworkReplyPtr reply = manager.put(request, &generator);
+
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QTime time;
+ generator.start();
+ time.start();
+ QTestEventLoop::instance().enterLoop(40);
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ qint64 elapsed = time.elapsed();
+ qDebug() << "tst_QNetworkReply::httpUploadPerformance" << elapsed << "msec, "
+ << ((UploadSize/1024.0)/(elapsed/1000.0)) << " kB/sec";
+
+ reader.exit();
+ reader.wait();
+}
+
+
+void tst_qnetworkreply::performanceControlRate()
+{
+ // this is a control comparison for the other two above
+ // it does the same thing, but instead bypasses the QNetworkAccess system
+ qDebug() << "The following are the maximum transfer rates that we can get in this system"
+ " (bypassing QNetworkAccess)";
+
+ TimedSender sender(5000);
+ QTcpSocket sink;
+ sink.connectToHost("127.0.0.1", sender.serverPort());
+ DataReader reader(&sink, false);
+
+ QTime loopTime;
+ connect(&sink, SIGNAL(disconnected()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ loopTime.start();
+ QTestEventLoop::instance().enterLoop(40);
+ int elapsedTime = loopTime.elapsed();
+ sender.wait();
+
+ qint64 receivedBytes = reader.totalBytes;
+ qDebug() << "tst_QNetworkReply::performanceControlRate" << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and"
+ << elapsedTime << "ms";
+}
+
+void tst_qnetworkreply::httpDownloadPerformance_data()
+{
+ QTest::addColumn<bool>("serverSendsContentLength");
+ QTest::addColumn<bool>("chunkedEncoding");
+
+ QTest::newRow("Server sends no Content-Length") << false << false;
+ QTest::newRow("Server sends Content-Length") << true << false;
+ QTest::newRow("Server uses chunked encoding") << false << true;
+
+}
+
+void tst_qnetworkreply::httpDownloadPerformance()
+{
+ QFETCH(bool, serverSendsContentLength);
+ QFETCH(bool, chunkedEncoding);
+#ifdef Q_OS_SYMBIAN
+ // Show some mercy to non-desktop platform/s
+ enum {UploadSize = 4*1024*1024}; // 4 MB
+#else
+ enum {UploadSize = 128*1024*1024}; // 128 MB
+#endif
+ HttpDownloadPerformanceServer server(UploadSize, serverSendsContentLength, chunkedEncoding);
+
+ QNetworkRequest request(QUrl("http://127.0.0.1:" + QString::number(server.serverPort()) + "/?bare=1"));
+ QNetworkReplyPtr reply = manager.get(request);
+
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection);
+ HttpDownloadPerformanceClient client(reply);
+
+ QTime time;
+ time.start();
+ QTestEventLoop::instance().enterLoop(40);
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ qint64 elapsed = time.elapsed();
+ qDebug() << "tst_QNetworkReply::httpDownloadPerformance" << elapsed << "msec, "
+ << ((UploadSize/1024.0)/(elapsed/1000.0)) << " kB/sec";
+}
+
QTEST_MAIN(tst_qnetworkreply)
#include "tst_qnetworkreply.moc"
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
index d8c2abd..06c1d9c 100644
--- a/tools/configure/configureapp.cpp
+++ b/tools/configure/configureapp.cpp
@@ -3391,10 +3391,7 @@ void Configure::buildHostTools()
QString pwd = QDir::currentPath();
QStringList hostToolsDirs;
hostToolsDirs
- << "src/tools/bootstrap"
- << "src/tools/moc"
- << "src/tools/rcc"
- << "src/tools/uic";
+ << "src/tools";
if(dictionary["XQMAKESPEC"].startsWith("wince"))
hostToolsDirs << "tools/checksdk";