diff options
author | aavit <qt-info@nokia.com> | 2010-08-25 11:49:34 (GMT) |
---|---|---|
committer | aavit <qt-info@nokia.com> | 2010-08-25 11:49:34 (GMT) |
commit | deef2e16776c171d4b033257cd4fc3ab2bd005a3 (patch) | |
tree | 85ac87094fc690f71d20a6bd2989879b166992bf /tests/arthur/common | |
parent | dae23694cb89b853785a5772cc7e0477f65ac5bf (diff) | |
download | Qt-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.cpp | 219 | ||||
-rw-r--r-- | tests/arthur/common/baselineprotocol.h | 76 | ||||
-rw-r--r-- | tests/arthur/common/baselineprotocol.pri | 9 |
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 |