summaryrefslogtreecommitdiffstats
path: root/tests/arthur/common
diff options
context:
space:
mode:
authoraavit <qt-info@nokia.com>2010-08-25 11:49:34 (GMT)
committeraavit <qt-info@nokia.com>2010-08-25 11:49:34 (GMT)
commitdeef2e16776c171d4b033257cd4fc3ab2bd005a3 (patch)
tree85ac87094fc690f71d20a6bd2989879b166992bf /tests/arthur/common
parentdae23694cb89b853785a5772cc7e0477f65ac5bf (diff)
downloadQt-deef2e16776c171d4b033257cd4fc3ab2bd005a3.zip
Qt-deef2e16776c171d4b033257cd4fc3ab2bd005a3.tar.gz
Qt-deef2e16776c171d4b033257cd4fc3ab2bd005a3.tar.bz2
First shot at a new client-server based autotest of the Arthur
2D rendering system, based on the lance test tool. Hence dubbed lancelot.
Diffstat (limited to 'tests/arthur/common')
-rw-r--r--tests/arthur/common/baselineprotocol.cpp219
-rw-r--r--tests/arthur/common/baselineprotocol.h76
-rw-r--r--tests/arthur/common/baselineprotocol.pri9
3 files changed, 304 insertions, 0 deletions
diff --git a/tests/arthur/common/baselineprotocol.cpp b/tests/arthur/common/baselineprotocol.cpp
new file mode 100644
index 0000000..fb4f06d
--- /dev/null
+++ b/tests/arthur/common/baselineprotocol.cpp
@@ -0,0 +1,219 @@
+
+#include "baselineprotocol.h"
+#include <QLibraryInfo>
+#include <QImage>
+#include <QBuffer>
+#include <QHostInfo>
+
+PlatformInfo::PlatformInfo(bool useLocal)
+{
+ if (useLocal) {
+ buildKey = QLibraryInfo::buildKey();
+ qtVersion = QLatin1String(qVersion());
+ hostname = QHostInfo::localHostName();
+ }
+}
+
+QDataStream & operator<< (QDataStream &stream, const PlatformInfo &pinfo)
+{
+ stream << pinfo.buildKey << pinfo.qtVersion << pinfo.hostname;
+ return stream;
+}
+
+QDataStream & operator>> (QDataStream& stream, PlatformInfo& pinfo)
+{
+ stream >> pinfo.buildKey >> pinfo.qtVersion >> pinfo.hostname;
+ return stream;
+}
+
+BaselineProtocol::~BaselineProtocol()
+{
+ socket.close();
+ if (socket.state() != QTcpSocket::UnconnectedState)
+ socket.waitForDisconnected(Timeout);
+}
+
+
+bool BaselineProtocol::connect()
+{
+ errMsg.clear();
+ //TBD: determine server address; for now localhost
+ QLatin1String serverName("localhost");
+
+ socket.connectToHost(serverName, ServerPort);
+
+ if (!socket.waitForConnected(Timeout)) {
+ errMsg += QLatin1String("TCP connectToHost failed. Host:") + serverName + QLatin1String(" port:") + QString::number(ServerPort);
+ return false;
+ }
+
+ PlatformInfo pi(true);
+ QByteArray block;
+ QDataStream ds(&block, QIODevice::ReadWrite);
+ ds << pi;
+ if (!sendBlock(AcceptPlatformInfo, block)) {
+ errMsg += QLatin1String("Failed to send data to server.");
+ return false;
+ }
+
+ Command cmd = Ack;
+ if (!receiveBlock(&cmd, &block) || cmd != Ack) {
+ errMsg += QLatin1String("Failed to get response from server.");
+ return false;
+ }
+
+ return true;
+}
+
+
+bool BaselineProtocol::acceptConnection(PlatformInfo *pi)
+{
+ errMsg.clear();
+
+ QByteArray block;
+ Command cmd = AcceptPlatformInfo;
+ if (!receiveBlock(&cmd, &block) || cmd != AcceptPlatformInfo)
+ return false;
+
+ if (pi) {
+ QDataStream ds(block);
+ ds >> *pi;
+ }
+
+ if (!sendBlock(Ack, QByteArray()))
+ return false;
+ return true;
+}
+
+
+bool BaselineProtocol::requestBaseline(const QString &caseId, Command *response, QImage *baseline)
+{
+ errMsg.clear();
+ if (!sendBlock(RequestBaseline, caseId.toLatin1()))
+ return false;
+ QByteArray imgData;
+ Command cmd;
+ if (!receiveBlock(&cmd, &imgData))
+ return false;
+ if (response)
+ *response = cmd;
+ if (cmd == BaselineNotPresent || cmd == IgnoreCase)
+ return true;
+ else if (cmd == AcceptBaseline) {
+ if (baseline) {
+ // hm, get the name also, for checking?
+ *baseline = QImage::fromData(imgData);
+ if (baseline->isNull()) {
+ errMsg.prepend(QLatin1String("Invalid baseline image data received. "));
+ return false;
+ }
+ }
+ return true;
+ }
+ errMsg.prepend(QLatin1String("Unexpected reply from server on baseline request. "));
+ return false;
+}
+
+
+bool BaselineProtocol::submitNewBaseline(const QString &caseId, const QImage &baseline)
+{
+ errMsg.clear();
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QDataStream ds(&buf);
+ ds << caseId.toLatin1();
+ if (!baseline.save(&buf, FileFormat)) {
+ errMsg = QLatin1String("Failed to convert new baseline image to ") + QLatin1String(FileFormat);
+ return false;
+ }
+ if (!sendBlock(AcceptNewBaseline, buf.data())) {
+ errMsg.prepend(QLatin1String("Failed to submit new baseline to server. "));
+ return false;
+ }
+ Command cmd;
+ receiveBlock(&cmd, 0); // Just wait for the pong; ignore reply contents
+ return true;
+}
+
+
+bool BaselineProtocol::submitMismatch(const QString &caseId, const QImage &mismatch, QByteArray *failMsg)
+{
+ errMsg.clear();
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QDataStream ds(&buf);
+ ds << caseId.toLatin1();
+ if (!mismatch.save(&buf, FileFormat)) {
+ errMsg = QLatin1String("Failed to convert mismatched image to ") + QLatin1String(FileFormat);
+ return false;
+ }
+ if (!sendBlock(AcceptMismatch, buf.data())) {
+ errMsg.prepend(QLatin1String("Failed to submit mismatched image to server. "));
+ return false;
+ }
+ Command cmd;
+ if (!receiveBlock(&cmd, failMsg)) {
+ errMsg.prepend(QLatin1String("Failed to receive response on mismatched image from server. "));
+ return false;
+ }
+ return true;
+}
+
+
+bool BaselineProtocol::sendBlock(Command cmd, const QByteArray &block)
+{
+ QDataStream s(&socket);
+ // TBD: set qds version as a constant
+ s << quint16(ProtocolVersion) << quint16(cmd);
+ s.writeBytes(block.constData(), block.size());
+ return true;
+}
+
+
+bool BaselineProtocol::receiveBlock(Command *cmd, QByteArray *block)
+{
+ while (socket.bytesAvailable() < int(2*sizeof(quint16) + sizeof(quint32))) {
+ if (!socket.waitForReadyRead(Timeout))
+ return false;
+ }
+ QDataStream ds(&socket);
+ quint16 rcvProtocolVersion, rcvCmd;
+ ds >> rcvProtocolVersion >> rcvCmd;
+ if (rcvProtocolVersion != ProtocolVersion) {
+ // TBD: More resilient handling of this case; the server should accept client's version
+ errMsg = QLatin1String("Server protocol version mismatch, received:") + QString::number(rcvProtocolVersion);
+
+ return false;
+ }
+ if (cmd)
+ *cmd = Command(rcvCmd);
+
+ QByteArray uMsg;
+ quint32 remaining;
+ ds >> remaining;
+ uMsg.resize(remaining);
+ int got = 0;
+ char* uMsgBuf = uMsg.data();
+ do {
+ got = ds.readRawData(uMsgBuf, remaining);
+ remaining -= got;
+ uMsgBuf += got;
+ } while (remaining && got >= 0 && socket.waitForReadyRead(Timeout));
+
+ if (got < 0)
+ return false;
+
+ if (block)
+ *block = uMsg;
+
+ return true;
+}
+
+
+QString BaselineProtocol::errorMessage()
+{
+ QString ret = errMsg;
+ if (socket.error() >= 0)
+ ret += QLatin1String(" Socket state: ") + socket.errorString();
+ return ret;
+}
diff --git a/tests/arthur/common/baselineprotocol.h b/tests/arthur/common/baselineprotocol.h
new file mode 100644
index 0000000..8740413
--- /dev/null
+++ b/tests/arthur/common/baselineprotocol.h
@@ -0,0 +1,76 @@
+#ifndef BASELINEPROTOCOL_H
+#define BASELINEPROTOCOL_H
+
+#include <QDataStream>
+#include <QTcpSocket>
+
+#define FileFormat "png"
+
+struct PlatformInfo
+{
+public:
+ PlatformInfo(bool useLocal = false);
+
+ QString buildKey;
+ QString qtVersion;
+ QString hostname;
+};
+
+
+
+class BaselineProtocol
+{
+public:
+ BaselineProtocol() {}
+ ~BaselineProtocol();
+
+ // ****************************************************
+ // Important constants here
+ // ****************************************************
+ enum Constant {
+ ProtocolVersion = 1,
+ ServerPort = 54129,
+ Timeout = 100000
+ };
+
+ enum Command {
+ UnknownError = 0,
+ // Queries
+ AcceptPlatformInfo = 1,
+ RequestBaseline = 2,
+ AcceptNewBaseline = 3,
+ AcceptMismatch = 4,
+ // Responses
+ Ack = 128,
+ AcceptBaseline = 129,
+ BaselineNotPresent = 130,
+ IgnoreCase = 131
+ };
+
+ // For client:
+ bool connect();
+ bool requestBaseline(const QString &caseId, Command *response, QImage *baseline);
+ bool submitNewBaseline(const QString &caseId, const QImage &baseline);
+ bool submitMismatch(const QString &caseId, const QImage &mismatch, QByteArray *failMsg);
+
+ // For server:
+ bool acceptConnection(PlatformInfo *pi);
+
+ QString errorMessage();
+
+private:
+ bool sendBlock(Command cmd, const QByteArray &block);
+ bool receiveBlock(Command *cmd, QByteArray *block);
+ QString errMsg;
+ QTcpSocket socket;
+
+ friend class BaselineThread;
+ friend class BaselineHandler;
+};
+
+
+QDataStream & operator<< (QDataStream &stream, const PlatformInfo &pinfo);
+
+QDataStream & operator>> (QDataStream& stream, PlatformInfo& pinfo);
+
+#endif // BASELINEPROTOCOL_H
diff --git a/tests/arthur/common/baselineprotocol.pri b/tests/arthur/common/baselineprotocol.pri
new file mode 100644
index 0000000..338339e
--- /dev/null
+++ b/tests/arthur/common/baselineprotocol.pri
@@ -0,0 +1,9 @@
+INCLUDEPATH += $$PWD
+
+QT *= network
+
+SOURCES += \
+ $$PWD/baselineprotocol.cpp
+
+HEADERS += \
+ $$PWD/baselineprotocol.h