summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/arthur/baselineserver/src/baselineserver.cpp84
-rw-r--r--tests/arthur/baselineserver/src/baselineserver.h12
-rw-r--r--tests/arthur/baselineserver/src/baselineserver.pro4
-rw-r--r--tests/arthur/baselineserver/src/main.cpp2
-rw-r--r--tests/arthur/baselineserver/src/report.cpp (renamed from tests/arthur/baselineserver/src/htmlpage.cpp)228
-rw-r--r--tests/arthur/baselineserver/src/report.h (renamed from tests/arthur/baselineserver/src/htmlpage.h)45
-rw-r--r--tests/arthur/common/baselineprotocol.cpp5
-rw-r--r--tests/arthur/common/baselineprotocol.h12
-rw-r--r--tests/arthur/common/qbaselinetest.cpp124
-rw-r--r--tests/arthur/common/qbaselinetest.h64
-rw-r--r--tests/arthur/common/qbaselinetest.pri13
-rw-r--r--tests/auto/baselineexample/baselineexample.pro18
-rw-r--r--tests/auto/baselineexample/tst_baselineexample.cpp158
-rw-r--r--tests/auto/lancelot/lancelot.pro5
-rw-r--r--tests/auto/lancelot/tst_lancelot.cpp2
15 files changed, 616 insertions, 160 deletions
diff --git a/tests/arthur/baselineserver/src/baselineserver.cpp b/tests/arthur/baselineserver/src/baselineserver.cpp
index 90eb594..6351dff 100644
--- a/tests/arthur/baselineserver/src/baselineserver.cpp
+++ b/tests/arthur/baselineserver/src/baselineserver.cpp
@@ -145,36 +145,43 @@ const char *BaselineHandler::logtime()
//return QTime::currentTime().toString(QLS("mm:ss.zzz"));
}
-void BaselineHandler::receiveRequest()
+bool BaselineHandler::establishConnection()
{
- if (!connectionEstablished) {
- if (!proto.acceptConnection(&plat)) {
- qWarning() << runId << logtime() << "Accepting new connection from" << proto.socket.peerAddress().toString() << "failed." << proto.errorMessage();
- proto.socket.disconnectFromHost();
- return;
- }
- QString logMsg;
- foreach (QString key, plat.keys()) {
- if (key != PI_HostName && key != PI_HostAddress)
- logMsg += key + QLS(": '") + plat.value(key) + QLS("', ");
- }
- qDebug() << runId << logtime() << "Connection established with" << plat.value(PI_HostName)
- << "[" << qPrintable(plat.value(PI_HostAddress)) << "]" << logMsg;
+ if (!proto.acceptConnection(&plat)) {
+ qWarning() << runId << logtime() << "Accepting new connection from" << proto.socket.peerAddress().toString() << "failed." << proto.errorMessage();
+ proto.socket.disconnectFromHost();
+ return false;
+ }
+ QString logMsg;
+ foreach (QString key, plat.keys()) {
+ if (key != PI_HostName && key != PI_HostAddress)
+ logMsg += key + QLS(": '") + plat.value(key) + QLS("', ");
+ }
+ 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;
- }
+ // 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 false;
+ }
+
+ proto.sendBlock(BaselineProtocol::Ack, QByteArray());
+
+ report.init(this, runId, plat);
+ return true;
+}
- proto.sendBlock(BaselineProtocol::Ack, QByteArray());
- connectionEstablished = true;
+void BaselineHandler::receiveRequest()
+{
+ if (!connectionEstablished) {
+ connectionEstablished = establishConnection();
return;
}
@@ -247,7 +254,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, context, itemList);
+ report.addItems(itemList);
}
@@ -274,19 +281,15 @@ void BaselineHandler::storeImage(const QByteArray &itemBlock, bool isBaseline)
file.close();
if (!isBaseline)
- report.addItem(pathForItem(item, true, false) + QLS(FileFormat),
- pathForItem(item, false, false) + QLS(FileFormat),
- item);
+ report.addMismatch(item);
- QByteArray msg(isBaseline ? "New baseline image stored: " :
- "Mismatch report: " );
- msg += BaselineServer::baseUrl();
+ QString msg;
if (isBaseline)
- msg += pathForItem(item, true, false).toLatin1() + FileFormat;
+ msg = QLS("New baseline image stored: ") + pathForItem(item, true, true) + QLS(FileFormat);
else
- msg += report.filePath();
+ msg = BaselineServer::baseUrl() + report.filePath();
- proto.sendBlock(BaselineProtocol::Ack, msg);
+ proto.sendBlock(BaselineProtocol::Ack, msg.toLatin1());
}
@@ -298,7 +301,7 @@ void BaselineHandler::receiveDisconnect()
}
-void BaselineHandler::mapPlatformInfo()
+void BaselineHandler::mapPlatformInfo() const
{
mapped = plat;
@@ -328,12 +331,13 @@ void BaselineHandler::mapPlatformInfo()
mapped.insert(PI_QtVersion, ver.prepend(QLS("Qt-"))); //### TBD: remove patch version
}
-QString BaselineHandler::pathForItem(const ImageItem &item, bool isBaseline, bool absolute)
+QString BaselineHandler::pathForItem(const ImageItem &item, bool isBaseline, bool absolute) const
{
if (mapped.isEmpty())
mapPlatformInfo();
- QString itemName = item.itemName;
+ QString itemName = item.itemName.simplified();
+ itemName.replace(QLC(' '), QLC('_'));
itemName.replace(QLC('.'), QLC('_'));
itemName.append(QLC('_'));
itemName.append(QString::number(item.itemChecksum, 16).rightJustified(4, QLC('0')));
diff --git a/tests/arthur/baselineserver/src/baselineserver.h b/tests/arthur/baselineserver/src/baselineserver.h
index 346ce1f..e09a9d0 100644
--- a/tests/arthur/baselineserver/src/baselineserver.h
+++ b/tests/arthur/baselineserver/src/baselineserver.h
@@ -50,7 +50,7 @@
#include <QDateTime>
#include "baselineprotocol.h"
-#include "htmlpage.h"
+#include "report.h"
// #seconds between update checks
#define HEARTBEAT 10
@@ -99,7 +99,9 @@ class BaselineHandler : public QObject
public:
BaselineHandler(int socketDescriptor = -1);
void testPathMapping();
+ QString pathForItem(const ImageItem &item, bool isBaseline = true, bool absolute = true) const;
+ // CGI callbacks:
static QString view(const QString &baseline, const QString &rendered, const QString &compared);
static QString clearAllBaselines(const QString &context);
static QString updateSingleBaseline(const QString &oldBaseline, const QString &newBaseline);
@@ -110,19 +112,19 @@ private slots:
void receiveDisconnect();
private:
+ bool establishConnection();
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);
+ void mapPlatformInfo() const;
const char *logtime();
QString computeMismatchScore(const QImage& baseline, const QImage& rendered);
BaselineProtocol proto;
PlatformInfo plat;
- PlatformInfo mapped;
+ mutable PlatformInfo mapped;
bool connectionEstablished;
QString runId;
- HTMLPage report;
+ Report report;
};
#endif // BASELINESERVER_H
diff --git a/tests/arthur/baselineserver/src/baselineserver.pro b/tests/arthur/baselineserver/src/baselineserver.pro
index defa05a..770662b 100644
--- a/tests/arthur/baselineserver/src/baselineserver.pro
+++ b/tests/arthur/baselineserver/src/baselineserver.pro
@@ -20,11 +20,11 @@ include(../../common/baselineprotocol.pri)
SOURCES += main.cpp \
baselineserver.cpp \
- htmlpage.cpp
+ report.cpp
HEADERS += \
baselineserver.h \
- htmlpage.h
+ report.h
RESOURCES += \
baselineserver.qrc
diff --git a/tests/arthur/baselineserver/src/main.cpp b/tests/arthur/baselineserver/src/main.cpp
index a5ec4db..bf41f41 100644
--- a/tests/arthur/baselineserver/src/main.cpp
+++ b/tests/arthur/baselineserver/src/main.cpp
@@ -48,7 +48,7 @@ int main(int argc, char *argv[])
QString queryString(qgetenv("QUERY_STRING"));
if (!queryString.isEmpty()) {
// run as CGI script
- HTMLPage::handleCGIQuery(queryString);
+ Report::handleCGIQuery(queryString);
return 0;
}
diff --git a/tests/arthur/baselineserver/src/htmlpage.cpp b/tests/arthur/baselineserver/src/report.cpp
index 2b16d25..f5bb418 100644
--- a/tests/arthur/baselineserver/src/htmlpage.cpp
+++ b/tests/arthur/baselineserver/src/report.cpp
@@ -38,147 +38,199 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#include "htmlpage.h"
+#include "report.h"
#include "baselineprotocol.h"
#include "baselineserver.h"
#include <QDir>
#include <QProcess>
#include <QUrl>
-HTMLPage::HTMLPage()
- : headerWritten(false)
+Report::Report()
+ : written(false), numItems(0), numMismatches(0)
{
}
-HTMLPage::~HTMLPage()
+Report::~Report()
{
end();
}
-QString HTMLPage::filePath()
+QString Report::filePath()
{
return path;
}
-void HTMLPage::start(const QString &storagepath, const QString &runId, const PlatformInfo pinfo, const QString &context, const ImageItemList &itemList)
+void Report::init(const BaselineHandler *h, const QString &r, const PlatformInfo &p)
{
- end();
-
- id = runId;
- plat = pinfo;
- ctx = context;
- root = storagepath + QLC('/');
- imageItems = itemList;
- reportDir = pinfo.value(PI_TestCase) + QLC('/') + (pinfo.value(PI_PulseGitBranch).isEmpty() ? QLS("reports/adhoc/") : QLS("reports/pulse/"));
- QString dir = root + reportDir;
+ handler = h;
+ runId = r;
+ plat = p;
+ rootDir = BaselineServer::storagePath() + QLC('/');
+ reportDir = plat.value(PI_TestCase) + QLC('/') + (plat.value(PI_PulseGitBranch).isEmpty() ? QLS("reports/adhoc/") : QLS("reports/pulse/"));
+ QString dir = rootDir + reportDir;
QDir cwd;
if (!cwd.exists(dir))
cwd.mkpath(dir);
+ path = reportDir + QLS("Report_") + runId + QLS(".html");
}
+void Report::addItems(const ImageItemList &items)
+{
+ if (items.isEmpty())
+ return;
+ numItems += items.size();
+ QString func = items.at(0).testFunction;
+ if (!testFunctions.contains(func))
+ testFunctions.append(func);
+ itemLists[func] += items;
+}
-void HTMLPage::writeHeader(const ImageItem &item)
+void Report::addMismatch(const ImageItem &item)
{
- path = reportDir + id + QLC('_') + item.testFunction + QLS(".html");
+ if (!testFunctions.contains(item.testFunction)) {
+ qWarning() << "Report::addMismatch: unknown testfunction" << item.testFunction;
+ return;
+ }
+ bool found = false;
+ ImageItemList &list = itemLists[item.testFunction];
+ for (ImageItemList::iterator it = list.begin(); it != list.end(); ++it) {
+ if (it->itemName == item.itemName && it->itemChecksum == item.itemChecksum) {
+ it->status = ImageItem::Mismatch;
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ numMismatches++;
+ else
+ qWarning() << "Report::addMismatch: unknown item" << item.itemName << "in testfunction" << item.testFunction;
+}
- QString pageUrl = BaselineServer::baseUrl() + path;
+void Report::end()
+{
+ if (written || !numMismatches)
+ return;
+ write();
+ written = true;
+}
- file.setFileName(root + path);
- if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
+
+void Report::write()
+{
+ QFile file(rootDir + path);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qWarning() << "Failed to open report file" << file.fileName();
+ return;
+ }
out.setDevice(&file);
- out << "<html><body><h1>Lancelot results from run " << id << "</h1>\n\n";
- out << "<p><h3>Platform Info:</h3>\n";
- out << "<table>\n";
+ writeHeader();
+ foreach(const QString &func, testFunctions) {
+ writeFunctionResults(itemLists.value(func));
+ }
+ writeFooter();
+ file.close();
+}
+
+
+void Report::writeHeader()
+{
+ QString title = plat.value(PI_TestCase) + QLS(" Qt Baseline Test Report");
+ out << "<head><title>" << title << "</title></head>\n"
+ << "<html><body><h1>" << title << "</h1>\n"
+ << "<p>Run Id: <b>" << runId << "</b></p>\n"
+ << "<p>Summary: <b>" << numMismatches << " of " << numItems << "</b> items reported mismatching</p>\n\n";
+ out << "<h3>Platform Info:</h3>\n"
+ << "<table>\n";
foreach (QString key, plat.keys())
out << "<tr><td>" << key << "</td><td>" << plat.value(key) << "</td></tr>\n";
- out << "</table></p>\n\n";
+ out << "</table>\n\n";
+}
+
+
+void Report::writeFunctionResults(const ImageItemList &list)
+{
+ QString testFunction = list.at(0).testFunction;
+ QString pageUrl = BaselineServer::baseUrl() + path;
+ QString ctx = handler->pathForItem(list.at(0), true, false).section(QLC('/'), 0, -2);
+ out << "\n<p>&nbsp;</p><h3>Test function: " << testFunction << "</h3>\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"
+ out << "<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> (diffs are <span style=\"color:red\">RED</span>)</td>\n"
- "<td><b>Info/Action</b></td>\n"
- "</b></tr><br>";
-}
+ "<th width=123>Item</th>\n"
+ "<th width=246>Baseline</th>\n"
+ "<th width=246>Rendered</th>\n"
+ "<th width=246>Comparison (diffs are <span style=\"color:red\">RED</span>)</th>\n"
+ "<th width=246>Info/Action</th>\n"
+ "</tr>\n\n";
+ foreach (const ImageItem &item, list) {
+ out << "<tr>\n";
+ out << "<td>" << item.itemName << "</td>\n";
+ QString baseline = handler->pathForItem(item, true, false) + QLS(FileFormat);
+ if (item.status == ImageItem::Mismatch) {
+ QString rendered = handler->pathForItem(item, false, false) + QLS(FileFormat);
+ writeItem(baseline, rendered, item, ctx);
+ }
+ else {
+ out << "<td align=center><a href=\"/" << baseline << "\">view</a></td>\n"
+ << "<td align=center colspan=2><small>n/a</small></td>\n"
+ << "<td align=center>";
+ switch (item.status) {
+ case ImageItem::BaselineNotFound:
+ out << "Baseline not found/regenerated";
+ break;
+ case ImageItem::IgnoreItem:
+ out << "<span style=\"background-color:yellow\">Blacklisted</span> "
+ << "<a href=\"/cgi-bin/server.cgi?cmd=whitelist&context=" << ctx
+ << "&itemId=" << item.itemName << "&url=" << pageUrl
+ << "\">Whitelist this item</a>";
+ break;
+ case ImageItem::Ok:
+ out << "<span style=\"color:green\"><small>No mismatch reported</small></span>";
+ break;
+ default:
+ out << "?";
+ break;
+ }
+ out << "</td>\n";
+ }
+ out << "</tr>\n\n";
+ }
-void HTMLPage::writeFooter()
-{
- out << "</table></p>\n</body></html>\n";
+ out << "</table>\n";
}
-
-void HTMLPage::addItem(const QString &baseline, const QString &rendered, const ImageItem &item)
+void Report::writeItem(const QString &baseline, const QString &rendered, const ImageItem &item, const QString &ctx)
{
- if (!headerWritten) {
- writeHeader(item);
- headerWritten = true;
- }
QString compared = generateCompared(baseline, rendered);
QString pageUrl = BaselineServer::baseUrl() + path;
- out << "<tr>\n";
- out << "<td>" << item.itemName << "</td>\n";
QStringList images = QStringList() << baseline << rendered << compared;
- foreach(const QString& img, images)
- out << "<td><a href=\"/" << img << "\"><img src=\"/" << generateThumbnail(img) << "\" width=240 height=240></a></td>\n";
+ foreach (const QString& img, images)
+ out << "<td height=246 align=center><a href=\"/" << img << "\"><img src=\"/" << generateThumbnail(img) << "\"></a></td>\n";
- out << "<td>\n"
+ out << "<td align=center>\n"
+ << "<p><span style=\"color:red\">Mismatch reported</span></p>\n"
<< "<p><a href=\"/cgi-bin/server.cgi?cmd=updateSingleBaseline&oldBaseline=" << baseline
<< "&newBaseline=" << rendered << "&url=" << pageUrl << "\">Replace baseline with rendered</a></p>\n"
<< "<p><a href=\"/cgi-bin/server.cgi?cmd=blacklist&context=" << ctx
<< "&itemId=" << item.itemName << "&url=" << pageUrl << "\">Blacklist this item</a></p>\n"
<< "<p><a href=\"/cgi-bin/server.cgi?cmd=view&baseline=" << baseline << "&rendered=" << rendered
- << "&compared=" << compared << "&url=" << pageUrl << "\">View</a></p>\n"
+ << "&compared=" << compared << "&url=" << pageUrl << "\">Inspect</a></p>\n"
<< "</td>\n";
- out << "</tr>\n\n";
-
- QMutableVectorIterator<ImageItem> it(imageItems);
- while (it.hasNext()) {
- it.next();
- if (it.value().itemName == item.itemName) {
- it.remove();
- break;
- }
- }
}
-
-void HTMLPage::end()
+void Report::writeFooter()
{
- if (file.isOpen()) {
- // Add the names of the scripts that passed the test, or were blacklisted
- QString pageUrl = BaselineServer::baseUrl() + path;
- for (int i=0; i<imageItems.count(); ++i) {
- out << "<tr><td>" << imageItems.at(i).itemName << "</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> "
- << "<a href=\"/cgi-bin/server.cgi?cmd=whitelist&context=" << ctx
- << "&itemId=" << imageItems.at(i).itemName << "&url=" << pageUrl
- << "\">Whitelist item</a>";
- } else {
- out << "<span style=\"color:green\">Test passed</span>";
- }
- out << "</td></tr>\n";
- }
-
- writeFooter();
- out.flush();
- file.close();
- path.clear();
- headerWritten = false;
- }
+ out << "\n</body></html>\n";
}
-QString HTMLPage::generateCompared(const QString &baseline, const QString &rendered, bool fuzzy)
+QString Report::generateCompared(const QString &baseline, const QString &rendered, bool fuzzy)
{
QString res = rendered;
QFileInfo fi(res);
@@ -187,29 +239,29 @@ QString HTMLPage::generateCompared(const QString &baseline, const QString &rende
QStringList args;
if (fuzzy)
args << QLS("-fuzz") << QLS("5%");
- args << root+baseline << root+rendered << root+res;
+ args << rootDir+baseline << rootDir+rendered << rootDir+res;
QProcess::execute(QLS("compare"), args);
return res;
}
-QString HTMLPage::generateThumbnail(const QString &image)
+QString Report::generateThumbnail(const QString &image)
{
QString res = image;
- QFileInfo imgFI(root+image);
+ QFileInfo imgFI(rootDir+image);
res.chop(imgFI.suffix().length() + 1);
res += QLS("_thumbnail.jpg");
- QFileInfo resFI(root+res);
+ QFileInfo resFI(rootDir+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;
+ args << rootDir+image << QLS("-resize") << QLS("240x240>") << QLS("-quality") << QLS("50") << rootDir+res;
QProcess::execute(QLS("convert"), args);
return res;
}
-void HTMLPage::handleCGIQuery(const QString &query)
+void Report::handleCGIQuery(const QString &query)
{
QUrl cgiUrl(QLS("http://dummy/cgi-bin/dummy.cgi?") + query);
QTextStream s(stdout);
diff --git a/tests/arthur/baselineserver/src/htmlpage.h b/tests/arthur/baselineserver/src/report.h
index 5f1e051..0df613a 100644
--- a/tests/arthur/baselineserver/src/htmlpage.h
+++ b/tests/arthur/baselineserver/src/report.h
@@ -38,42 +38,53 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef HTMLPAGE_H
-#define HTMLPAGE_H
+#ifndef REPORT_H
+#define REPORT_H
#include "baselineprotocol.h"
#include <QFile>
#include <QTextStream>
+#include <QMap>
+#include <QStringList>
-class HTMLPage
+class BaselineHandler;
+
+class Report
{
public:
- HTMLPage();
- ~HTMLPage();
+ Report();
+ ~Report();
- 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 init(const BaselineHandler *h, const QString &r, const PlatformInfo &p);
+ void addItems(const ImageItemList& items);
+ void addMismatch(const ImageItem& item);
void end();
+
QString filePath();
static void handleCGIQuery(const QString &query);
private:
- void writeHeader(const ImageItem &item);
+ void write();
+ void writeFunctionResults(const ImageItemList &list);
+ void writeItem(const QString &baseline, const QString &rendered, const ImageItem &item, const QString &ctx);
+ void writeHeader();
void writeFooter();
QString generateCompared(const QString &baseline, const QString &rendered, bool fuzzy = false);
QString generateThumbnail(const QString &image);
- QString root;
- QString path;
+ const BaselineHandler *handler;
+ QString runId;
+ PlatformInfo plat;
+ QString rootDir;
QString reportDir;
- QFile file;
+ QString path;
+ QStringList testFunctions;
+ QMap<QString, ImageItemList> itemLists;
+ bool written;
+ int numItems;
+ int numMismatches;
QTextStream out;
- QString id;
- PlatformInfo plat;
- QString ctx;
- ImageItemList imageItems;
- bool headerWritten;
};
-#endif // HTMLPAGE_H
+#endif // REPORT_H
diff --git a/tests/arthur/common/baselineprotocol.cpp b/tests/arthur/common/baselineprotocol.cpp
index c7e9e72..e4445bd 100644
--- a/tests/arthur/common/baselineprotocol.cpp
+++ b/tests/arthur/common/baselineprotocol.cpp
@@ -48,6 +48,7 @@
#include <QFileInfo>
#include <QDir>
#include <QTime>
+#include <QPointer>
#ifndef QMAKESPEC
#define QMAKESPEC "Unknown"
@@ -264,6 +265,10 @@ QDataStream & operator>> (QDataStream &stream, ImageItem &ii)
return stream;
}
+BaselineProtocol::BaselineProtocol()
+{
+}
+
BaselineProtocol::~BaselineProtocol()
{
socket.close();
diff --git a/tests/arthur/common/baselineprotocol.h b/tests/arthur/common/baselineprotocol.h
index 1f4d593..2315bc3 100644
--- a/tests/arthur/common/baselineprotocol.h
+++ b/tests/arthur/common/baselineprotocol.h
@@ -38,6 +38,7 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+
#ifndef BASELINEPROTOCOL_H
#define BASELINEPROTOCOL_H
@@ -46,6 +47,7 @@
#include <QImage>
#include <QVector>
#include <QMap>
+#include <QPointer>
#define QLS QLatin1String
#define QLC QLatin1Char
@@ -87,7 +89,8 @@ public:
enum ItemStatus {
Ok = 0,
BaselineNotFound = 1,
- IgnoreItem = 2
+ IgnoreItem = 2,
+ Mismatch = 3
};
QString testFunction;
@@ -107,12 +110,15 @@ Q_DECLARE_METATYPE(ImageItem);
typedef QVector<ImageItem> ImageItemList;
+
class BaselineProtocol
{
public:
- BaselineProtocol() {}
+ BaselineProtocol();
~BaselineProtocol();
+ static BaselineProtocol *instance(QObject *parent = 0);
+
// ****************************************************
// Important constants here
// ****************************************************
@@ -136,6 +142,8 @@ public:
};
// For client:
+
+ // For advanced client:
bool connect(const QString &testCase, bool *dryrun = 0);
bool requestBaselineChecksums(const QString &testFunction, ImageItemList *itemList);
bool submitNewBaseline(const ImageItem &item, QByteArray *serverMsg);
diff --git a/tests/arthur/common/qbaselinetest.cpp b/tests/arthur/common/qbaselinetest.cpp
new file mode 100644
index 0000000..e95b510
--- /dev/null
+++ b/tests/arthur/common/qbaselinetest.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbaselinetest.h"
+#include "baselineprotocol.h"
+
+namespace QBaselineTest {
+
+bool connected = false;
+bool triedConnecting = false;
+BaselineProtocol proto;
+
+
+bool checkImage(const QImage& img, const char *name, quint16 checksum, QByteArray *msg, bool *error)
+{
+ QByteArray itemName;
+ bool hasName = qstrlen(name);
+ const char *tag = QTest::currentDataTag();
+ if (qstrlen(tag)) {
+ itemName = tag;
+ if (hasName)
+ itemName.append('_').append(name);
+ } else {
+ itemName = hasName ? name : "default_name";
+ }
+
+ *msg = "Baseline check of image '" + itemName + "': ";
+
+ if (!triedConnecting) {
+ triedConnecting = true;
+ if (!proto.connect(QTest::testObject()->metaObject()->className())) {
+ *msg += "Failed to connect to baseline server: " + proto.errorMessage().toLatin1();
+ *error = true;
+ return true;
+ }
+ connected = true;
+ }
+ if (!connected) {
+ *msg = "Not connected to baseline server.";
+ *error = true;
+ return true;
+ }
+
+ ImageItem item;
+ item.itemName = QLatin1String(itemName);
+ item.itemChecksum = checksum;
+ item.testFunction = QLatin1String(QTest::currentTestFunction());
+ ImageItemList list;
+ list.append(item);
+ if (!proto.requestBaselineChecksums(QLatin1String(QTest::currentTestFunction()), &list) || list.isEmpty()) {
+ *msg = "Communication with baseline server failed: " + proto.errorMessage().toLatin1();
+ *error = true;
+ return true;
+ }
+ item.image = img;
+ item.imageChecksums.prepend(ImageItem::computeChecksum(img));
+ QByteArray srvMsg;
+ switch (list.at(0).status) {
+ case ImageItem::IgnoreItem :
+ qDebug() << msg->constData() << "Ignored, blacklisted on server.";
+ return true;
+ break;
+ case ImageItem::BaselineNotFound:
+ if (proto.submitNewBaseline(item, &srvMsg))
+ qDebug() << msg->constData() << "Baseline not found on server. New baseline uploaded.";
+ else
+ qDebug() << msg->constData() << "Baseline not found on server. Uploading of new baseline failed:" << srvMsg;
+ return true;
+ break;
+ case ImageItem::Ok:
+ break;
+ default:
+ qWarning() << "Unexpected reply from baseline server.";
+ return true;
+ break;
+ }
+ *error = false;
+ // The actual comparison of the given image with the baseline:
+ if (list.at(0).imageChecksums.contains(item.imageChecksums.at(0)))
+ return true;
+ proto.submitMismatch(item, &srvMsg);
+ *msg += "Mismatch. See report:\n " + srvMsg;
+ return false;
+}
+
+}
diff --git a/tests/arthur/common/qbaselinetest.h b/tests/arthur/common/qbaselinetest.h
new file mode 100644
index 0000000..3445c72
--- /dev/null
+++ b/tests/arthur/common/qbaselinetest.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BASELINETEST_H
+#define BASELINETEST_H
+
+#include <QTest>
+
+namespace QBaselineTest {
+bool checkImage(const QImage& img, const char *name, quint16 checksum, QByteArray *msg, bool *error);
+}
+
+#define QBASELINE_CHECK_SUM(image, name, checksum)\
+do {\
+ QByteArray _msg;\
+ bool _err = false;\
+ if (!QBaselineTest::checkImage((image), (name), (checksum), &_msg, &_err)) {\
+ QFAIL(_msg.constData());\
+ } else if (_err) {\
+ QSKIP(_msg.constData(), SkipSingle);\
+ }\
+} while (0)
+
+#define QBASELINE_CHECK(image, name) QBASELINE_CHECK_SUM(image, name, 0)
+
+#endif // BASELINETEST_H
diff --git a/tests/arthur/common/qbaselinetest.pri b/tests/arthur/common/qbaselinetest.pri
new file mode 100644
index 0000000..5420c6e
--- /dev/null
+++ b/tests/arthur/common/qbaselinetest.pri
@@ -0,0 +1,13 @@
+QT *= testlib
+
+SOURCES += \
+ $$PWD/qbaselinetest.cpp
+
+HEADERS += \
+ $$PWD/qbaselinetest.h
+
+win32|symbian*:MKSPEC=$$replace(QMAKESPEC, \\\\, /)
+else:MKSPEC=$$QMAKESPEC
+DEFINES += QMAKESPEC=\\\"$$MKSPEC\\\"
+
+include($$PWD/baselineprotocol.pri)
diff --git a/tests/auto/baselineexample/baselineexample.pro b/tests/auto/baselineexample/baselineexample.pro
new file mode 100644
index 0000000..30feecc
--- /dev/null
+++ b/tests/auto/baselineexample/baselineexample.pro
@@ -0,0 +1,18 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2010-12-09T14:55:13
+#
+#-------------------------------------------------
+
+QT += testlib
+
+TARGET = tst_baselineexample
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+SOURCES += tst_baselineexample.cpp
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
+
+include($$QT_SOURCE_TREE/tests/arthur/common/qbaselinetest.pri)
diff --git a/tests/auto/baselineexample/tst_baselineexample.cpp b/tests/auto/baselineexample/tst_baselineexample.cpp
new file mode 100644
index 0000000..28cbec5
--- /dev/null
+++ b/tests/auto/baselineexample/tst_baselineexample.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qbaselinetest.h>
+#include <QPushButton>
+
+class tst_BaselineExample : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_BaselineExample();
+
+private Q_SLOTS:
+ void testBasicUsage();
+ void testMultipleImages();
+ void testDataDriven_data();
+ void testDataDriven();
+ void testDataDrivenMultiple_data();
+ void testDataDrivenMultiple();
+ void testChecksum_data();
+ void testChecksum();
+};
+
+
+tst_BaselineExample::tst_BaselineExample()
+{
+}
+
+
+void tst_BaselineExample::testBasicUsage()
+{
+ // Generate an image:
+ QPushButton b("Press me!");
+ b.resize(100, 50);
+ b.show();
+ QTest::qWaitForWindowShown(&b);
+ QImage img1 = QPixmap::grabWidget(&b).toImage();
+ QVERIFY(!img1.isNull());
+
+ // Compare it to baseline on server:
+ QBASELINE_CHECK(img1, "button");
+}
+
+
+void tst_BaselineExample::testMultipleImages()
+{
+ QPushButton b("Press me!");
+ b.resize(100, 50);
+ b.show();
+ QTest::qWaitForWindowShown(&b);
+ QBASELINE_CHECK(QPixmap::grabWidget(&b).toImage(), "text1");
+
+ b.setText("Kick me!");
+ QTest::qWait(50);
+ QBASELINE_CHECK(QPixmap::grabWidget(&b).toImage(), "text2");
+}
+
+
+void tst_BaselineExample::testDataDriven_data()
+{
+ QTest::addColumn<QString>("label");
+ QTest::newRow("short") << "Ok!";
+ QTest::newRow("long") << "A really long button text that just does not seem to end";
+ QTest::newRow("empty") << "";
+}
+
+
+void tst_BaselineExample::testDataDriven()
+{
+ QFETCH(QString, label);
+ QPushButton b(label);
+ b.resize(100, 50);
+ b.show();
+ QTest::qWaitForWindowShown(&b);
+ QBASELINE_CHECK(QPixmap::grabWidget(&b).toImage(), 0);
+}
+
+
+void tst_BaselineExample::testDataDrivenMultiple_data()
+{
+ testDataDriven_data();
+}
+
+
+void tst_BaselineExample::testDataDrivenMultiple()
+{
+ QFETCH(QString, label);
+ QPushButton b(label);
+ b.resize(100, 50);
+ b.show();
+ QTest::qWaitForWindowShown(&b);
+ QBASELINE_CHECK(QPixmap::grabWidget(&b).toImage(), "normal");
+
+ b.setText(label.prepend('&'));
+ QTest::qWait(50);
+ QBASELINE_CHECK(QPixmap::grabWidget(&b).toImage(), "shortcut");
+}
+
+
+void tst_BaselineExample::testChecksum_data()
+{
+ testDataDriven_data();
+}
+
+
+void tst_BaselineExample::testChecksum()
+{
+ QFETCH(QString, label);
+ QPushButton b(label);
+ b.resize(100, 50);
+ b.show();
+ QTest::qWaitForWindowShown(&b);
+ QBASELINE_CHECK_SUM(QPixmap::grabWidget(&b).toImage(), 0, quint16(qHash(label)));
+}
+
+
+QTEST_MAIN(tst_BaselineExample);
+
+#include "tst_baselineexample.moc"
diff --git a/tests/auto/lancelot/lancelot.pro b/tests/auto/lancelot/lancelot.pro
index 4535b83..6d6edf8 100644
--- a/tests/auto/lancelot/lancelot.pro
+++ b/tests/auto/lancelot/lancelot.pro
@@ -7,9 +7,6 @@ SOURCES += tst_lancelot.cpp \
HEADERS += $$QT_SOURCE_TREE/tests/arthur/common/paintcommands.h
RESOURCES += $$QT_SOURCE_TREE/tests/arthur/common/images.qrc
-include($$QT_SOURCE_TREE/tests/arthur/common/baselineprotocol.pri)
-win32|symbian*:MKSPEC=$$replace(QMAKESPEC, \\\\, /)
-else:MKSPEC=$$QMAKESPEC
-DEFINES += QMAKESPEC=\\\"$$MKSPEC\\\"
+include($$QT_SOURCE_TREE/tests/arthur/common/qbaselinetest.pri)
!symbian:!wince*:DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/lancelot/tst_lancelot.cpp b/tests/auto/lancelot/tst_lancelot.cpp
index d1b093f..4bde927 100644
--- a/tests/auto/lancelot/tst_lancelot.cpp
+++ b/tests/auto/lancelot/tst_lancelot.cpp
@@ -252,7 +252,7 @@ void tst_Lancelot::runTestSuite(GraphicsEngine engine, QImage::Format format)
if (dryRunMode)
qDebug() << "Dryrun mode, ignoring detected mismatch." << serverMsg;
else
- QFAIL("Rendered image differs from baseline.\n" + serverMsg);
+ QFAIL("Rendered image differs from baseline. Report:\n " + serverMsg);
}
}