2013-01-27 09:40:09 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
*
|
|
|
|
* Copyright (C) 2013 Dominik Riebeling
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2021-12-26 10:06:57 +00:00
|
|
|
#include <QtTest>
|
|
|
|
#include <QObject>
|
2013-01-27 09:40:09 +00:00
|
|
|
#include "httpget.h"
|
|
|
|
|
|
|
|
#define TEST_USER_AGENT "TestAgent/2.3"
|
2021-12-21 17:34:01 +00:00
|
|
|
#define TEST_HTTP_TIMEOUT 10000
|
2013-01-27 09:40:09 +00:00
|
|
|
#define TEST_BINARY_BLOB "\x01\x10\x20\x30\x40\x50\x60\x70" \
|
|
|
|
"\x80\x90\xff\xee\xdd\xcc\xbb\xaa"
|
|
|
|
|
|
|
|
// HttpDaemon is the the class that implements the simple HTTP server.
|
|
|
|
class HttpDaemon : public QTcpServer
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
2015-12-18 22:15:13 +00:00
|
|
|
HttpDaemon(quint16 port = 0, QObject* parent = 0) : QTcpServer(parent)
|
2013-01-27 09:40:09 +00:00
|
|
|
{
|
|
|
|
listen(QHostAddress::Any, port);
|
|
|
|
}
|
|
|
|
|
2015-12-18 22:15:13 +00:00
|
|
|
quint16 port(void) { return this->serverPort(); }
|
|
|
|
|
2013-01-27 09:40:09 +00:00
|
|
|
#if QT_VERSION < 0x050000
|
|
|
|
void incomingConnection(int socket)
|
|
|
|
#else
|
|
|
|
// Qt 5 uses a different prototype for this function!
|
|
|
|
void incomingConnection(qintptr socket)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
// When a new client connects, the server constructs a QTcpSocket and all
|
|
|
|
// communication with the client is done over this QTcpSocket. QTcpSocket
|
|
|
|
// works asynchronously, this means that all the communication is done
|
|
|
|
// in the two slots readClient() and discardClient().
|
|
|
|
QTcpSocket* s = new QTcpSocket(this);
|
2021-12-25 16:29:55 +00:00
|
|
|
connect(s, &QIODevice::readyRead, this, &HttpDaemon::readClient);
|
|
|
|
connect(s, &QAbstractSocket::disconnected, this, &HttpDaemon::discardClient);
|
2013-01-27 09:40:09 +00:00
|
|
|
s->setSocketDescriptor(socket);
|
|
|
|
}
|
|
|
|
QList<QString> lastRequestData(void)
|
|
|
|
{
|
|
|
|
return m_lastRequestData;
|
|
|
|
}
|
|
|
|
void setResponsesToSend(QList<QByteArray> response)
|
|
|
|
{
|
|
|
|
m_requestNumber = 0;
|
|
|
|
m_responsesToSend = response;
|
|
|
|
}
|
|
|
|
void reset(void)
|
|
|
|
{
|
|
|
|
m_requestNumber = 0;
|
|
|
|
m_lastRequestData.clear();
|
|
|
|
QString now =
|
|
|
|
QDateTime::currentDateTime().toString("ddd, d MMM yyyy hh:mm:ss");
|
|
|
|
m_defaultResponse = QByteArray(
|
|
|
|
"HTTP/1.1 404 Not Found\r\n"
|
|
|
|
"Date: " + now.toLatin1() + "\r\n"
|
|
|
|
"Last-Modified: " + now.toLatin1() + "\r\n"
|
|
|
|
"Connection: close\r\n"
|
|
|
|
"\r\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void readClient()
|
|
|
|
{
|
|
|
|
// This slot is called when the client sent data to the server.
|
|
|
|
QTcpSocket* socket = (QTcpSocket*)sender();
|
|
|
|
// read whole request
|
|
|
|
QString request;
|
|
|
|
while(socket->canReadLine()) {
|
|
|
|
QString line = socket->readLine();
|
|
|
|
request.append(line);
|
|
|
|
if(request.endsWith("\r\n\r\n")) {
|
|
|
|
m_lastRequestData.append(request);
|
|
|
|
|
|
|
|
if(m_requestNumber < m_responsesToSend.size())
|
|
|
|
socket->write(m_responsesToSend.at(m_requestNumber));
|
|
|
|
else
|
|
|
|
socket->write(m_defaultResponse);
|
|
|
|
socket->close();
|
|
|
|
m_requestNumber++;
|
|
|
|
}
|
2021-12-25 16:36:50 +00:00
|
|
|
if (socket->state() == QTcpSocket::UnconnectedState) {
|
2013-01-27 09:40:09 +00:00
|
|
|
delete socket;
|
2021-12-25 16:36:50 +00:00
|
|
|
break;
|
|
|
|
}
|
2013-01-27 09:40:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
void discardClient()
|
|
|
|
{
|
|
|
|
QTcpSocket* socket = (QTcpSocket*)sender();
|
|
|
|
socket->deleteLater();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
int m_requestNumber;
|
|
|
|
QList<QByteArray> m_responsesToSend;
|
|
|
|
QList<QString> m_lastRequestData;
|
|
|
|
QByteArray m_defaultResponse;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class TestHttpGet : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
private slots:
|
2015-12-18 22:05:13 +00:00
|
|
|
void testFileUrlRequest(void);
|
2013-01-27 09:40:09 +00:00
|
|
|
void testCachedRequest(void);
|
|
|
|
void testUncachedRepeatedRequest(void);
|
|
|
|
void testUncachedMovedRequest(void);
|
|
|
|
void testUserAgent(void);
|
|
|
|
void testResponseCode(void);
|
|
|
|
void testContentToBuffer(void);
|
|
|
|
void testContentToFile(void);
|
|
|
|
void testNoServer(void);
|
|
|
|
void testServerTimestamp(void);
|
|
|
|
void testMovedQuery(void);
|
|
|
|
void init(void);
|
|
|
|
void cleanup(void);
|
|
|
|
|
|
|
|
public slots:
|
2015-12-18 22:15:13 +00:00
|
|
|
void waitTimeout(void)
|
|
|
|
{
|
|
|
|
m_waitTimeoutOccured = true;
|
|
|
|
}
|
2013-01-27 09:40:09 +00:00
|
|
|
QDir temporaryFolder(void)
|
|
|
|
{
|
|
|
|
// Qt unfortunately doesn't support creating temporary folders so
|
|
|
|
// we need to do that ourselves.
|
|
|
|
QString tempdir;
|
|
|
|
for(int i = 0; i < 100000; i++) {
|
|
|
|
tempdir = QDir::tempPath() + QString("/qttest-temp-%1").arg(i);
|
2021-12-25 18:59:57 +00:00
|
|
|
if(!QFileInfo::exists(tempdir))
|
|
|
|
break;
|
2013-01-27 09:40:09 +00:00
|
|
|
}
|
|
|
|
QDir().mkpath(tempdir);
|
|
|
|
return QDir(tempdir);
|
|
|
|
}
|
|
|
|
void rmTree(QString folder)
|
|
|
|
{
|
|
|
|
// no function in Qt to recursively delete a folder :(
|
|
|
|
QDir dir(folder);
|
|
|
|
Q_FOREACH(QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot
|
|
|
|
| QDir::System | QDir::Hidden | QDir::AllDirs
|
|
|
|
| QDir::Files, QDir::DirsFirst)) {
|
|
|
|
if(info.isDir()) rmTree(info.absoluteFilePath());
|
|
|
|
else QFile::remove(info.absoluteFilePath());
|
|
|
|
}
|
|
|
|
dir.rmdir(folder);
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
HttpDaemon *m_daemon;
|
2015-12-18 22:15:13 +00:00
|
|
|
QByteArray m_port;
|
2013-01-27 09:40:09 +00:00
|
|
|
bool m_waitTimeoutOccured;
|
|
|
|
QString m_now;
|
|
|
|
QDir m_cachedir;
|
2015-12-20 10:10:18 +00:00
|
|
|
HttpGet *m_getter;
|
|
|
|
QSignalSpy *m_doneSpy;
|
|
|
|
QSignalSpy *m_progressSpy;
|
2013-01-27 09:40:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void TestHttpGet::init(void)
|
|
|
|
{
|
|
|
|
m_now = QDateTime::currentDateTime().toString("ddd, d MMM yyyy hh:mm:ss");
|
2015-12-18 22:15:13 +00:00
|
|
|
m_daemon = new HttpDaemon(0, this); // use port 0 to auto-pick
|
2013-01-27 09:40:09 +00:00
|
|
|
m_daemon->reset();
|
2015-12-18 22:15:13 +00:00
|
|
|
m_port = QString("%1").arg(m_daemon->port()).toLatin1();
|
2013-01-27 09:40:09 +00:00
|
|
|
m_cachedir = temporaryFolder();
|
|
|
|
m_getter = new HttpGet(this);
|
2021-12-25 16:29:55 +00:00
|
|
|
m_doneSpy = new QSignalSpy(m_getter, &HttpGet::done);
|
|
|
|
m_progressSpy = new QSignalSpy(m_getter, &HttpGet::dataReadProgress);
|
2013-01-27 09:40:09 +00:00
|
|
|
m_waitTimeoutOccured = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestHttpGet::cleanup(void)
|
|
|
|
{
|
|
|
|
rmTree(m_cachedir.absolutePath());
|
|
|
|
if(m_getter) {
|
2022-03-16 21:19:00 +00:00
|
|
|
m_getter->abort(); delete m_getter; m_getter = nullptr;
|
2013-01-27 09:40:09 +00:00
|
|
|
}
|
2022-03-16 21:19:00 +00:00
|
|
|
if(m_daemon) { delete m_daemon; m_daemon = nullptr; }
|
|
|
|
if(m_doneSpy) { delete m_doneSpy; m_doneSpy = nullptr; }
|
|
|
|
if(m_progressSpy) { delete m_progressSpy; m_progressSpy = nullptr; }
|
2013-01-27 09:40:09 +00:00
|
|
|
}
|
|
|
|
|
2015-12-18 22:05:13 +00:00
|
|
|
void TestHttpGet::testFileUrlRequest(void)
|
|
|
|
{
|
2021-12-25 16:29:55 +00:00
|
|
|
QTimer::singleShot(TEST_HTTP_TIMEOUT, this, &TestHttpGet::waitTimeout);
|
2015-12-18 22:05:13 +00:00
|
|
|
|
|
|
|
QString teststring = "The quick brown fox jumps over the lazy dog.";
|
|
|
|
QTemporaryFile datafile;
|
|
|
|
datafile.open();
|
|
|
|
datafile.write(teststring.toLatin1());
|
2016-04-09 11:15:11 +00:00
|
|
|
m_getter->getFile(QUrl::fromLocalFile(datafile.fileName()));
|
2015-12-18 22:05:13 +00:00
|
|
|
datafile.close();
|
|
|
|
while(m_doneSpy->count() == 0 && m_waitTimeoutOccured == false)
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
|
|
|
|
QCOMPARE(m_doneSpy->count(), 1);
|
|
|
|
QCOMPARE(m_waitTimeoutOccured, false);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().size(), 0);
|
|
|
|
QCOMPARE(m_getter->readAll(), teststring.toLatin1());
|
|
|
|
QCOMPARE(m_getter->httpResponse(), 200);
|
2015-12-20 10:10:18 +00:00
|
|
|
QCOMPARE(m_progressSpy->at(0).at(0).toInt(), 0);
|
2015-12-18 22:05:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-01-27 09:40:09 +00:00
|
|
|
/* On uncached requests, HttpGet is supposed to sent a GET request only.
|
|
|
|
*/
|
|
|
|
void TestHttpGet::testUncachedRepeatedRequest(void)
|
|
|
|
{
|
|
|
|
QList<QByteArray> responses;
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
"Date: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"Last-Modified: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"\r\n\r\n");
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
"Last-Modified: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"Date: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"<html></html>\r\n\r\n");
|
|
|
|
m_daemon->setResponsesToSend(responses);
|
|
|
|
|
2021-12-25 16:29:55 +00:00
|
|
|
QTimer::singleShot(TEST_HTTP_TIMEOUT, this, &TestHttpGet::waitTimeout);
|
2013-01-27 09:40:09 +00:00
|
|
|
|
2015-12-18 22:15:13 +00:00
|
|
|
m_getter->getFile(QUrl("http://localhost:" + m_port + "/test1.txt"));
|
2013-01-27 09:40:09 +00:00
|
|
|
while(m_doneSpy->count() == 0 && m_waitTimeoutOccured == false)
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
|
|
|
|
QCOMPARE(m_doneSpy->count(), 1);
|
|
|
|
QCOMPARE(m_waitTimeoutOccured, false);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().size(), 1);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().at(0).startsWith("GET"), true);
|
|
|
|
|
|
|
|
// request second time
|
2015-12-18 22:15:13 +00:00
|
|
|
m_getter->getFile(QUrl("http://localhost:" + m_port + "/test1.txt"));
|
2013-01-27 09:40:09 +00:00
|
|
|
while(m_doneSpy->count() < 2 && m_waitTimeoutOccured == false)
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
QCOMPARE(m_doneSpy->count(), 2);
|
|
|
|
QCOMPARE(m_waitTimeoutOccured, false);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().size(), 2);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().at(1).startsWith("GET"), true);
|
|
|
|
QCOMPARE(m_getter->httpResponse(), 200);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* With enabled cache HttpGet is supposed to check the server file using a HEAD
|
|
|
|
* request first, then request the file using GET if the server file is newer
|
|
|
|
* than the cached one (or the file does not exist in the cache)
|
|
|
|
*/
|
|
|
|
void TestHttpGet::testCachedRequest(void)
|
|
|
|
{
|
|
|
|
QList<QByteArray> responses;
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 302 Found\r\n"
|
2015-12-18 22:15:13 +00:00
|
|
|
"Location: http://localhost:" + m_port + "/test2.txt\r\n"
|
2013-01-27 09:40:09 +00:00
|
|
|
"Date: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"Last-Modified: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"\r\n");
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
"Last-Modified: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"Date: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"<html></html>\r\n\r\n");
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
"Last-Modified: 1 Jan 2000 00:00:00\r\n"
|
|
|
|
"Date: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"\r\n");
|
|
|
|
m_daemon->setResponsesToSend(responses);
|
|
|
|
|
2021-12-25 16:29:55 +00:00
|
|
|
QTimer::singleShot(TEST_HTTP_TIMEOUT, this, &TestHttpGet::waitTimeout);
|
2013-01-27 09:40:09 +00:00
|
|
|
|
|
|
|
m_getter->setCache(m_cachedir);
|
2015-12-18 22:15:13 +00:00
|
|
|
m_getter->getFile(QUrl("http://localhost:" + m_port + "/test1.txt"));
|
2013-01-27 09:40:09 +00:00
|
|
|
while(m_doneSpy->count() == 0 && m_waitTimeoutOccured == false)
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
|
|
|
|
QList<QString> requests = m_daemon->lastRequestData();
|
|
|
|
QCOMPARE(m_doneSpy->count(), 1);
|
2022-03-16 21:19:00 +00:00
|
|
|
QCOMPARE(m_doneSpy->at(0).at(0).toInt(), QNetworkReply::NoError);
|
2013-01-27 09:40:09 +00:00
|
|
|
QCOMPARE(m_waitTimeoutOccured, false);
|
|
|
|
QCOMPARE(requests.size(), 2);
|
|
|
|
QCOMPARE(requests.at(0).startsWith("GET"), true);
|
|
|
|
QCOMPARE(requests.at(1).startsWith("GET"), true);
|
|
|
|
QCOMPARE(m_getter->httpResponse(), 200);
|
|
|
|
|
|
|
|
// request real file, this time the response should come from cache.
|
2015-12-18 22:15:13 +00:00
|
|
|
m_getter->getFile(QUrl("http://localhost:" + m_port + "/test2.txt"));
|
2013-01-27 09:40:09 +00:00
|
|
|
while(m_doneSpy->count() < 2 && m_waitTimeoutOccured == false)
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
QCOMPARE(m_doneSpy->count(), 2); // 2 requests, 2 times done()
|
2022-03-16 21:19:00 +00:00
|
|
|
QCOMPARE(m_doneSpy->at(1).at(0).toInt(), QNetworkReply::NoError);
|
2013-01-27 09:40:09 +00:00
|
|
|
QCOMPARE(m_waitTimeoutOccured, false);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().size(), 3);
|
|
|
|
// redirect will not cache as the redirection target file.
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().at(2).startsWith("GET"), true);
|
|
|
|
QCOMPARE(m_getter->httpResponse(), 200);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* When a custom user agent is set all requests are supposed to contain it.
|
|
|
|
* Enable cache to make HttpGet performs a HEAD request. Answer with 302, so
|
|
|
|
* HttpGet follows and sends another HEAD request before finally doing a GET.
|
|
|
|
*/
|
|
|
|
void TestHttpGet::testUserAgent(void)
|
|
|
|
{
|
|
|
|
QList<QByteArray> responses;
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
"Date: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"Last-Modified: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"\r\n\r\n");
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
"Last-Modified: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"Date: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"<html></html>\r\n\r\n");
|
|
|
|
m_daemon->setResponsesToSend(responses);
|
|
|
|
|
2021-12-25 16:29:55 +00:00
|
|
|
QTimer::singleShot(TEST_HTTP_TIMEOUT, this, &TestHttpGet::waitTimeout);
|
2013-01-27 09:40:09 +00:00
|
|
|
|
|
|
|
m_getter->setGlobalUserAgent(TEST_USER_AGENT);
|
|
|
|
m_getter->setCache(m_cachedir);
|
2015-12-18 22:15:13 +00:00
|
|
|
m_getter->getFile(QUrl("http://localhost:" + m_port + "/test1.txt"));
|
2013-01-27 09:40:09 +00:00
|
|
|
while(m_doneSpy->count() == 0 && m_waitTimeoutOccured == false)
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
|
|
|
|
QList<QString> requests = m_daemon->lastRequestData();
|
|
|
|
QCOMPARE(m_doneSpy->count(), 1);
|
|
|
|
QCOMPARE(m_waitTimeoutOccured, false);
|
|
|
|
QCOMPARE(requests.size(), 1);
|
|
|
|
QCOMPARE(requests.at(0).startsWith("GET"), true);
|
|
|
|
|
|
|
|
for(int i = 0; i < requests.size(); ++i) {
|
2021-12-26 10:06:57 +00:00
|
|
|
QRegularExpression rx("User-Agent:[\t ]+([a-zA-Z0-9\\./]+)");
|
|
|
|
auto match = rx.match(requests.at(i));
|
|
|
|
bool userAgentFound = match.hasMatch();
|
2013-01-27 09:40:09 +00:00
|
|
|
QCOMPARE(userAgentFound, true);
|
2021-12-26 10:06:57 +00:00
|
|
|
QString userAgentString = match.captured(1);
|
2013-01-27 09:40:09 +00:00
|
|
|
QCOMPARE(userAgentString, QString(TEST_USER_AGENT));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestHttpGet::testUncachedMovedRequest(void)
|
|
|
|
{
|
|
|
|
QList<QByteArray> responses;
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 302 Found\r\n"
|
2015-12-18 22:15:13 +00:00
|
|
|
"Location: http://localhost:" + m_port + "/test2.txt\r\n"
|
2013-01-27 09:40:09 +00:00
|
|
|
"Date: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"Last-Modified: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"\r\n");
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
"Last-Modified: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"Date: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"<html></html>\r\n\r\n");
|
|
|
|
m_daemon->setResponsesToSend(responses);
|
|
|
|
|
2021-12-25 16:29:55 +00:00
|
|
|
QTimer::singleShot(TEST_HTTP_TIMEOUT, this, &TestHttpGet::waitTimeout);
|
2013-01-27 09:40:09 +00:00
|
|
|
|
2015-12-18 22:15:13 +00:00
|
|
|
m_getter->getFile(QUrl("http://localhost:" + m_port + "/test1.php?var=1&b=foo"));
|
2013-01-27 09:40:09 +00:00
|
|
|
while(m_doneSpy->count() == 0 && m_waitTimeoutOccured == false)
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
|
|
|
|
QCOMPARE(m_doneSpy->count(), 1);
|
|
|
|
QCOMPARE(m_waitTimeoutOccured, false);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().size(), 2);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().at(0).startsWith("GET"), true);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().at(1).startsWith("GET"), true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestHttpGet::testResponseCode(void)
|
|
|
|
{
|
2021-12-25 16:29:55 +00:00
|
|
|
QTimer::singleShot(TEST_HTTP_TIMEOUT, this, &TestHttpGet::waitTimeout);
|
2013-01-27 09:40:09 +00:00
|
|
|
|
2015-12-18 22:15:13 +00:00
|
|
|
m_getter->getFile(QUrl("http://localhost:" + m_port + "/test1.txt"));
|
2013-01-27 09:40:09 +00:00
|
|
|
while(m_doneSpy->count() == 0 && m_waitTimeoutOccured == false)
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
|
|
|
|
QCOMPARE(m_doneSpy->count(), 1);
|
2022-03-16 21:19:00 +00:00
|
|
|
QCOMPARE(m_doneSpy->at(0).at(0).toInt(), QNetworkReply::ContentNotFoundError);
|
2013-01-27 09:40:09 +00:00
|
|
|
QCOMPARE(m_waitTimeoutOccured, false);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().size(), 1);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().at(0).startsWith("GET"), true);
|
|
|
|
QCOMPARE(m_getter->httpResponse(), 404);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestHttpGet::testContentToBuffer(void)
|
|
|
|
{
|
|
|
|
QList<QByteArray> responses;
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
"Last-Modified: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"Date: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"\r\n"
|
|
|
|
TEST_BINARY_BLOB);
|
|
|
|
m_daemon->setResponsesToSend(responses);
|
|
|
|
|
2021-12-25 16:29:55 +00:00
|
|
|
QTimer::singleShot(TEST_HTTP_TIMEOUT, this, &TestHttpGet::waitTimeout);
|
2013-01-27 09:40:09 +00:00
|
|
|
|
2015-12-18 22:15:13 +00:00
|
|
|
m_getter->getFile(QUrl("http://localhost:" + m_port + "/test1.txt"));
|
2013-01-27 09:40:09 +00:00
|
|
|
while(m_doneSpy->count() == 0 && m_waitTimeoutOccured == false)
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
|
|
|
|
QCOMPARE(m_doneSpy->count(), 1);
|
|
|
|
QCOMPARE(m_waitTimeoutOccured, false);
|
|
|
|
QCOMPARE(m_getter->readAll(), QByteArray(TEST_BINARY_BLOB));
|
|
|
|
// sizeof(TEST_BINARY_BLOB) will include an additional terminating NULL.
|
2016-03-27 10:36:37 +00:00
|
|
|
QCOMPARE(m_getter->readAll().size(), (int)sizeof(TEST_BINARY_BLOB) - 1);
|
2015-12-20 10:10:18 +00:00
|
|
|
QCOMPARE(m_progressSpy->at(m_progressSpy->count() - 1).at(0).toInt(), (int)sizeof(TEST_BINARY_BLOB) - 1);
|
|
|
|
QCOMPARE(m_progressSpy->at(m_progressSpy->count() - 1).at(1).toInt(), (int)sizeof(TEST_BINARY_BLOB) - 1);
|
2013-01-27 09:40:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestHttpGet::testContentToFile(void)
|
|
|
|
{
|
|
|
|
QTemporaryFile tf(this);
|
|
|
|
QList<QByteArray> responses;
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
"Last-Modified: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"Date: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"\r\n"
|
|
|
|
TEST_BINARY_BLOB);
|
|
|
|
m_daemon->setResponsesToSend(responses);
|
|
|
|
|
2021-12-25 16:29:55 +00:00
|
|
|
QTimer::singleShot(TEST_HTTP_TIMEOUT, this, &TestHttpGet::waitTimeout);
|
2013-01-27 09:40:09 +00:00
|
|
|
|
|
|
|
m_getter->setFile(&tf);
|
2015-12-18 22:15:13 +00:00
|
|
|
m_getter->getFile(QUrl("http://localhost:" + m_port + "/test1.txt"));
|
2013-01-27 09:40:09 +00:00
|
|
|
while(m_doneSpy->count() == 0 && m_waitTimeoutOccured == false)
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
|
|
|
|
QCOMPARE(m_doneSpy->count(), 1);
|
|
|
|
QCOMPARE(m_waitTimeoutOccured, false);
|
|
|
|
|
|
|
|
tf.open();
|
|
|
|
QByteArray data = tf.readAll();
|
|
|
|
QCOMPARE(data, QByteArray(TEST_BINARY_BLOB));
|
|
|
|
QCOMPARE((unsigned long)data.size(), sizeof(TEST_BINARY_BLOB) - 1);
|
|
|
|
tf.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestHttpGet::testNoServer(void)
|
|
|
|
{
|
2021-12-25 16:29:55 +00:00
|
|
|
QTimer::singleShot(TEST_HTTP_TIMEOUT, this, &TestHttpGet::waitTimeout);
|
2015-12-18 22:15:13 +00:00
|
|
|
m_getter->getFile(QUrl("http://localhost:53/test1.txt"));
|
2013-01-27 09:40:09 +00:00
|
|
|
while(m_doneSpy->count() == 0 && m_waitTimeoutOccured == false)
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
|
|
|
|
QCOMPARE(m_doneSpy->count(), 1);
|
2022-03-16 21:19:00 +00:00
|
|
|
QCOMPARE(m_doneSpy->at(0).at(0).toInt(), QNetworkReply::ConnectionRefusedError);
|
2013-01-27 09:40:09 +00:00
|
|
|
QCOMPARE(m_waitTimeoutOccured, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestHttpGet::testServerTimestamp(void)
|
|
|
|
{
|
|
|
|
QList<QByteArray> responses;
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
"Last-Modified: Wed, 20 Jan 2010 10:20:30\r\n" // RFC 822
|
|
|
|
"Date: Wed, 20 Jan 2010 10:20:30\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"\r\n");
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
"Last-Modified: Sat Feb 19 09:08:07 2011\r\n" // asctime
|
|
|
|
"Date: Sat Feb 19 09:08:07 2011\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"\r\n");
|
|
|
|
|
|
|
|
QList<QDateTime> times;
|
|
|
|
times << QDateTime::fromString("2010-01-20T11:20:30", Qt::ISODate);
|
|
|
|
times << QDateTime::fromString("2011-02-19T10:08:07", Qt::ISODate);
|
|
|
|
|
|
|
|
m_daemon->setResponsesToSend(responses);
|
|
|
|
|
2021-12-25 16:29:55 +00:00
|
|
|
QTimer::singleShot(TEST_HTTP_TIMEOUT, this, &TestHttpGet::waitTimeout);
|
2013-01-27 09:40:09 +00:00
|
|
|
|
|
|
|
int count = m_doneSpy->count();
|
|
|
|
for(int i = 0; i < responses.size(); ++i) {
|
2015-12-18 22:15:13 +00:00
|
|
|
m_getter->getFile(QUrl("http://localhost:" + m_port + "/test1.txt"));
|
2013-01-27 09:40:09 +00:00
|
|
|
while(m_doneSpy->count() == count && m_waitTimeoutOccured == false)
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
count = m_doneSpy->count();
|
|
|
|
QCOMPARE(m_getter->timestamp(), times.at(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestHttpGet::testMovedQuery(void)
|
|
|
|
{
|
|
|
|
QList<QByteArray> responses;
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 302 Found\r\n"
|
2015-12-18 22:15:13 +00:00
|
|
|
"Location: http://localhost:" + m_port + "/test2.php\r\n"
|
2013-01-27 09:40:09 +00:00
|
|
|
"Date: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"Last-Modified: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"\r\n");
|
|
|
|
responses << QByteArray(
|
|
|
|
"HTTP/1.1 200 OK\r\n"
|
|
|
|
"Last-Modified: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"Date: " + m_now.toLatin1() + "\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"<html></html>\r\n\r\n");
|
|
|
|
m_daemon->setResponsesToSend(responses);
|
|
|
|
|
2021-12-25 16:29:55 +00:00
|
|
|
QTimer::singleShot(TEST_HTTP_TIMEOUT, this, &TestHttpGet::waitTimeout);
|
2013-01-27 09:40:09 +00:00
|
|
|
|
2015-12-18 22:15:13 +00:00
|
|
|
m_getter->getFile(QUrl("http://localhost:" + m_port + "/test1.php?var=1&b=foo"));
|
2013-01-27 09:40:09 +00:00
|
|
|
while(m_doneSpy->count() == 0 && m_waitTimeoutOccured == false)
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
|
|
|
|
QCOMPARE(m_doneSpy->count(), 1);
|
|
|
|
QCOMPARE(m_waitTimeoutOccured, false);
|
|
|
|
QCOMPARE(m_getter->httpResponse(), 200);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().size(), 2);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().at(0).startsWith("GET"), true);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().at(1).startsWith("GET"), true);
|
|
|
|
// current implementation keeps order of query items.
|
2021-12-26 10:06:57 +00:00
|
|
|
qDebug() << m_daemon->lastRequestData().at(1);
|
|
|
|
QCOMPARE(m_daemon->lastRequestData().at(1).contains("/test2.php?var=1&b=foo"), true);
|
2013-01-27 09:40:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QTEST_MAIN(TestHttpGet)
|
|
|
|
|
|
|
|
// this include is needed because we don't use a separate header file for the
|
|
|
|
// test class. It also needs to be at the end.
|
|
|
|
#include "test-httpget.moc"
|
|
|
|
|