diff options
Diffstat (limited to 'tests/arthur')
-rw-r--r-- | tests/arthur/baselineserver/src/baselineserver.cpp | 59 | ||||
-rw-r--r-- | tests/arthur/baselineserver/src/baselineserver.h | 3 | ||||
-rw-r--r-- | tests/arthur/baselineserver/src/htmlpage.cpp | 51 | ||||
-rw-r--r-- | tests/arthur/baselineserver/src/htmlpage.h | 2 | ||||
-rw-r--r-- | tests/arthur/common/baselineprotocol.cpp | 47 | ||||
-rw-r--r-- | tests/arthur/common/baselineprotocol.h | 7 |
6 files changed, 103 insertions, 66 deletions
diff --git a/tests/arthur/baselineserver/src/baselineserver.cpp b/tests/arthur/baselineserver/src/baselineserver.cpp index 7679f13..0399224 100644 --- a/tests/arthur/baselineserver/src/baselineserver.cpp +++ b/tests/arthur/baselineserver/src/baselineserver.cpp @@ -51,6 +51,7 @@ #include <QHostInfo> #include <QTextStream> #include <QProcess> +#include <QDirIterator> QString BaselineServer::storage; @@ -97,8 +98,8 @@ void BaselineServer::heartbeat() if (me.lastModified() == meLastMod) return; - // (could close() here to avoid accepting new connections, to avoid livelock) - // also, could check for a timeout to force exit, to avoid hung threads blocking + //# (could close() here to avoid accepting new connections, to avoid livelock) + //# also, could check for a timeout to force exit, to avoid hung threads blocking bool isServing = false; foreach(BaselineThread *thread, findChildren<BaselineThread *>()) { if (thread->isRunning()) { @@ -304,10 +305,13 @@ void BaselineHandler::mapPlatformInfo() if (host.isEmpty() || host == QLS("localhost")) { host = plat.value(PI_HostAddress); } else { - // remove index postfix typical of vm hostnames - host.remove(QRegExp(QLS("\\d+$"))); - if (host.endsWith(QLC('-'))) - host.chop(1); + //# Site specific, should be in a config file + if (!host.startsWith(QLS("oldhcp"))) { + // remove index postfix typical of vm hostnames + host.remove(QRegExp(QLS("\\d+$"))); + if (host.endsWith(QLC('-'))) + host.chop(1); + } } if (host.isEmpty()) host = QLS("unknownhost"); @@ -349,43 +353,18 @@ QString BaselineHandler::pathForItem(const ImageItem &item, bool isBaseline, boo } -QString BaselineHandler::updateAllBaselines(const QString &host, const QString &id, - const QString &engine, const QString &format) +QString BaselineHandler::clearAllBaselines(const QString &context) { -#if 0 - QString basePath(BaselineServer::storagePath()); - QString srcDir(basePath + host + QLC('/') + itemSubPath(engine, format, false) + id); - QString dstDir(basePath + host + QLC('/') + itemSubPath(engine, format)); - - QDir dir(srcDir); - QStringList nameFilter; - nameFilter << "*.metadata" << "*.png"; - QStringList fileList = dir.entryList(nameFilter, QDir::Files | QDir::NoDotAndDotDot); - - // remove the generated _fuzzycompared.png and _compared.png files from the list - QMutableStringListIterator it(fileList); + int tot = 0; + int failed = 0; + QDirIterator it(BaselineServer::storagePath() + QLC('/') + context, + QStringList() << QLS("*.png") << QLS("*.metadata")); while (it.hasNext()) { - it.next(); - if (it.value().endsWith(QLS("compared.png"))) - it.remove(); + tot++; + if (!QFile::remove(it.next())) + failed++; } - - QString res; - QProcess proc; - proc.setWorkingDirectory(srcDir); - proc.setProcessChannelMode(QProcess::MergedChannels); - proc.start(QLS("cp"), QStringList() << QLS("-f") << fileList << dstDir); - proc.waitForFinished(); - if (proc.exitCode() == 0) - res = QLS("Successfully updated baseline for all failed tests."); - else - res = QString("Error updating baseline: %1<br>" - "Command output: <pre>%2</pre>").arg(proc.errorString(), proc.readAll().constData()); - - return res; -#else - return QString(); -#endif + return QString(QLS("%1 of %2 baselines cleared from context ")).arg((tot-failed)/2).arg(tot/2) + context; } QString BaselineHandler::updateSingleBaseline(const QString &oldBaseline, const QString &newBaseline) diff --git a/tests/arthur/baselineserver/src/baselineserver.h b/tests/arthur/baselineserver/src/baselineserver.h index d49aedb..c5cb45e 100644 --- a/tests/arthur/baselineserver/src/baselineserver.h +++ b/tests/arthur/baselineserver/src/baselineserver.h @@ -100,8 +100,7 @@ public: BaselineHandler(int socketDescriptor = -1); void testPathMapping(); - static QString updateAllBaselines(const QString &host, const QString &id, - const QString &engine, const QString &format); + static QString clearAllBaselines(const QString &context); static QString updateSingleBaseline(const QString &oldBaseline, const QString &newBaseline); static QString blacklistTest(const QString &context, const QString &itemId, bool removeFromBlacklist = false); diff --git a/tests/arthur/baselineserver/src/htmlpage.cpp b/tests/arthur/baselineserver/src/htmlpage.cpp index f75da88..9659505 100644 --- a/tests/arthur/baselineserver/src/htmlpage.cpp +++ b/tests/arthur/baselineserver/src/htmlpage.cpp @@ -69,7 +69,8 @@ void HTMLPage::start(const QString &storagepath, const QString &runId, const Pla ctx = context; root = storagepath + QLC('/'); imageItems = itemList; - QString dir = root + QLS("reports/"); + reportDir = pinfo.value(PI_PulseGitBranch).isEmpty() ? QLS("reports/adhoc/") : QLS("reports/pulse/"); + QString dir = root + reportDir; QDir cwd; if (!cwd.exists(dir)) cwd.mkpath(dir); @@ -78,7 +79,7 @@ void HTMLPage::start(const QString &storagepath, const QString &runId, const Pla void HTMLPage::writeHeader(const ImageItem &item) { - path = QLS("reports/") + id + QLC('_') + item.engineAsString() + path = reportDir + id + QLC('_') + item.engineAsString() + QLC('_') + item.formatAsString() + QLS(".html"); QString pageUrl = BaselineServer::baseUrl() + path; @@ -89,24 +90,21 @@ void HTMLPage::writeHeader(const ImageItem &item) out.setDevice(&file); out << "<html><body><h1>Lancelot results from run " << id << "</h1>\n\n"; - out << "<h3>Platform Info:</h3>\n"; + out << "<p><h3>Platform Info:</h3>\n"; out << "<table>\n"; foreach (QString key, plat.keys()) out << "<tr><td>" << key << "</td><td>" << plat.value(key) << "</td></tr>\n"; - out << "</table>\n"; - -#if 0 - out << "<h3><a href=\"/cgi-bin/server.cgi?cmd=updateAllBaselines&id="<< id << "&host=" << plat.hostName - << "&engine=" << item.engineAsString() << "&format=" << item.formatAsString() - << "&url=" << pageUrl - << "\">Update all baselines</a><br>"; -#endif - out << "<table border=\"2\">\n" + out << "</table></p>\n\n"; + + out << "<p><a href=\"/cgi-bin/server.cgi?cmd=clearAllBaselines&context=" << ctx << "&url=" << pageUrl + << "\"><b><big>Clear all baselines</big></b></a></h3> (They will be recreated by the next run)</p>\n\n"; + + out << "<p><table border=\"2\">\n" "<tr>\n" "<td><b>Script</b></td>\n" "<td><b>Baseline</b></td>\n" "<td><b>Rendered</b></td>\n" - "<td><b>Comparison</b></td>\n" + "<td><b>Comparison</b> (diffs are <span style=\"color:red\">RED</span>)</td>\n" "<td><b>Info/Action</b></td>\n" "</b></tr><br>"; } @@ -114,7 +112,7 @@ void HTMLPage::writeHeader(const ImageItem &item) void HTMLPage::writeFooter() { - out << "</table>\n</body></html>\n"; + out << "</table></p>\n</body></html>\n"; } @@ -131,7 +129,7 @@ void HTMLPage::addItem(const QString &baseline, const QString &rendered, const I out << "<td>" << item.scriptName << "</td>\n"; QStringList images = QStringList() << baseline << rendered << compared; foreach(const QString& img, images) - out << "<td><a href=\"/" << img << "\"><img src=\"/" << img << "\" width=240 height=240></a></td>\n"; + out << "<td><a href=\"/" << img << "\"><img src=\"/" << generateThumbnail(img) << "\" width=240 height=240></a></td>\n"; out << "<td><p><a href=\"/cgi-bin/server.cgi?cmd=updateSingleBaseline&oldBaseline=" << baseline << "&newBaseline=" << rendered << "&url=" << pageUrl << "\">Replace baseline with rendered</a></p>" @@ -193,6 +191,22 @@ QString HTMLPage::generateCompared(const QString &baseline, const QString &rende } +QString HTMLPage::generateThumbnail(const QString &image) +{ + QString res = image; + QFileInfo imgFI(root+image); + res.chop(imgFI.suffix().length() + 1); + res += QLS("_thumbnail.jpg"); + QFileInfo resFI(root+res); + if (resFI.exists() && resFI.lastModified() > imgFI.lastModified()) + return res; + QStringList args; + args << root+image << QLS("-resize") << QLS("240x240") << QLS("-quality") << QLS("50") << root+res; + QProcess::execute(QLS("convert"), args); + return res; +} + + void HTMLPage::handleCGIQuery(const QString &query) { QUrl cgiUrl(QLS("http://dummy/cgi-bin/dummy.cgi?") + query); @@ -207,11 +221,8 @@ void HTMLPage::handleCGIQuery(const QString &query) if (command == QLS("updateSingleBaseline")) { s << BaselineHandler::updateSingleBaseline(cgiUrl.queryItemValue(QLS("oldBaseline")), cgiUrl.queryItemValue(QLS("newBaseline"))); - } else if (command == QLS("updateAllBaselines")) { - s << BaselineHandler::updateAllBaselines(cgiUrl.queryItemValue(QLS("host")), - cgiUrl.queryItemValue(QLS("id")), - cgiUrl.queryItemValue(QLS("engine")), - cgiUrl.queryItemValue(QLS("format"))); + } else if (command == QLS("clearAllBaselines")) { + s << BaselineHandler::clearAllBaselines(cgiUrl.queryItemValue(QLS("context"))); } else if (command == QLS("blacklist")) { // blacklist a test s << BaselineHandler::blacklistTest(cgiUrl.queryItemValue(QLS("context")), diff --git a/tests/arthur/baselineserver/src/htmlpage.h b/tests/arthur/baselineserver/src/htmlpage.h index fa4d1ed..5f1e051 100644 --- a/tests/arthur/baselineserver/src/htmlpage.h +++ b/tests/arthur/baselineserver/src/htmlpage.h @@ -62,9 +62,11 @@ private: void writeHeader(const ImageItem &item); void writeFooter(); QString generateCompared(const QString &baseline, const QString &rendered, bool fuzzy = false); + QString generateThumbnail(const QString &image); QString root; QString path; + QString reportDir; QFile file; QTextStream out; QString id; diff --git a/tests/arthur/common/baselineprotocol.cpp b/tests/arthur/common/baselineprotocol.cpp index 6d26e9a..5ed58b4 100644 --- a/tests/arthur/common/baselineprotocol.cpp +++ b/tests/arthur/common/baselineprotocol.cpp @@ -206,10 +206,52 @@ QString ImageItem::formatAsString() const return QLS(formatNames[renderFormat]); } +void ImageItem::writeImageToStream(QDataStream &out) const +{ + if (image.isNull() || image.format() == QImage::Format_Invalid) { + out << quint8(0); + return; + } + out << quint8('Q') << quint8(image.format()); + out << quint8(QSysInfo::ByteOrder) << quint8(0); // pad to multiple of 4 bytes + out << quint32(image.width()) << quint32(image.height()) << quint32(image.bytesPerLine()); + out << qCompress((const uchar *)image.constBits(), image.byteCount()); + //# can be followed by colormap for formats that use it +} + +void ImageItem::readImageFromStream(QDataStream &in) +{ + quint8 hdr, fmt, endian, pad; + quint32 width, height, bpl; + QByteArray data; + + in >> hdr; + if (hdr != 'Q') { + image = QImage(); + return; + } + in >> fmt >> endian >> pad; + if (!fmt || fmt >= QImage::NImageFormats) { + image = QImage(); + return; + } + if (endian != QSysInfo::ByteOrder) { + qWarning("ImageItem cannot read streamed image with different endianness"); + image = QImage(); + return; + } + in >> width >> height >> bpl; + in >> data; + data = qUncompress(data); + QImage res((const uchar *)data.constData(), width, height, bpl, QImage::Format(fmt)); + image = res.copy(); //# yuck, seems there is currently no way to avoid data copy +} + QDataStream & operator<< (QDataStream &stream, const ImageItem &ii) { stream << ii.scriptName << ii.scriptChecksum << quint8(ii.status) << quint8(ii.renderFormat) - << quint8(ii.engine) << ii.image << ii.imageChecksums; + << quint8(ii.engine) << ii.imageChecksums; + ii.writeImageToStream(stream); return stream; } @@ -217,10 +259,11 @@ QDataStream & operator>> (QDataStream &stream, ImageItem &ii) { quint8 encFormat, encStatus, encEngine; stream >> ii.scriptName >> ii.scriptChecksum >> encStatus >> encFormat - >> encEngine >> ii.image >> ii.imageChecksums; + >> encEngine >> ii.imageChecksums; ii.renderFormat = QImage::Format(encFormat); ii.status = ImageItem::ItemStatus(encStatus); ii.engine = ImageItem::GraphicsEngine(encEngine); + ii.readImageFromStream(stream); return stream; } diff --git a/tests/arthur/common/baselineprotocol.h b/tests/arthur/common/baselineprotocol.h index 9f59454..baffb4a 100644 --- a/tests/arthur/common/baselineprotocol.h +++ b/tests/arthur/common/baselineprotocol.h @@ -84,6 +84,9 @@ public: QString engineAsString() const; QString formatAsString() const; + void writeImageToStream(QDataStream &stream) const; + void readImageFromStream(QDataStream &stream); + enum ItemStatus { Ok = 0, BaselineNotFound = 1, @@ -105,7 +108,7 @@ public: quint16 scriptChecksum; }; QDataStream & operator<< (QDataStream &stream, const ImageItem &ii); -QDataStream & operator>> (QDataStream& stream, ImageItem& ii); +QDataStream & operator>> (QDataStream &stream, ImageItem& ii); Q_DECLARE_METATYPE(ImageItem); @@ -121,7 +124,7 @@ public: // Important constants here // **************************************************** enum Constant { - ProtocolVersion = 2, + ProtocolVersion = 3, ServerPort = 54129, Timeout = 5000 }; |