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 }