summaryrefslogtreecommitdiffstats
path: root/tests/arthur
diff options
context:
space:
mode:
Diffstat (limited to 'tests/arthur')
-rw-r--r--tests/arthur/baselineserver/src/baselineserver.cpp174
-rw-r--r--tests/arthur/baselineserver/src/baselineserver.h11
-rw-r--r--tests/arthur/baselineserver/src/htmlpage.cpp44
-rw-r--r--tests/arthur/baselineserver/src/htmlpage.h4
-rw-r--r--tests/arthur/common/baselineprotocol.cpp51
-rw-r--r--tests/arthur/common/baselineprotocol.h8
6 files changed, 160 insertions, 132 deletions
diff --git a/tests/arthur/baselineserver/src/baselineserver.cpp b/tests/arthur/baselineserver/src/baselineserver.cpp
index 03d6499..7679f13 100644
--- a/tests/arthur/baselineserver/src/baselineserver.cpp
+++ b/tests/arthur/baselineserver/src/baselineserver.cpp
@@ -38,6 +38,10 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+
+#define QT_USE_FAST_CONCATENATION
+#define QT_USE_FAST_OPERATOR_PLUS
+
#include "baselineserver.h"
#include <QBuffer>
#include <QFile>
@@ -50,6 +54,7 @@
QString BaselineServer::storage;
+
BaselineServer::BaselineServer(QObject *parent)
: QTcpServer(parent)
{
@@ -63,11 +68,9 @@ BaselineServer::BaselineServer(QObject *parent)
QString BaselineServer::storagePath()
{
if (storage.isEmpty()) {
- QByteArray envDir = qgetenv("QT_LANCELOT_DIR");
- if (!envDir.isEmpty())
- storage = QLS(envDir.append('/'));
- else
- storage = QLS("/var/www/");
+ storage = QLS(qgetenv("QT_LANCELOT_DIR"));
+ if (storage.isEmpty())
+ storage = QLS("/var/www");
}
return storage;
}
@@ -147,7 +150,6 @@ void BaselineHandler::receiveRequest()
proto.socket.disconnectFromHost();
return;
}
- connectionEstablished = true;
QString logMsg;
foreach (QString key, plat.keys()) {
if (key != PI_HostName && key != PI_HostAddress)
@@ -155,6 +157,21 @@ void BaselineHandler::receiveRequest()
}
qDebug() << runId << logtime() << "Connection established with" << plat.value(PI_HostName)
<< "[" << qPrintable(plat.value(PI_HostAddress)) << "]" << logMsg;
+
+ // Filter on branch
+ QString branch = plat.value(PI_PulseGitBranch);
+ if (branch.isEmpty()) {
+ // Not run by Pulse, i.e. ad hoc run: Ok.
+ }
+ else if (branch != QLS("master-integration") || !plat.value(PI_GitCommit).contains(QLS("Merge branch 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into master-integration"))) {
+ qDebug() << runId << logtime() << "Did not pass branch/staging repo filter, disconnecting.";
+ proto.sendBlock(BaselineProtocol::Abort, QByteArray("This branch/staging repo is not assigned to be tested."));
+ proto.socket.disconnectFromHost();
+ return;
+ }
+
+ proto.sendBlock(BaselineProtocol::Ack, QByteArray());
+ connectionEstablished = true;
return;
}
@@ -206,9 +223,9 @@ void BaselineHandler::provideBaselineChecksums(const QByteArray &itemListBlock)
}
// Find and mark blacklisted items
+ QString context = pathForItem(itemList.at(0), true, false).section(QLC('/'), 0, -2);
if (itemList.count() > 0) {
- QString prefix = pathForItem(itemList.at(0), true).section(QLC('/'), 0, -2);
- QFile file(prefix + QLS("/.blacklist"));
+ QFile file(BaselineServer::storagePath() + QLC('/') + context + QLS("/BLACKLIST"));
if (file.open(QIODevice::ReadOnly)) {
QTextStream in(&file);
do {
@@ -227,7 +244,7 @@ void BaselineHandler::provideBaselineChecksums(const QByteArray &itemListBlock)
QDataStream ods(&block, QIODevice::WriteOnly);
ods << itemList;
proto.sendBlock(BaselineProtocol::Ack, block);
- report.start(BaselineServer::storagePath(), runId, plat, proto.socket.peerAddress().toString(), itemList);
+ report.start(BaselineServer::storagePath(), runId, plat, context, itemList);
}
@@ -278,34 +295,37 @@ void BaselineHandler::receiveDisconnect()
}
-QString BaselineHandler::itemSubPath(const QString &engine, const QString &format, bool isBaseline)
+void BaselineHandler::mapPlatformInfo()
{
- if (isBaseline)
- return QString(QLS("baselines_%1_%2/")).arg(engine, format);
- else
- return QString(QLS("mismatches_%1_%2/")).arg(engine, format);
+ mapped = plat;
+
+ // Map hostname
+ QString host = plat.value(PI_HostName).section(QLC('.'), 0, 0); // Filter away domain, if any
+ 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);
+ }
+ if (host.isEmpty())
+ host = QLS("unknownhost");
+ mapped.insert(PI_HostName, host);
+
+ // Map qmakespec
+ QString mkspec = plat.value(PI_QMakeSpec);
+ mapped.insert(PI_QMakeSpec, mkspec.replace(QLC('/'), QLC('_')));
+
+ // Map Qt version
+ QString ver = plat.value(PI_QtVersion);
+ mapped.insert(PI_QtVersion, ver.prepend(QLS("Qt-"))); //### TBD: remove patch version
}
QString BaselineHandler::pathForItem(const ImageItem &item, bool isBaseline, bool absolute)
{
- if (pathForRun.isNull()) {
- QString host = plat.value(PI_HostName).section(QLC('.'), 0, 0); // Filter away domain, if any
- if (host.isEmpty() || host == QLS("localhost")) {
- host = proto.socket.peerAddress().toString();
- if (host.isEmpty())
- host = QLS("Unknown");
- } else {
- host.replace(QRegExp(QLS("^(bq|oslo?)-(.*)$")), QLS("\\2"));
- host.replace(QRegExp(QLS("^(.*)-\\d+$")), QLS("vm-\\1"));
- }
- pathForRun = host + QLC('/');
- }
-
- QString storePath = pathForRun;
- if (isBaseline)
- storePath += itemSubPath(item.engineAsString(), item.formatAsString(), isBaseline);
- else
- storePath += itemSubPath(item.engineAsString(), item.formatAsString(), isBaseline) + runId + QLC('/');
+ if (mapped.isEmpty())
+ mapPlatformInfo();
QString itemName = item.scriptName;
if (itemName.contains(QLC('.')))
@@ -313,15 +333,26 @@ QString BaselineHandler::pathForItem(const ImageItem &item, bool isBaseline, boo
itemName.append(QLC('_'));
itemName.append(QString::number(item.scriptChecksum, 16).rightJustified(4, QLC('0')));
+ QStringList path;
if (absolute)
- storePath.prepend(BaselineServer::storagePath());
- return storePath + itemName + QLC('.');
+ path += BaselineServer::storagePath();
+ path += QLS(isBaseline ? "baselines" : "mismatches");
+ path += item.engineAsString() + QLC('_') + item.formatAsString();
+ path += mapped.value(PI_QtVersion);
+ path += mapped.value(PI_QMakeSpec);
+ path += mapped.value(PI_HostName);
+ if (!isBaseline)
+ path += runId;
+ path += itemName + QLC('.');
+
+ return path.join(QLS("/"));
}
QString BaselineHandler::updateAllBaselines(const QString &host, const QString &id,
const QString &engine, const QString &format)
{
+#if 0
QString basePath(BaselineServer::storagePath());
QString srcDir(basePath + host + QLC('/') + itemSubPath(engine, format, false) + id);
QString dstDir(basePath + host + QLC('/') + itemSubPath(engine, format));
@@ -352,12 +383,15 @@ QString BaselineHandler::updateAllBaselines(const QString &host, const QString &
"Command output: <pre>%2</pre>").arg(proc.errorString(), proc.readAll().constData());
return res;
+#else
+ return QString();
+#endif
}
QString BaselineHandler::updateSingleBaseline(const QString &oldBaseline, const QString &newBaseline)
{
QString res;
- QString basePath(BaselineServer::storagePath());
+ QString basePath(BaselineServer::storagePath() + QLC('/'));
QString srcBase(basePath + newBaseline.left(newBaseline.length() - 3));
QString dstDir(basePath + oldBaseline.left(oldBaseline.lastIndexOf(QLC('/'))));
@@ -374,53 +408,29 @@ QString BaselineHandler::updateSingleBaseline(const QString &oldBaseline, const
return res;
}
-QString BaselineHandler::blacklistTest(const QString &scriptName, const QString &host, const QString &engine,
- const QString &format)
+QString BaselineHandler::blacklistTest(const QString &context, const QString &itemId, bool removeFromBlacklist)
{
- QString configFile(BaselineServer::storagePath() + host + QLC('/')
- + itemSubPath(engine, format) + QLS(".blacklist"));
- QFile file(configFile);
- if (file.open(QIODevice::Append)) {
- QTextStream out(&file);
- out << scriptName << endl;
- return QLS("Blacklisted ") + scriptName;
+ QFile file(BaselineServer::storagePath() + QLC('/') + context + QLS("/BLACKLIST"));
+ QStringList blackList;
+ if (file.open(QIODevice::ReadWrite)) {
+ while (!file.atEnd())
+ blackList.append(file.readLine().trimmed());
+
+ if (removeFromBlacklist)
+ blackList.removeAll(itemId);
+ else if (!blackList.contains(itemId))
+ blackList.append(itemId);
+
+ file.resize(0);
+ foreach (QString id, blackList)
+ file.write(id.toLatin1() + '\n');
+ file.close();
+ return QLS(removeFromBlacklist ? "Whitelisted " : "Blacklisted ") + itemId + QLS(" in context ") + context;
} else {
- return QLS("Unable to update blacklisted tests.");
+ return QLS("Unable to update blacklisted tests, failed to open ") + file.fileName();
}
}
-QString BaselineHandler::whitelistTest(const QString &scriptName, const QString &host, const QString &engine,
- const QString &format)
-{
- QString configFile(BaselineServer::storagePath() + host + QLC('/')
- + itemSubPath(engine, format) + QLS(".blacklist"));
- QFile file(configFile);
- QStringList tests;
- if (file.open(QIODevice::ReadOnly)) {
- QTextStream in(&file);
- do {
- tests << in.readLine();
- } while (!in.atEnd());
- if (tests.count() != 0) {
- QMutableStringListIterator it(tests);
- while (it.hasNext()) {
- it.next();
- if (it.value() == scriptName)
- it.remove();
- }
- }
- file.close();
- if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- QTextStream out(&file);
- for (int i=0; i<tests.count(); ++i)
- out << tests.at(i);
- return QLS("Whitelisted ") + scriptName;
- } else {
- QLS("Unable to whitelist ") + scriptName + QLS(". Unable to truncate blacklist file.");
- }
- }
- return QLS("Unable to whitelist ") + scriptName + QLS(". Unable to open blacklist file.");
-}
void BaselineHandler::testPathMapping()
{
@@ -433,6 +443,9 @@ void BaselineHandler::testPathMapping()
<< QLS("osl-mac-master-6.test.qt.nokia.com")
<< QLS("sv-xp-vs-010")
<< QLS("sv-xp-vs-011")
+ << QLS("sv-solaris-sparc-008")
+ << QLS("macbuilder-02.test.troll.no")
+ << QLS("bqvm1164")
<< QLS("chimera")
<< QLS("localhost");
@@ -445,11 +458,12 @@ void BaselineHandler::testPathMapping()
plat.insert(PI_QtVersion, QLS("4.8.0"));
plat.insert(PI_BuildKey, QLS("(nobuildkey)"));
+ plat.insert(PI_QMakeSpec, "linux-g++");
foreach(const QString& host, hosts) {
- pathForRun = QString();
+ mapped.clear();
plat.insert(PI_HostName, host);
- qDebug() << "Baseline from" << host << "->" << pathForItem(item, true).remove(BaselineServer::storagePath());
- qDebug() << "Mismatch from" << host << "->" << pathForItem(item, false).remove(BaselineServer::storagePath());
+ qDebug() << "Baseline from" << host << "->" << pathForItem(item, true);
+ qDebug() << "Mismatch from" << host << "->" << pathForItem(item, false);
}
}
diff --git a/tests/arthur/baselineserver/src/baselineserver.h b/tests/arthur/baselineserver/src/baselineserver.h
index e311527..d49aedb 100644
--- a/tests/arthur/baselineserver/src/baselineserver.h
+++ b/tests/arthur/baselineserver/src/baselineserver.h
@@ -103,10 +103,7 @@ public:
static QString updateAllBaselines(const QString &host, const QString &id,
const QString &engine, const QString &format);
static QString updateSingleBaseline(const QString &oldBaseline, const QString &newBaseline);
- static QString blacklistTest(const QString &scriptName, const QString &host,
- const QString &engine, const QString &format);
- static QString whitelistTest(const QString &scriptName, const QString &host,
- const QString &engine, const QString &format);
+ static QString blacklistTest(const QString &context, const QString &itemId, bool removeFromBlacklist = false);
private slots:
void receiveRequest();
@@ -115,18 +112,16 @@ private slots:
private:
void provideBaselineChecksums(const QByteArray &itemListBlock);
void storeImage(const QByteArray &itemBlock, bool isBaseline);
+ void mapPlatformInfo();
QString pathForItem(const ImageItem &item, bool isBaseline = true, bool absolute = true);
const char *logtime();
QString computeMismatchScore(const QImage& baseline, const QImage& rendered);
- QString engineForItem(const ImageItem &item);
-
- static QString itemSubPath(const QString &engine, const QString &format, bool isBaseline = true);
BaselineProtocol proto;
PlatformInfo plat;
+ PlatformInfo mapped;
bool connectionEstablished;
QString runId;
- QString pathForRun;
HTMLPage report;
};
diff --git a/tests/arthur/baselineserver/src/htmlpage.cpp b/tests/arthur/baselineserver/src/htmlpage.cpp
index ad7f8b7..f75da88 100644
--- a/tests/arthur/baselineserver/src/htmlpage.cpp
+++ b/tests/arthur/baselineserver/src/htmlpage.cpp
@@ -60,14 +60,14 @@ QString HTMLPage::filePath()
return path;
}
-void HTMLPage::start(const QString &storagepath, const QString &runId, const PlatformInfo pinfo, const QString &hostAddress, const ImageItemList &itemList)
+void HTMLPage::start(const QString &storagepath, const QString &runId, const PlatformInfo pinfo, const QString &context, const ImageItemList &itemList)
{
end();
id = runId;
plat = pinfo;
- address = hostAddress;
- root = storagepath;
+ ctx = context;
+ root = storagepath + QLC('/');
imageItems = itemList;
QString dir = root + QLS("reports/");
QDir cwd;
@@ -132,16 +132,13 @@ void HTMLPage::addItem(const QString &baseline, const QString &rendered, const I
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=\"/cgi-bin/server.cgi?cmd=updateSingleBaseline&oldBaseline=" << baseline
- << "&newBaseline=" << rendered << "&url=" << pageUrl << "\">Update baseline</a><br>"
-#if 0
- "<a href=\"/cgi-bin/server.cgi?cmd=blacklist&scriptName=" << item.scriptName
- << "&host=" << plat.hostName << "&engine=" << item.engineAsString()
- << "&format=" << item.formatAsString()
- << "&url=" << pageUrl << "\">Blacklist test</a>"
-#endif
+
+ out << "<td><p><a href=\"/cgi-bin/server.cgi?cmd=updateSingleBaseline&oldBaseline=" << baseline
+ << "&newBaseline=" << rendered << "&url=" << pageUrl << "\">Replace baseline with rendered</a></p>"
+ << "<p><a href=\"/cgi-bin/server.cgi?cmd=blacklist&context=" << ctx
+ << "&itemId=" << item.scriptName << "&url=" << pageUrl << "\">Blacklist this item</a></p>"
<< "</td>\n";
- out << "</tr>\n\n";
+ out << "</tr>\n\n";
QMutableVectorIterator<ImageItem> it(imageItems);
while (it.hasNext()) {
@@ -162,13 +159,10 @@ void HTMLPage::end()
for (int i=0; i<imageItems.count(); ++i) {
out << "<tr><td>" << imageItems.at(i).scriptName << "</td><td>N/A</td><td>N/A</td><td>N/A</td><td>";
if (imageItems.at(i).status == ImageItem::IgnoreItem) {
- out << "<span style=\"background-color:yellow\">Blacklisted</span><br>"
- "<a href=\"/cgi-bin/server.cgi?cmd=whitelist&scriptName="
- << imageItems.at(i).scriptName << "&host=" << plat.value(PI_HostName)
- << "&engine=" << imageItems.at(i).engineAsString()
- << "&format=" << imageItems.at(i).formatAsString()
- << "&url=" << pageUrl
- << "\">Whitelist test</a>";
+ out << "<span style=\"background-color:yellow\">Blacklisted</span> "
+ << "<a href=\"/cgi-bin/server.cgi?cmd=whitelist&context=" << ctx
+ << "&itemId=" << imageItems.at(i).scriptName << "&url=" << pageUrl
+ << "\">Whitelist item</a>";
} else {
out << "<span style=\"color:green\">Test passed</span>";
}
@@ -220,16 +214,12 @@ void HTMLPage::handleCGIQuery(const QString &query)
cgiUrl.queryItemValue(QLS("format")));
} else if (command == QLS("blacklist")) {
// blacklist a test
- s << BaselineHandler::blacklistTest(cgiUrl.queryItemValue(QLS("scriptName")),
- cgiUrl.queryItemValue(QLS("host")),
- cgiUrl.queryItemValue(QLS("engine")),
- cgiUrl.queryItemValue(QLS("format")));
+ s << BaselineHandler::blacklistTest(cgiUrl.queryItemValue(QLS("context")),
+ cgiUrl.queryItemValue(QLS("itemId")));
} else if (command == QLS("whitelist")) {
// whitelist a test
- s << BaselineHandler::whitelistTest(cgiUrl.queryItemValue(QLS("scriptName")),
- cgiUrl.queryItemValue(QLS("host")),
- cgiUrl.queryItemValue(QLS("engine")),
- cgiUrl.queryItemValue(QLS("format")));
+ s << BaselineHandler::blacklistTest(cgiUrl.queryItemValue(QLS("context")),
+ cgiUrl.queryItemValue(QLS("itemId")), true);
} else {
s << "Unknown query:<br>" << query << "<br>";
}
diff --git a/tests/arthur/baselineserver/src/htmlpage.h b/tests/arthur/baselineserver/src/htmlpage.h
index bef6b55..fa4d1ed 100644
--- a/tests/arthur/baselineserver/src/htmlpage.h
+++ b/tests/arthur/baselineserver/src/htmlpage.h
@@ -51,7 +51,7 @@ public:
HTMLPage();
~HTMLPage();
- void start(const QString &storagePath, const QString &runId, const PlatformInfo pinfo, const QString &hostAddress, const ImageItemList &itemList);
+ void start(const QString &storagePath, const QString &runId, const PlatformInfo pinfo, const QString &context, const ImageItemList &itemList);
void addItem(const QString &baseline, const QString &rendered, const ImageItem &item);
void end();
QString filePath();
@@ -69,7 +69,7 @@ private:
QTextStream out;
QString id;
PlatformInfo plat;
- QString address;
+ QString ctx;
ImageItemList imageItems;
bool headerWritten;
};
diff --git a/tests/arthur/common/baselineprotocol.cpp b/tests/arthur/common/baselineprotocol.cpp
index 2a41104..6d26e9a 100644
--- a/tests/arthur/common/baselineprotocol.cpp
+++ b/tests/arthur/common/baselineprotocol.cpp
@@ -47,11 +47,28 @@
#include <QProcess>
#include <QFileInfo>
#include <QDir>
+#include <QTime>
#ifndef QMAKESPEC
#define QMAKESPEC "Unknown"
#endif
+#if defined(Q_OS_WIN)
+#include <QtCore/qt_windows.h>
+#endif
+#if defined(Q_OS_UNIX)
+#include <time.h>
+#endif
+void BaselineProtocol::sysSleep(int ms)
+{
+#if defined(Q_OS_WIN)
+ Sleep(DWORD(ms));
+#else
+ struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
+ nanosleep(&ts, NULL);
+#endif
+}
+
PlatformInfo::PlatformInfo(bool useLocal)
: QMap<QString, QString>()
{
@@ -141,12 +158,6 @@ quint64 ImageItem::computeChecksum(const QImage &image)
p += bpl;
}
}
- if (img.format() == QImage::Format_RGB32) { // Thank you, Haavard
- quint32 *p = (quint32 *)img.bits();
- const quint32 *end = p + (img.byteCount()/4);
- while (p<end)
- *p++ &= RGB_MASK;
- }
quint32 h1 = 0xfeedbacc;
quint32 h2 = 0x21604894;
@@ -221,7 +232,7 @@ BaselineProtocol::~BaselineProtocol()
}
-bool BaselineProtocol::connect()
+bool BaselineProtocol::connect(bool *dryrun)
{
errMsg.clear();
QByteArray serverName(qgetenv("QT_LANCELOT_SERVER"));
@@ -230,8 +241,11 @@ bool BaselineProtocol::connect()
socket.connectToHost(serverName, ServerPort);
if (!socket.waitForConnected(Timeout)) {
- errMsg += QLS("TCP connectToHost failed. Host:") + serverName + QLS(" port:") + QString::number(ServerPort);
- return false;
+ sysSleep(Timeout); // Wait a bit and try again, the server might just be restarting
+ if (!socket.waitForConnected(Timeout)) {
+ errMsg += QLS("TCP connectToHost failed. Host:") + serverName + QLS(" port:") + QString::number(ServerPort);
+ return false;
+ }
}
PlatformInfo pi(true);
@@ -243,12 +257,25 @@ bool BaselineProtocol::connect()
return false;
}
- Command cmd = Ack;
- if (!receiveBlock(&cmd, &block) || cmd != Ack) {
+ Command cmd = UnknownError;
+ if (!receiveBlock(&cmd, &block)) {
errMsg += QLS("Failed to get response from server.");
return false;
}
+ if (cmd == Abort) {
+ errMsg += QLS("Server aborted connection. Reason: ") + QString::fromLatin1(block);
+ return false;
+ }
+
+ if (dryrun)
+ *dryrun = (cmd == DoDryRun);
+
+ if (cmd != Ack && cmd != DoDryRun) {
+ errMsg += QLS("Unexpected response from server.");
+ return false;
+ }
+
return true;
}
@@ -268,8 +295,6 @@ bool BaselineProtocol::acceptConnection(PlatformInfo *pi)
pi->insert(PI_HostAddress, socket.peerAddress().toString());
}
- if (!sendBlock(Ack, QByteArray()))
- return false;
return true;
}
diff --git a/tests/arthur/common/baselineprotocol.h b/tests/arthur/common/baselineprotocol.h
index 162a19f..9f59454 100644
--- a/tests/arthur/common/baselineprotocol.h
+++ b/tests/arthur/common/baselineprotocol.h
@@ -123,7 +123,7 @@ public:
enum Constant {
ProtocolVersion = 2,
ServerPort = 54129,
- Timeout = 10000
+ Timeout = 5000
};
enum Command {
@@ -135,10 +135,12 @@ public:
AcceptMismatch = 5,
// Responses
Ack = 128,
+ Abort = 129,
+ DoDryRun = 130
};
// For client:
- bool connect();
+ bool connect(bool *dryrun = 0);
bool requestBaselineChecksums(ImageItemList *itemList);
bool submitNewBaseline(const ImageItem &item, QByteArray *serverMsg);
bool submitMismatch(const ImageItem &item, QByteArray *serverMsg);
@@ -153,6 +155,8 @@ private:
bool sendBlock(Command cmd, const QByteArray &block);
bool receiveBlock(Command *cmd, QByteArray *block);
+ void sysSleep(int ms);
+
QString errMsg;
QTcpSocket socket;