diff options
Diffstat (limited to 'tests/auto/shared/testhttpserver.cpp')
-rw-r--r-- | tests/auto/shared/testhttpserver.cpp | 243 |
1 files changed, 157 insertions, 86 deletions
diff --git a/tests/auto/shared/testhttpserver.cpp b/tests/auto/shared/testhttpserver.cpp index 7235246fc0..80ce10cacd 100644 --- a/tests/auto/shared/testhttpserver.cpp +++ b/tests/auto/shared/testhttpserver.cpp @@ -36,6 +36,7 @@ #include <QDebug> #include <QFile> #include <QTimer> +#include <QTest> /*! \internal @@ -80,25 +81,35 @@ The following request urls will then result in the appropriate action: \row \li http://localhost:14445/slowMain.qml \li slowMain.qml returned after 500ms \endtable */ -TestHTTPServer::TestHTTPServer() -: m_state(AwaitingHeader) + +static QUrl localHostUrl(quint16 port) { - QObject::connect(&server, SIGNAL(newConnection()), this, SLOT(newConnection())); + QUrl url; + url.setScheme(QStringLiteral("http")); + url.setHost(QStringLiteral("127.0.0.1")); + url.setPort(port); + return url; +} +TestHTTPServer::TestHTTPServer() + : m_state(AwaitingHeader) +{ + QObject::connect(&m_server, &QTcpServer::newConnection, this, &TestHTTPServer::newConnection); } bool TestHTTPServer::listen() { - return server.listen(QHostAddress::LocalHost, 0); + return m_server.listen(QHostAddress::LocalHost, 0); } QUrl TestHTTPServer::baseUrl() const { - QUrl url; - url.setScheme(QStringLiteral("http")); - url.setHost(QStringLiteral("127.0.0.1")); - url.setPort(server.serverPort()); - return url; + return localHostUrl(m_server.serverPort()); +} + +quint16 TestHTTPServer::port() const +{ + return m_server.serverPort(); } QUrl TestHTTPServer::url(const QString &documentPath) const @@ -113,12 +124,12 @@ QString TestHTTPServer::urlString(const QString &documentPath) const QString TestHTTPServer::errorString() const { - return server.errorString(); + return m_server.errorString(); } bool TestHTTPServer::serveDirectory(const QString &dir, Mode mode) { - dirs.append(qMakePair(dir, mode)); + m_directories.append(qMakePair(dir, mode)); return true; } @@ -128,17 +139,17 @@ bool TestHTTPServer::serveDirectory(const QString &dir, Mode mode) */ void TestHTTPServer::addAlias(const QString &filename, const QString &alias) { - aliases.insert(filename, alias); + m_aliases.insert(filename, alias); } void TestHTTPServer::addRedirect(const QString &filename, const QString &redirectName) { - redirects.insert(filename, redirectName); + m_redirects.insert(filename, redirectName); } void TestHTTPServer::registerFileNameForContentSubstitution(const QString &fileName) { - contentSubstitutedFileNames.insert(fileName); + m_contentSubstitutedFileNames.insert(fileName); } bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &body) @@ -147,19 +158,23 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod m_data.clear(); QFile expectFile(expect.toLocalFile()); - if (!expectFile.open(QIODevice::ReadOnly)) return false; + if (!expectFile.open(QIODevice::ReadOnly)) + return false; QFile replyFile(reply.toLocalFile()); - if (!replyFile.open(QIODevice::ReadOnly)) return false; + if (!replyFile.open(QIODevice::ReadOnly)) + return false; - bodyData = QByteArray(); + m_bodyData = QByteArray(); if (body.isValid()) { QFile bodyFile(body.toLocalFile()); - if (!bodyFile.open(QIODevice::ReadOnly)) return false; - bodyData = bodyFile.readAll(); + if (!bodyFile.open(QIODevice::ReadOnly)) + return false; + m_bodyData = bodyFile.readAll(); } - const QByteArray serverHostUrl = QByteArrayLiteral("127.0.0.1:") + QByteArray::number(server.serverPort()); + const QByteArray serverHostUrl + = QByteArrayLiteral("127.0.0.1:")+ QByteArray::number(m_server.serverPort()); QByteArray line; bool headers_done = false; @@ -170,10 +185,10 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod continue; } if (headers_done) { - waitData.body.append(line); + m_waitData.body.append(line); } else { line.replace("{{ServerHostUrl}}", serverHostUrl); - waitData.headers.append(line); + m_waitData.headers.append(line); } } /* @@ -181,20 +196,21 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod waitData = waitData.left(waitData.count() - 1); */ - replyData = replyFile.readAll(); + m_replyData = replyFile.readAll(); - if (!replyData.endsWith('\n')) - replyData.append("\n"); - replyData.append("Content-length: " + QByteArray::number(bodyData.length())); - replyData .append("\n\n"); + if (!m_replyData.endsWith('\n')) + m_replyData.append('\n'); + m_replyData.append("Content-length: "); + m_replyData.append(QByteArray::number(m_bodyData.length())); + m_replyData.append("\n\n"); - for (int ii = 0; ii < replyData.count(); ++ii) { - if (replyData.at(ii) == '\n' && (!ii || replyData.at(ii - 1) != '\r')) { - replyData.insert(ii, '\r'); + for (int ii = 0; ii < m_replyData.count(); ++ii) { + if (m_replyData.at(ii) == '\n' && (!ii || m_replyData.at(ii - 1) != '\r')) { + m_replyData.insert(ii, '\r'); ++ii; } } - replyData.append(bodyData); + m_replyData.append(m_bodyData); return true; } @@ -206,25 +222,27 @@ bool TestHTTPServer::hasFailed() const void TestHTTPServer::newConnection() { - QTcpSocket *socket = server.nextPendingConnection(); - if (!socket) return; + QTcpSocket *socket = m_server.nextPendingConnection(); + if (!socket) + return; - if (!dirs.isEmpty()) - dataCache.insert(socket, QByteArray()); + if (!m_directories.isEmpty()) + m_dataCache.insert(socket, QByteArray()); - QObject::connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected())); - QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead())); + QObject::connect(socket, &QAbstractSocket::disconnected, this, &TestHTTPServer::disconnected); + QObject::connect(socket, &QIODevice::readyRead, this, &TestHTTPServer::readyRead); } void TestHTTPServer::disconnected() { QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); - if (!socket) return; + if (!socket) + return; - dataCache.remove(socket); - for (int ii = 0; ii < toSend.count(); ++ii) { - if (toSend.at(ii).first == socket) { - toSend.removeAt(ii); + m_dataCache.remove(socket); + for (int ii = 0; ii < m_toSend.count(); ++ii) { + if (m_toSend.at(ii).first == socket) { + m_toSend.removeAt(ii); --ii; } } @@ -235,14 +253,15 @@ void TestHTTPServer::disconnected() void TestHTTPServer::readyRead() { QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); - if (!socket || socket->state() == QTcpSocket::ClosingState) return; + if (!socket || socket->state() == QTcpSocket::ClosingState) + return; - if (!dirs.isEmpty()) { + if (!m_directories.isEmpty()) { serveGET(socket, socket->readAll()); return; } - if (m_state == Failed || (waitData.body.isEmpty() && waitData.headers.count() == 0)) { + if (m_state == Failed || (m_waitData.body.isEmpty() && m_waitData.headers.count() == 0)) { qWarning() << "TestHTTPServer: Unexpected data" << socket->readAll(); return; } @@ -256,8 +275,9 @@ void TestHTTPServer::readyRead() m_data += socket->readAll(); break; } else { - if (!waitData.headers.contains(line)) { - qWarning() << "TestHTTPServer: Unexpected header:" << line << "\nExpected headers: " << waitData.headers; + if (!m_waitData.headers.contains(line)) { + qWarning() << "TestHTTPServer: Unexpected header:" << line + << "\nExpected headers: " << m_waitData.headers; m_state = Failed; socket->disconnectFromHost(); return; @@ -268,34 +288,38 @@ void TestHTTPServer::readyRead() m_data += socket->readAll(); } - if (!m_data.isEmpty() || waitData.body.isEmpty()) { - if (waitData.body != m_data) { - qWarning() << "TestHTTPServer: Unexpected data" << m_data << "\nExpected: " << waitData.body; + if (!m_data.isEmpty() || m_waitData.body.isEmpty()) { + if (m_waitData.body != m_data) { + qWarning() << "TestHTTPServer: Unexpected data" << m_data << "\nExpected: " << m_waitData.body; m_state = Failed; } else { - socket->write(replyData); + socket->write(m_replyData); } socket->disconnectFromHost(); } } -bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileName) +bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileNameIn) { - if (redirects.contains(fileName)) { - QByteArray response = "HTTP/1.1 302 Found\r\nContent-length: 0\r\nContent-type: text/html; charset=UTF-8\r\nLocation: " + redirects[fileName].toUtf8() + "\r\n\r\n"; + const QString fileName = QLatin1String(fileNameIn); + if (m_redirects.contains(fileName)) { + const QByteArray response + = "HTTP/1.1 302 Found\r\nContent-length: 0\r\nContent-type: text/html; charset=UTF-8\r\nLocation: " + + m_redirects.value(fileName).toUtf8() + "\r\n\r\n"; socket->write(response); return true; } - for (int ii = 0; ii < dirs.count(); ++ii) { - QString dir = dirs.at(ii).first; - Mode mode = dirs.at(ii).second; + for (int ii = 0; ii < m_directories.count(); ++ii) { + const QString &dir = m_directories.at(ii).first; + const Mode mode = m_directories.at(ii).second; - QString dirFile = dir + QLatin1String("/") + QLatin1String(fileName); + QString dirFile = dir + QLatin1Char('/') + fileName; if (!QFile::exists(dirFile)) { - if (aliases.contains(fileName)) - dirFile = dir + QLatin1String("/") + aliases.value(fileName); + const QHash<QString, QString>::const_iterator it = m_aliases.constFind(fileName); + if (it != m_aliases.constEnd()) + dirFile = dir + QLatin1Char('/') + it.value(); } QFile file(dirFile); @@ -305,18 +329,18 @@ bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileName) return true; QByteArray data = file.readAll(); - if (contentSubstitutedFileNames.contains("/" + fileName)) { + if (m_contentSubstitutedFileNames.contains(QLatin1Char('/') + fileName)) data.replace(QByteArrayLiteral("{{ServerBaseUrl}}"), baseUrl().toString().toUtf8()); - } - QByteArray response = "HTTP/1.0 200 OK\r\nContent-type: text/html; charset=UTF-8\r\nContent-length: "; + QByteArray response + = "HTTP/1.0 200 OK\r\nContent-type: text/html; charset=UTF-8\r\nContent-length: "; response += QByteArray::number(data.count()); response += "\r\n\r\n"; response += data; if (mode == Delay) { - toSend.append(qMakePair(socket, response)); - QTimer::singleShot(500, this, SLOT(sendOne())); + m_toSend.append(qMakePair(socket, response)); + QTimer::singleShot(500, this, &TestHTTPServer::sendOne); return false; } else { socket->write(response); @@ -325,9 +349,7 @@ bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileName) } } - - QByteArray response = "HTTP/1.0 404 Not found\r\nContent-type: text/html; charset=UTF-8\r\n\r\n"; - socket->write(response); + socket->write("HTTP/1.0 404 Not found\r\nContent-type: text/html; charset=UTF-8\r\n\r\n"); return true; } @@ -339,39 +361,88 @@ void TestHTTPServer::sendDelayedItem() void TestHTTPServer::sendOne() { - if (!toSend.isEmpty()) { - toSend.first().first->write(toSend.first().second); - toSend.first().first->close(); - toSend.removeFirst(); + if (!m_toSend.isEmpty()) { + m_toSend.first().first->write(m_toSend.first().second); + m_toSend.first().first->close(); + m_toSend.removeFirst(); } } void TestHTTPServer::serveGET(QTcpSocket *socket, const QByteArray &data) { - if (!dataCache.contains(socket)) + const QHash<QTcpSocket *, QByteArray>::iterator it = m_dataCache.find(socket); + if (it == m_dataCache.end()) return; - QByteArray total = dataCache[socket] + data; - dataCache[socket] = total; + QByteArray &total = it.value(); + total.append(data); if (total.contains("\n\r\n")) { - bool close = true; - if (total.startsWith("GET /")) { + const int space = total.indexOf(' ', 4); + if (space != -1) + close = reply(socket, total.mid(5, space - 5)); + } + m_dataCache.erase(it); + if (close) + socket->disconnectFromHost(); + } +} - int space = total.indexOf(' ', 4); - if (space != -1) { +ThreadedTestHTTPServer::ThreadedTestHTTPServer(const QString &dir, TestHTTPServer::Mode mode) : + m_port(0) +{ + m_dirs[dir] = mode; + start(); +} - QByteArray req = total.mid(5, space - 5); - close = reply(socket, req); +ThreadedTestHTTPServer::ThreadedTestHTTPServer(const QHash<QString, TestHTTPServer::Mode> &dirs) : + m_dirs(dirs), m_port(0) +{ + start(); +} - } - } - dataCache.remove(socket); +ThreadedTestHTTPServer::~ThreadedTestHTTPServer() +{ + quit(); + wait(); +} - if (close) - socket->disconnectFromHost(); +QUrl ThreadedTestHTTPServer::baseUrl() const +{ + return localHostUrl(m_port); +} + +QUrl ThreadedTestHTTPServer::url(const QString &documentPath) const +{ + return baseUrl().resolved(documentPath); +} + +QString ThreadedTestHTTPServer::urlString(const QString &documentPath) const +{ + return url(documentPath).toString(); +} + +void ThreadedTestHTTPServer::run() +{ + TestHTTPServer server; + { + QMutexLocker locker(&m_mutex); + QVERIFY2(server.listen(), qPrintable(server.errorString())); + m_port = server.port(); + for (QHash<QString, TestHTTPServer::Mode>::ConstIterator i = m_dirs.constBegin(); + i != m_dirs.constEnd(); ++i) { + server.serveDirectory(i.key(), i.value()); + } + m_condition.wakeAll(); } + exec(); } +void ThreadedTestHTTPServer::start() +{ + QMutexLocker locker(&m_mutex); + QThread::start(); + m_condition.wait(&m_mutex); +} |