File indexing completed on 2024-05-12 05:15:04

0001 /*
0002    Copyright (C) 2008 Omat Holding B.V. <info@omat.nl>
0003 
0004    Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
0005    Author: Kevin Ottens <kevin@kdab.com>
0006 
0007    Copyright (C) 2017 Sandro Kanuß <knauss@kde.org>
0008 
0009    This program is free software; you can redistribute it and/or
0010    modify it under the terms of the GNU General Public
0011    License as published by the Free Software Foundation; either
0012    version 2 of the License, or (at your option) any later version.
0013 
0014    This program is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017    General Public License for more details.
0018 
0019    You should have received a copy of the GNU General Public License
0020    along with this program; if not, write to the Free Software
0021    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
0022 */
0023 
0024 // Own
0025 #include "fakeserver.h"
0026 
0027 // Qt
0028 #include <QDebug>
0029 #include <QTcpServer>
0030 
0031 #include <QDebug>
0032 #include <QFile>
0033 #include <qtest.h>
0034 
0035 FakeServer::FakeServer(QObject *parent) 
0036     : QThread(parent)
0037     , m_port(5989)
0038 {
0039     moveToThread(this);
0040 }
0041 
0042 FakeServer::~FakeServer()
0043 {
0044     quit();
0045     wait();
0046 }
0047 
0048 void FakeServer::startAndWait()
0049 {
0050     start();
0051     // this will block until the event queue starts
0052     QMetaObject::invokeMethod(this, "started", Qt::BlockingQueuedConnection);
0053 }
0054 
0055 void FakeServer::dataAvailable()
0056 {
0057     QMutexLocker locker(&m_mutex);
0058 
0059     QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
0060     Q_ASSERT(socket != nullptr);
0061 
0062     int scenarioNumber = m_clientSockets.indexOf(socket);
0063 
0064     readClientPart(scenarioNumber);
0065     writeServerPart(scenarioNumber);
0066 }
0067 
0068 void FakeServer::newConnection()
0069 {
0070     QMutexLocker locker(&m_mutex);
0071 
0072     m_clientSockets << m_tcpServer->nextPendingConnection();
0073     connect(m_clientSockets.last(), SIGNAL(readyRead()), this, SLOT(dataAvailable()));
0074 }
0075 
0076 void FakeServer::run()
0077 {
0078     m_tcpServer = new QTcpServer();
0079 
0080     if (!m_tcpServer->listen(QHostAddress(QHostAddress::LocalHost), m_port)) {
0081         qFatal("Unable to start the server");
0082     }
0083 
0084     connect(m_tcpServer, &QTcpServer::newConnection, this, &FakeServer::newConnection);
0085 
0086     exec();
0087 
0088     qDeleteAll(m_clientSockets);
0089 
0090     delete m_tcpServer;
0091 }
0092 
0093 void FakeServer::started()
0094 {
0095     // do nothing: this is a dummy slot used by startAndWait()
0096 }
0097 
0098 void FakeServer::setScenario(const QList<QByteArray> &scenario)
0099 {
0100     QMutexLocker locker(&m_mutex);
0101 
0102     m_scenarios.clear();
0103     m_scenarios << scenario;
0104 }
0105 
0106 void FakeServer::addScenario(const QList<QByteArray> &scenario)
0107 {
0108     QMutexLocker locker(&m_mutex);
0109 
0110     m_scenarios << scenario;
0111 }
0112 
0113 void FakeServer::addScenarioFromFile(const QString &fileName)
0114 {
0115     QFile file(fileName);
0116     file.open(QFile::ReadOnly);
0117 
0118     QList<QByteArray> scenario;
0119 
0120     while (!file.atEnd()) {
0121         scenario << file.readLine().trimmed();
0122     }
0123 
0124     file.close();
0125 
0126     addScenario(scenario);
0127 }
0128 
0129 bool FakeServer::isScenarioDone(int scenarioNumber) const
0130 {
0131     QMutexLocker locker(&m_mutex);
0132 
0133     if (scenarioNumber < m_scenarios.size()) {
0134         return m_scenarios[scenarioNumber].isEmpty();
0135     } else {
0136         return true; // Non existent hence empty, right?
0137     }
0138 }
0139 
0140 bool FakeServer::isAllScenarioDone() const
0141 {
0142     QMutexLocker locker(&m_mutex);
0143 
0144     foreach (const QList<QByteArray> &scenario, m_scenarios) {
0145         if (!scenario.isEmpty()) {
0146             return false;
0147         }
0148     }
0149 
0150     return true;
0151 }
0152 
0153 void FakeServer::writeServerPart(int scenarioNumber)
0154 {
0155     QList<QByteArray> scenario = m_scenarios[scenarioNumber];
0156     QTcpSocket *clientSocket = m_clientSockets[scenarioNumber];
0157 
0158     while (!scenario.isEmpty() &&
0159             scenario.first().startsWith("S: ")) {
0160         QByteArray rule = scenario.takeFirst();
0161 
0162         QByteArray payload = rule.mid(3);
0163         clientSocket->write(payload + "\r\n");
0164     }
0165 
0166     QByteArray data;
0167 
0168     while (!scenario.isEmpty() &&
0169             scenario.first().startsWith("D: ")) {
0170         QByteArray rule = scenario.takeFirst();
0171 
0172         QByteArray payload = rule.mid(3);
0173         data.append(payload + "\r\n");
0174     }
0175 
0176     clientSocket->write(QStringLiteral("Content-Length: %1\r\n\r\n").arg(data.length()).toLatin1());
0177     clientSocket->write(data);
0178 
0179     if (!scenario.isEmpty() &&
0180             scenario.first().startsWith("X")) {
0181         scenario.takeFirst();
0182         clientSocket->close();
0183     }
0184 
0185     if (!scenario.isEmpty()) {
0186         QVERIFY(scenario.first().startsWith("C: "));
0187     }
0188 
0189     m_scenarios[scenarioNumber] = scenario;
0190 }
0191 
0192 void FakeServer::readClientPart(int scenarioNumber)
0193 {
0194     QList<QByteArray> scenario = m_scenarios[scenarioNumber];
0195     QTcpSocket *socket = m_clientSockets[scenarioNumber];
0196     QByteArray line = socket->readLine();
0197     QVector<QByteArray> header;
0198 
0199     while(line != "\r\n") {
0200         header << line;
0201         line = socket->readLine();
0202     }
0203 
0204     while (!scenario.isEmpty() &&
0205             scenario.first().startsWith("C: ")) {
0206         QByteArray expected = scenario.takeFirst().mid(3) + "\r\n";
0207 
0208         if (!header.contains(expected)) {
0209             qWarning() << expected << "not found in header: " << header;
0210             QVERIFY(false);
0211             break;
0212         }
0213     }
0214 
0215     if (!scenario.isEmpty()) {
0216         QVERIFY(scenario.first().startsWith("S: "));
0217     }
0218 
0219     m_scenarios[scenarioNumber] = scenario;
0220 }
0221 
0222 int FakeServer::port() const
0223 {
0224     return m_port;
0225 }