From 0b63c90f5f4f5d1948e63c12f8b9b3395d316809 Mon Sep 17 00:00:00 2001 From: aavit Date: Fri, 19 Nov 2010 14:51:40 +0100 Subject: Added command to clear all baselines --- tests/arthur/baselineserver/src/baselineserver.cpp | 42 ++++------------------ tests/arthur/baselineserver/src/baselineserver.h | 3 +- tests/arthur/baselineserver/src/htmlpage.cpp | 26 ++++++-------- 3 files changed, 18 insertions(+), 53 deletions(-) diff --git a/tests/arthur/baselineserver/src/baselineserver.cpp b/tests/arthur/baselineserver/src/baselineserver.cpp index 7679f13..416b58f 100644 --- a/tests/arthur/baselineserver/src/baselineserver.cpp +++ b/tests/arthur/baselineserver/src/baselineserver.cpp @@ -51,6 +51,7 @@ #include #include #include +#include QString BaselineServer::storage; @@ -349,43 +350,14 @@ 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); - while (it.hasNext()) { - it.next(); - if (it.value().endsWith(QLS("compared.png"))) - it.remove(); - } + QDirIterator it(BaselineServer::storagePath() + QLC('/') + context, + QStringList() << QLS("*.png") << QLS("*.metadata")); + while (it.hasNext()) + QFile::remove(it.next()); - 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
" - "Command output:
%2
").arg(proc.errorString(), proc.readAll().constData()); - - return res; -#else - return QString(); -#endif + return QLS("All baselines cleared from context ") + 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..fdbdfb8 100644 --- a/tests/arthur/baselineserver/src/htmlpage.cpp +++ b/tests/arthur/baselineserver/src/htmlpage.cpp @@ -89,19 +89,16 @@ void HTMLPage::writeHeader(const ImageItem &item) out.setDevice(&file); out << "

Lancelot results from run " << id << "

\n\n"; - out << "

Platform Info:

\n"; + out << "

Platform Info:

\n"; out << "\n"; foreach (QString key, plat.keys()) out << "\n"; - out << "
" << key << "" << plat.value(key) << "
\n"; - -#if 0 - out << "

Update all baselines
"; -#endif - out << "\n" + out << "

\n\n"; + + out << "

Clear all baselines

(They will be recreated by the next run)

\n\n"; + + out << "

\n" "\n" "\n" "\n" @@ -114,7 +111,7 @@ void HTMLPage::writeHeader(const ImageItem &item) void HTMLPage::writeFooter() { - out << "
ScriptBaseline
\n\n"; + out << "

\n\n"; } @@ -207,11 +204,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")), -- cgit v0.12 From 779dd15d1297c99970fc63a290fca22a405c267f Mon Sep 17 00:00:00 2001 From: aavit Date: Mon, 22 Nov 2010 14:48:10 +0100 Subject: Add cmd to simulate testfail. Misc server improvements. --- tests/arthur/baselineserver/src/baselineserver.cpp | 27 +++++++++++++-------- tests/auto/lancelot/tst_lancelot.cpp | 28 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/tests/arthur/baselineserver/src/baselineserver.cpp b/tests/arthur/baselineserver/src/baselineserver.cpp index 416b58f..0399224 100644 --- a/tests/arthur/baselineserver/src/baselineserver.cpp +++ b/tests/arthur/baselineserver/src/baselineserver.cpp @@ -98,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()) { if (thread->isRunning()) { @@ -305,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"); @@ -352,12 +355,16 @@ QString BaselineHandler::pathForItem(const ImageItem &item, bool isBaseline, boo QString BaselineHandler::clearAllBaselines(const QString &context) { + int tot = 0; + int failed = 0; QDirIterator it(BaselineServer::storagePath() + QLC('/') + context, QStringList() << QLS("*.png") << QLS("*.metadata")); - while (it.hasNext()) - QFile::remove(it.next()); - - return QLS("All baselines cleared from context ") + context; + while (it.hasNext()) { + tot++; + if (!QFile::remove(it.next())) + failed++; + } + 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/auto/lancelot/tst_lancelot.cpp b/tests/auto/lancelot/tst_lancelot.cpp index 8467672..0c5d787 100644 --- a/tests/auto/lancelot/tst_lancelot.cpp +++ b/tests/auto/lancelot/tst_lancelot.cpp @@ -63,6 +63,8 @@ Q_OBJECT public: tst_Lancelot(); + static bool simfail; + private: ImageItem render(const ImageItem &item); void paint(QPaintDevice *device, const QStringList &script, const QString &filePath); @@ -91,6 +93,8 @@ private slots: #endif }; +bool tst_Lancelot::simfail = false; + tst_Lancelot::tst_Lancelot() { } @@ -290,12 +294,36 @@ void tst_Lancelot::paint(QPaintDevice *device, const QStringList &script, const { QPainter p(device); PaintCommands pcmd(script, 800, 800); + //pcmd.setShouldDrawText(false); pcmd.setType(ImageType); pcmd.setPainter(&p); pcmd.setFilePath(filePath); pcmd.runCommands(); + + if (simfail) { + p.drawLine(0, 0, 800, 800); + simfail = false; + } + p.end(); } +#define main rmain QTEST_MAIN(tst_Lancelot) +#undef main + +int main(int argc, char *argv[]) +{ + char *fargv[20]; + int fargc = 0; + for (int i = 0; i < qMin(argc, 19); i++) { + if (!qstrcmp(argv[i], "-simfail")) + tst_Lancelot::simfail = true; + else + fargv[fargc++] = argv[i]; + } + fargv[fargc] = 0; + return rmain(fargc, fargv); +} + #include "tst_lancelot.moc" -- cgit v0.12 From bc40961abdcdfb7cca8cfd7020d9ca32a3105735 Mon Sep 17 00:00:00 2001 From: aavit Date: Mon, 22 Nov 2010 15:28:38 +0100 Subject: Separate reports from adhoc and pulse runs --- tests/arthur/baselineserver/src/htmlpage.cpp | 5 +++-- tests/arthur/baselineserver/src/htmlpage.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/arthur/baselineserver/src/htmlpage.cpp b/tests/arthur/baselineserver/src/htmlpage.cpp index fdbdfb8..a4e9e0c 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; diff --git a/tests/arthur/baselineserver/src/htmlpage.h b/tests/arthur/baselineserver/src/htmlpage.h index fa4d1ed..f5e6e1c 100644 --- a/tests/arthur/baselineserver/src/htmlpage.h +++ b/tests/arthur/baselineserver/src/htmlpage.h @@ -65,6 +65,7 @@ private: QString root; QString path; + QString reportDir; QFile file; QTextStream out; QString id; -- cgit v0.12 From a1fd6c60455def34663c8a5621f21bab8fee9c21 Mon Sep 17 00:00:00 2001 From: aavit Date: Tue, 23 Nov 2010 11:52:09 +0100 Subject: Generate thumbnails for faster loading of the web reports --- tests/arthur/baselineserver/src/htmlpage.cpp | 20 ++++++++++++++++++-- tests/arthur/baselineserver/src/htmlpage.h | 1 + tests/auto/lancelot/tst_lancelot.cpp | 8 +++++--- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/tests/arthur/baselineserver/src/htmlpage.cpp b/tests/arthur/baselineserver/src/htmlpage.cpp index a4e9e0c..9659505 100644 --- a/tests/arthur/baselineserver/src/htmlpage.cpp +++ b/tests/arthur/baselineserver/src/htmlpage.cpp @@ -104,7 +104,7 @@ void HTMLPage::writeHeader(const ImageItem &item) "Script\n" "Baseline\n" "Rendered\n" - "Comparison\n" + "Comparison (diffs are RED)\n" "Info/Action\n" "
"; } @@ -129,7 +129,7 @@ void HTMLPage::addItem(const QString &baseline, const QString &rendered, const I out << "" << item.scriptName << "\n"; QStringList images = QStringList() << baseline << rendered << compared; foreach(const QString& img, images) - out << "\n"; + out << "\n"; out << "

Replace baseline with rendered

" @@ -191,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); diff --git a/tests/arthur/baselineserver/src/htmlpage.h b/tests/arthur/baselineserver/src/htmlpage.h index f5e6e1c..5f1e051 100644 --- a/tests/arthur/baselineserver/src/htmlpage.h +++ b/tests/arthur/baselineserver/src/htmlpage.h @@ -62,6 +62,7 @@ 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; diff --git a/tests/auto/lancelot/tst_lancelot.cpp b/tests/auto/lancelot/tst_lancelot.cpp index 0c5d787..7c6fe66 100644 --- a/tests/auto/lancelot/tst_lancelot.cpp +++ b/tests/auto/lancelot/tst_lancelot.cpp @@ -299,13 +299,15 @@ void tst_Lancelot::paint(QPaintDevice *device, const QStringList &script, const pcmd.setPainter(&p); pcmd.setFilePath(filePath); pcmd.runCommands(); + p.end(); if (simfail) { - p.drawLine(0, 0, 800, 800); + QPainter p2(device); + p2.setPen(QPen(QBrush(Qt::cyan), 3, Qt::DashLine)); + p2.drawLine(200, 200, 600, 600); + p2.drawLine(600, 200, 200, 600); simfail = false; } - - p.end(); } #define main rmain -- cgit v0.12 From d3ac35fdc0d5580946f886208e081634cbef6fbb Mon Sep 17 00:00:00 2001 From: aavit Date: Wed, 24 Nov 2010 15:01:42 +0100 Subject: Stream raw image data instead of PNG: more info, and faster. --- tests/arthur/common/baselineprotocol.cpp | 47 ++++++++++++++++++++++++++++++-- tests/arthur/common/baselineprotocol.h | 7 +++-- 2 files changed, 50 insertions(+), 4 deletions(-) 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 }; -- cgit v0.12