summaryrefslogtreecommitdiffstats
path: root/src/testlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/testlib')
-rw-r--r--src/testlib/doc/qttestlib.qdocconf1
-rw-r--r--src/testlib/doc/snippets/code/doc_src_qsignalspy.cpp5
-rw-r--r--src/testlib/qabstracttestlogger_p.h4
-rw-r--r--src/testlib/qbenchmarkvalgrind.cpp2
-rw-r--r--src/testlib/qplaintestlogger.cpp31
-rw-r--r--src/testlib/qsignalspy.h57
-rw-r--r--src/testlib/qsignalspy.qdoc14
-rw-r--r--src/testlib/qtest.h6
-rw-r--r--src/testlib/qtestaccessible.h51
-rw-r--r--src/testlib/qtestblacklist.cpp201
-rw-r--r--src/testlib/qtestblacklist_p.h67
-rw-r--r--src/testlib/qtestcase.cpp18
-rw-r--r--src/testlib/qtestlog.cpp33
-rw-r--r--src/testlib/qtestlog_p.h3
-rw-r--r--src/testlib/qtestresult.cpp17
-rw-r--r--src/testlib/qtestresult_p.h1
-rw-r--r--src/testlib/qxmltestlogger.cpp11
-rw-r--r--src/testlib/qxunittestlogger.cpp28
-rw-r--r--src/testlib/testlib.pro7
19 files changed, 512 insertions, 45 deletions
diff --git a/src/testlib/doc/qttestlib.qdocconf b/src/testlib/doc/qttestlib.qdocconf
index 92e5c97aab..35b4fbcb7b 100644
--- a/src/testlib/doc/qttestlib.qdocconf
+++ b/src/testlib/doc/qttestlib.qdocconf
@@ -2,7 +2,6 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtTestLib
description = Qt Test Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = testlib
diff --git a/src/testlib/doc/snippets/code/doc_src_qsignalspy.cpp b/src/testlib/doc/snippets/code/doc_src_qsignalspy.cpp
index e4702c6e0b..0856de9450 100644
--- a/src/testlib/doc/snippets/code/doc_src_qsignalspy.cpp
+++ b/src/testlib/doc/snippets/code/doc_src_qsignalspy.cpp
@@ -83,3 +83,8 @@ QSignalSpy spy(myPushButton, SIGNAL(clicked(bool)));
//! [5]
QVERIFY(spy.wait(1000));
//! [5]
+
+//! [6]
+QSignalSpy spy(myPushButton, &QPushButton::clicked);
+//! [6]
+
diff --git a/src/testlib/qabstracttestlogger_p.h b/src/testlib/qabstracttestlogger_p.h
index c549233ddb..6bb54d1af8 100644
--- a/src/testlib/qabstracttestlogger_p.h
+++ b/src/testlib/qabstracttestlogger_p.h
@@ -68,7 +68,9 @@ public:
Pass,
XFail,
Fail,
- XPass
+ XPass,
+ BlacklistedPass,
+ BlacklistedFail
};
enum MessageTypes {
diff --git a/src/testlib/qbenchmarkvalgrind.cpp b/src/testlib/qbenchmarkvalgrind.cpp
index 545de3bb65..cd804774e9 100644
--- a/src/testlib/qbenchmarkvalgrind.cpp
+++ b/src/testlib/qbenchmarkvalgrind.cpp
@@ -66,7 +66,7 @@ bool QBenchmarkValgrindUtils::haveValgrind()
if (!process.waitForFinished(-1))
return false;
const QByteArray out = process.readAllStandardOutput();
- QRegExp rx(QLatin1String("^valgrind-([0-9]).([0-9]).[0-9]"));
+ QRegExp rx(QLatin1String("^valgrind-([0-9]+).([0-9]+).[0-9]+"));
if (rx.indexIn(QLatin1String(out.data())) == -1)
return false;
bool ok;
diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp
index 39580f22d4..74f0290f38 100644
--- a/src/testlib/qplaintestlogger.cpp
+++ b/src/testlib/qplaintestlogger.cpp
@@ -51,21 +51,29 @@
#include <stdlib.h>
#include <string.h>
-#ifdef Q_OS_WIN
-#include <windows.h>
-#endif
-
#ifdef Q_OS_WINCE
#include <QtCore/QString>
#endif
+#ifdef min // windows.h without NOMINMAX is included by the benchmark headers.
+# undef min
+#endif
+#ifdef max
+# undef max
+#endif
+
#include <QtCore/QByteArray>
#include <QtCore/qmath.h>
+#include <QtCore/QLibraryInfo>
#ifdef Q_OS_ANDROID
# include <android/log.h>
#endif
+#ifdef Q_OS_WIN
+# include <qt_windows.h>
+#endif
+
QT_BEGIN_NAMESPACE
namespace QTest {
@@ -81,6 +89,10 @@ namespace QTest {
return "FAIL! ";
case QAbstractTestLogger::XPass:
return "XPASS ";
+ case QAbstractTestLogger::BlacklistedPass:
+ return "BPASS ";
+ case QAbstractTestLogger::BlacklistedFail:
+ return "BFAIL ";
}
return "??????";
}
@@ -334,7 +346,7 @@ void QPlainTestLogger::startLogging()
qsnprintf(buf, sizeof(buf),
"********* Start testing of %s *********\n"
"Config: Using QtTest library " QTEST_VERSION_STR
- ", Qt %s\n", QTestResult::currentTestObjectName(), qVersion());
+ ", %s\n", QTestResult::currentTestObjectName(), QLibraryInfo::build());
}
outputMessage(buf);
}
@@ -343,15 +355,16 @@ void QPlainTestLogger::stopLogging()
{
char buf[1024];
if (QTestLog::verboseLevel() < 0) {
- qsnprintf(buf, sizeof(buf), "Totals: %d passed, %d failed, %d skipped\n",
+ qsnprintf(buf, sizeof(buf), "Totals: %d passed, %d failed, %d skipped, %d blacklisted\n",
QTestLog::passCount(), QTestLog::failCount(),
- QTestLog::skipCount());
+ QTestLog::skipCount(), QTestLog::blacklistCount());
} else {
qsnprintf(buf, sizeof(buf),
- "Totals: %d passed, %d failed, %d skipped\n"
+ "Totals: %d passed, %d failed, %d skipped, %d blacklisted\n"
"********* Finished testing of %s *********\n",
QTestLog::passCount(), QTestLog::failCount(),
- QTestLog::skipCount(), QTestResult::currentTestObjectName());
+ QTestLog::skipCount(), QTestLog::blacklistCount(),
+ QTestResult::currentTestObjectName());
}
outputMessage(buf);
diff --git a/src/testlib/qsignalspy.h b/src/testlib/qsignalspy.h
index 72a5df1ed9..3ce1c6f99b 100644
--- a/src/testlib/qsignalspy.h
+++ b/src/testlib/qsignalspy.h
@@ -98,6 +98,48 @@ public:
initArgs(mo->method(sigIndex), obj);
}
+#ifdef Q_QDOC
+ QSignalSpy(const QObject *object, PointerToMemberFunction signal);
+#else
+ template <typename Func>
+ QSignalSpy(const typename QtPrivate::FunctionPointer<Func>::Object *obj, Func signal0)
+ : m_waiting(false)
+ {
+#ifdef Q_CC_BOR
+ const int memberOffset = QObject::staticMetaObject.methodCount();
+#else
+ static const int memberOffset = QObject::staticMetaObject.methodCount();
+#endif
+ if (!obj) {
+ qWarning("QSignalSpy: Cannot spy on a null object");
+ return;
+ }
+
+ if (!signal0) {
+ qWarning("QSignalSpy: Null signal name is not valid");
+ return;
+ }
+
+ const QMetaObject * const mo = obj->metaObject();
+ const QMetaMethod signalMetaMethod = QMetaMethod::fromSignal(signal0);
+ const int sigIndex = signalMetaMethod.methodIndex();
+ if (!signalMetaMethod.isValid() ||
+ signalMetaMethod.methodType() != QMetaMethod::Signal) {
+ qWarning("QSignalSpy: Not a valid signal: '%s'",
+ signalMetaMethod.methodSignature().constData());
+ return;
+ }
+
+ if (!QMetaObject::connect(obj, sigIndex, this, memberOffset,
+ Qt::DirectConnection, 0)) {
+ qWarning("QSignalSpy: QMetaObject::connect returned false. Unable to connect.");
+ return;
+ }
+ sig = signalMetaMethod.methodSignature();
+ initArgs(mo->method(sigIndex), obj);
+ }
+#endif // Q_QDOC
+
inline bool isValid() const { return !sig.isEmpty(); }
inline QByteArray signal() const { return sig; }
@@ -127,17 +169,11 @@ public:
}
private:
- void initArgs(const QMetaMethod &member)
- {
- initArgs(member, 0);
- }
-
void initArgs(const QMetaMethod &member, const QObject *obj)
{
- const QList<QByteArray> params = member.parameterTypes();
- args.reserve(params.size());
- for (int i = 0; i < params.count(); ++i) {
- int tp = QMetaType::type(params.at(i).constData());
+ args.reserve(member.parameterCount());
+ for (int i = 0; i < member.parameterCount(); ++i) {
+ int tp = member.parameterType(i);
if (tp == QMetaType::UnknownType && obj) {
void *argv[] = { &tp, &i };
QMetaObject::metacall(const_cast<QObject*>(obj),
@@ -147,9 +183,8 @@ private:
tp = QMetaType::UnknownType;
}
if (tp == QMetaType::UnknownType) {
- Q_ASSERT(tp != QMetaType::Void); // void parameter => metaobject is corrupt
qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.",
- params.at(i).constData());
+ member.parameterNames().at(i).constData());
}
args << tp;
}
diff --git a/src/testlib/qsignalspy.qdoc b/src/testlib/qsignalspy.qdoc
index 9559090e8f..31cdeaba6a 100644
--- a/src/testlib/qsignalspy.qdoc
+++ b/src/testlib/qsignalspy.qdoc
@@ -72,6 +72,20 @@
\snippet code/doc_src_qsignalspy.cpp 4
*/
+/*! \fn QSignalSpy::QSignalSpy(const QObject *object, PointerToMemberFunction signal)
+ \since 5.4
+
+ Constructs a new QSignalSpy that listens for emissions of the \a signal
+ from the QObject \a object. If QSignalSpy is not able to listen for a
+ valid signal (for example, because \a object is null or \a signal does
+ not denote a valid signal of \a object), an explanatory warning message
+ will be output using qWarning() and subsequent calls to \c isValid() will
+ return false.
+
+ Example:
+ \snippet code/doc_src_qsignalspy.cpp 6
+*/
+
/*! \fn QSignalSpy::isValid() const
Returns \c true if the signal spy listens to a valid signal, otherwise false.
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index 7d2f3cea72..8a18ea7541 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -54,6 +54,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qvariant.h>
#include <QtCore/qurl.h>
+#include <QtCore/qversionnumber.h>
#include <QtCore/qpoint.h>
#include <QtCore/qsize.h>
@@ -171,6 +172,11 @@ template<> inline char *toString(const QVariant &v)
return qstrdup(vstring.constData());
}
+template<> inline char *toString(const QVersionNumber &version)
+{
+ return toString(version.toString());
+}
+
template<>
inline bool qCompare(QString const &t1, QLatin1String const &t2, const char *actual,
const char *expected, const char *file, int line)
diff --git a/src/testlib/qtestaccessible.h b/src/testlib/qtestaccessible.h
index ef6f61bd82..65fbd4c818 100644
--- a/src/testlib/qtestaccessible.h
+++ b/src/testlib/qtestaccessible.h
@@ -194,42 +194,75 @@ private:
{
QAccessibleEvent *ev;
if (event->type() == QAccessible::StateChanged) {
- ev = new QAccessibleStateChangeEvent(event->object(),
+ if (event->object())
+ ev = new QAccessibleStateChangeEvent(event->object(),
+ static_cast<QAccessibleStateChangeEvent*>(event)->changedStates());
+ else
+ ev = new QAccessibleStateChangeEvent(event->accessibleInterface(),
static_cast<QAccessibleStateChangeEvent*>(event)->changedStates());
} else if (event->type() == QAccessible::TextCaretMoved) {
- ev = new QAccessibleTextCursorEvent(event->object(), static_cast<QAccessibleTextCursorEvent*>(event)->cursorPosition());
+ if (event->object())
+ ev = new QAccessibleTextCursorEvent(event->object(), static_cast<QAccessibleTextCursorEvent*>(event)->cursorPosition());
+ else
+ ev = new QAccessibleTextCursorEvent(event->accessibleInterface(), static_cast<QAccessibleTextCursorEvent*>(event)->cursorPosition());
} else if (event->type() == QAccessible::TextSelectionChanged) {
const QAccessibleTextSelectionEvent *original = static_cast<QAccessibleTextSelectionEvent*>(event);
- QAccessibleTextSelectionEvent *sel = new QAccessibleTextSelectionEvent(event->object(), original->selectionStart(), original->selectionEnd());
+ QAccessibleTextSelectionEvent *sel;
+ if (event->object())
+ sel = new QAccessibleTextSelectionEvent(event->object(), original->selectionStart(), original->selectionEnd());
+ else
+ sel = new QAccessibleTextSelectionEvent(event->accessibleInterface(), original->selectionStart(), original->selectionEnd());
sel->setCursorPosition(original->cursorPosition());
ev = sel;
} else if (event->type() == QAccessible::TextInserted) {
const QAccessibleTextInsertEvent *original = static_cast<QAccessibleTextInsertEvent*>(event);
- QAccessibleTextInsertEvent *ins = new QAccessibleTextInsertEvent(event->object(), original->changePosition(), original->textInserted());
+ QAccessibleTextInsertEvent *ins;
+ if (original->object())
+ ins = new QAccessibleTextInsertEvent(event->object(), original->changePosition(), original->textInserted());
+ else
+ ins = new QAccessibleTextInsertEvent(event->accessibleInterface(), original->changePosition(), original->textInserted());
ins->setCursorPosition(original->cursorPosition());
ev = ins;
} else if (event->type() == QAccessible::TextRemoved) {
const QAccessibleTextRemoveEvent *original = static_cast<QAccessibleTextRemoveEvent*>(event);
- QAccessibleTextRemoveEvent *rem = new QAccessibleTextRemoveEvent(event->object(), original->changePosition(), original->textRemoved());
+ QAccessibleTextRemoveEvent *rem;
+ if (event->object())
+ rem = new QAccessibleTextRemoveEvent(event->object(), original->changePosition(), original->textRemoved());
+ else
+ rem = new QAccessibleTextRemoveEvent(event->accessibleInterface(), original->changePosition(), original->textRemoved());
rem->setCursorPosition(original->cursorPosition());
ev = rem;
} else if (event->type() == QAccessible::TextUpdated) {
const QAccessibleTextUpdateEvent *original = static_cast<QAccessibleTextUpdateEvent*>(event);
- QAccessibleTextUpdateEvent *upd = new QAccessibleTextUpdateEvent(event->object(), original->changePosition(), original->textRemoved(), original->textInserted());
+ QAccessibleTextUpdateEvent *upd;
+ if (event->object())
+ upd = new QAccessibleTextUpdateEvent(event->object(), original->changePosition(), original->textRemoved(), original->textInserted());
+ else
+ upd = new QAccessibleTextUpdateEvent(event->accessibleInterface(), original->changePosition(), original->textRemoved(), original->textInserted());
upd->setCursorPosition(original->cursorPosition());
ev = upd;
} else if (event->type() == QAccessible::ValueChanged) {
- ev = new QAccessibleValueChangeEvent(event->object(), static_cast<QAccessibleValueChangeEvent*>(event)->value());
+ if (event->object())
+ ev = new QAccessibleValueChangeEvent(event->object(), static_cast<QAccessibleValueChangeEvent*>(event)->value());
+ else
+ ev = new QAccessibleValueChangeEvent(event->accessibleInterface(), static_cast<QAccessibleValueChangeEvent*>(event)->value());
} else if (event->type() == QAccessible::TableModelChanged) {
QAccessibleTableModelChangeEvent *oldEvent = static_cast<QAccessibleTableModelChangeEvent*>(event);
- QAccessibleTableModelChangeEvent *newEvent = new QAccessibleTableModelChangeEvent(event->object(), oldEvent->modelChangeType());
+ QAccessibleTableModelChangeEvent *newEvent;
+ if (event->object())
+ newEvent = new QAccessibleTableModelChangeEvent(event->object(), oldEvent->modelChangeType());
+ else
+ newEvent = new QAccessibleTableModelChangeEvent(event->accessibleInterface(), oldEvent->modelChangeType());
newEvent->setFirstRow(oldEvent->firstRow());
newEvent->setFirstColumn(oldEvent->firstColumn());
newEvent->setLastRow(oldEvent->lastRow());
newEvent->setLastColumn(oldEvent->lastColumn());
ev = newEvent;
} else {
- ev = new QAccessibleEvent(event->object(), event->type());
+ if (event->object())
+ ev = new QAccessibleEvent(event->object(), event->type());
+ else
+ ev = new QAccessibleEvent(event->accessibleInterface(), event->type());
}
ev->setChild(event->child());
return ev;
diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp
new file mode 100644
index 0000000000..7921b350b5
--- /dev/null
+++ b/src/testlib/qtestblacklist.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qtestblacklist_p.h"
+#include "qtestresult_p.h"
+
+#include <QtTest/qtestcase.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qfile.h>
+
+#include <set>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ The file format is simply a grouped listing of keywords
+ Ungrouped entries at the beginning apply to the whole testcase
+ Groups define testfunctions or specific test data to ignore.
+ After the groups come a list of entries (one per line) that define
+ for which platform/os combination to ignore the test result.
+ All keys in a single line have to match to blacklist the test.
+
+ mac
+ [testFunction]
+ linux
+ windows 64bit
+ [testfunction2:testData]
+ msvc
+
+ The known keys are listed below:
+*/
+
+// this table can be extended with new keywords as required
+const char *matchedConditions[] =
+{
+#ifdef Q_OS_LINUX
+ "linux",
+#endif
+#ifdef Q_OS_OSX
+ "osx",
+#endif
+#ifdef Q_OS_WIN
+ "windows",
+#endif
+#ifdef Q_OS_IOS
+ "ios",
+#endif
+#ifdef Q_OS_ANDROID
+ "android",
+#endif
+#ifdef Q_OS_QNX
+ "qnx",
+#endif
+#ifdef Q_OS_WINRT
+ "winrt",
+#endif
+#ifdef Q_OS_WINCE
+ "wince",
+#endif
+
+#if QT_POINTER_SIZE == 8
+ "64bit",
+#else
+ "32bit",
+#endif
+
+#ifdef Q_CC_GNU
+ "gcc",
+#endif
+#ifdef Q_CC_CLANG
+ "clang",
+#endif
+#ifdef Q_CC_MSVC
+ "msvc",
+#endif
+
+#ifdef Q_AUTOTEST_EXPORT
+ "developer-build",
+#endif
+ 0
+};
+
+
+static bool checkCondition(const QByteArray &condition)
+{
+ QList<QByteArray> conds = condition.split(' ');
+ std::set<QByteArray> matches;
+ const char **m = matchedConditions;
+ while (*m) {
+ matches.insert(*m);
+ ++m;
+ }
+
+ for (int i = 0; i < conds.size(); ++i) {
+ QByteArray c = conds.at(i);
+ bool result = c.startsWith('!');
+ if (result)
+ c = c.mid(1);
+
+ result ^= (matches.find(c) != matches.end());
+ if (!result)
+ return false;
+ }
+ return true;
+}
+
+static bool ignoreAll = false;
+static std::set<QByteArray> *ignoredTests = 0;
+
+namespace QTestPrivate {
+
+void parseBlackList()
+{
+ QString filename = QTest::qFindTestData(QStringLiteral("BLACKLIST"));
+ if (filename.isEmpty())
+ return;
+ QFile ignored(filename);
+ if (!ignored.open(QIODevice::ReadOnly))
+ return;
+
+ QByteArray function;
+
+ while (!ignored.atEnd()) {
+ QByteArray line = ignored.readLine().simplified();
+ if (line.isEmpty() || line.startsWith('#'))
+ continue;
+ if (line.startsWith('[')) {
+ function = line.mid(1, line.length() - 2);
+ continue;
+ }
+ bool condition = checkCondition(line);
+ if (condition) {
+ if (!function.size()) {
+ ignoreAll = true;
+ } else {
+ if (!ignoredTests)
+ ignoredTests = new std::set<QByteArray>;
+ ignoredTests->insert(function);
+ }
+ }
+ }
+}
+
+void checkBlackList(const char *slot, const char *data)
+{
+ bool ignore = ignoreAll;
+
+ if (!ignore && ignoredTests) {
+ QByteArray s = slot;
+ ignore = (ignoredTests->find(s) != ignoredTests->end());
+ if (!ignore && data) {
+ s += ':';
+ s += data;
+ ignore = (ignoredTests->find(s) != ignoredTests->end());
+ }
+ }
+
+ QTestResult::setBlacklistCurrentTest(ignore);
+}
+
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/testlib/qtestblacklist_p.h b/src/testlib/qtestblacklist_p.h
new file mode 100644
index 0000000000..a9d07ae024
--- /dev/null
+++ b/src/testlib/qtestblacklist_p.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTESTBLACKLIST_P_H
+#define QTESTBLACKLIST_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtTest/qtest_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QTestPrivate {
+ void parseBlackList();
+ void checkBlackList(const char *slot, const char *data);
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 83cba0d672..877be81fb9 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -63,6 +63,7 @@
#include <QtTest/private/qsignaldumper_p.h>
#include <QtTest/private/qbenchmark_p.h>
#include <QtTest/private/cycle_p.h>
+#include <QtTest/private/qtestblacklist_p.h>
#include <numeric>
#include <algorithm>
@@ -1034,6 +1035,13 @@ QT_BEGIN_NAMESPACE
Returns a textual representation of the given \a variant.
*/
+/*!
+ \fn char *QTest::toString(const QVersionNumber &version)
+ \overload
+
+ Returns a textual representation of the given \a version.
+*/
+
/*! \fn void QTest::qWait(int ms)
Waits for \a ms milliseconds. While waiting, events will be processed and
@@ -2009,6 +2017,9 @@ static bool qInvokeTestMethod(const char *slotName, const char *data=0)
QTestResult::setSkipCurrentTest(false);
if (!data || !qstrcmp(data, table.testData(curDataIndex)->dataTag())) {
foundFunction = true;
+
+ QTestPrivate::checkBlackList(slot, dataCount ? table.testData(curDataIndex)->dataTag() : 0);
+
QTestDataSetter s(curDataIndex >= dataCount ? static_cast<QTestData *>(0)
: table.testData(curDataIndex));
@@ -2426,6 +2437,8 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
}
#endif
+ QTestPrivate::parseBlackList();
+
QTestResult::reset();
QTEST_ASSERT(testObject);
@@ -2601,6 +2614,7 @@ void QTest::ignoreMessage(QtMsgType type, const char *message)
QTestLog::ignoreMessage(type, message);
}
+#ifndef QT_NO_REGULAREXPRESSION
/*!
\overload
@@ -2616,13 +2630,11 @@ void QTest::ignoreMessage(QtMsgType type, const char *message)
\since 5.3
*/
-
-#ifndef QT_NO_REGULAREXPRESSION
void QTest::ignoreMessage(QtMsgType type, const QRegularExpression &messagePattern)
{
QTestLog::ignoreMessage(type, messagePattern);
}
-#endif
+#endif // QT_NO_REGULAREXPRESSION
/*! \internal
*/
diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp
index 4ef1113641..b7ed3d0763 100644
--- a/src/testlib/qtestlog.cpp
+++ b/src/testlib/qtestlog.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtTest module of the Qt Toolkit.
@@ -59,8 +59,6 @@
QT_BEGIN_NAMESPACE
-Q_CORE_EXPORT QString qMessageFormatString(QtMsgType type, const QMessageLogContext &context, const QString& msg);
-
static void saveCoverageTool(const char * appname, bool testfailed, bool installedTestCoverage)
{
#ifdef __COVERAGESCANNER__
@@ -86,6 +84,7 @@ namespace QTest {
int fails = 0;
int passes = 0;
int skips = 0;
+ int blacklists = 0;
struct IgnoreResultList
{
@@ -287,7 +286,7 @@ namespace QTest {
// the message is expected, so just swallow it.
return;
- QString msg = qMessageFormatString(type, context, message);
+ QString msg = qFormatLogMessage(type, context, message);
msg.chop(1); // remove trailing newline
if (type != QtFatalMsg) {
@@ -417,6 +416,25 @@ void QTestLog::addXPass(const char *msg, const char *file, int line)
QTest::TestLoggers::addIncident(QAbstractTestLogger::XPass, msg, file, line);
}
+void QTestLog::addBPass(const char *msg)
+{
+ QTEST_ASSERT(msg);
+
+ ++QTest::blacklists;
+
+ QTest::TestLoggers::addIncident(QAbstractTestLogger::BlacklistedPass, msg);
+}
+
+void QTestLog::addBFail(const char *msg, const char *file, int line)
+{
+ QTEST_ASSERT(msg);
+ QTEST_ASSERT(file);
+
+ ++QTest::blacklists;
+
+ QTest::TestLoggers::addIncident(QAbstractTestLogger::BlacklistedFail, msg, file, line);
+}
+
void QTestLog::addSkip(const char *msg, const char *file, int line)
{
QTEST_ASSERT(msg);
@@ -525,7 +543,7 @@ void QTestLog::ignoreMessage(QtMsgType type, const QRegularExpression &expressio
QTest::IgnoreResultList::append(QTest::ignoreResultList, type, QVariant(expression));
}
-#endif
+#endif // QT_NO_REGULAREXPRESSION
void QTestLog::setMaxWarnings(int m)
{
@@ -554,6 +572,11 @@ int QTestLog::skipCount()
return QTest::skips;
}
+int QTestLog::blacklistCount()
+{
+ return QTest::blacklists;
+}
+
void QTestLog::resetCounters()
{
QTest::passes = 0;
diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h
index 0ed6750f63..5d5ffd3f6f 100644
--- a/src/testlib/qtestlog_p.h
+++ b/src/testlib/qtestlog_p.h
@@ -72,6 +72,8 @@ public:
static void addFail(const char *msg, const char *file, int line);
static void addXFail(const char *msg, const char *file, int line);
static void addXPass(const char *msg, const char *file, int line);
+ static void addBPass(const char *msg);
+ static void addBFail(const char *msg, const char *file, int line);
static void addSkip(const char *msg, const char *file, int line);
static void addBenchmarkResult(const QBenchmarkResult &result);
@@ -104,6 +106,7 @@ public:
static int passCount();
static int failCount();
static int skipCount();
+ static int blacklistCount();
static void resetCounters();
diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp
index 8eb1fa2d9c..8d1a942d8b 100644
--- a/src/testlib/qtestresult.cpp
+++ b/src/testlib/qtestresult.cpp
@@ -62,6 +62,7 @@ namespace QTest
static const char *currentTestObjectName = 0;
static bool failed = false;
static bool skipCurrentTest = false;
+ static bool blacklistCurrentTest = false;
static const char *expectFailComment = 0;
static int expectFailMode = 0;
@@ -77,10 +78,16 @@ void QTestResult::reset()
QTest::expectFailComment = 0;
QTest::expectFailMode = 0;
+ QTest::blacklistCurrentTest = false;
QTestLog::resetCounters();
}
+void QTestResult::setBlacklistCurrentTest(bool b)
+{
+ QTest::blacklistCurrentTest = b;
+}
+
bool QTestResult::currentTestFailed()
{
return QTest::failed;
@@ -139,7 +146,10 @@ void QTestResult::finishedCurrentTestDataCleanup()
{
// If the current test hasn't failed or been skipped, then it passes.
if (!QTest::failed && !QTest::skipCurrentTest) {
- QTestLog::addPass("");
+ if (QTest::blacklistCurrentTest)
+ QTestLog::addBPass("");
+ else
+ QTestLog::addPass("");
}
QTest::failed = false;
@@ -290,7 +300,10 @@ void QTestResult::addFailure(const char *message, const char *file, int line)
{
clearExpectFail();
- QTestLog::addFail(message, file, line);
+ if (QTest::blacklistCurrentTest)
+ QTestLog::addBFail(message, file, line);
+ else
+ QTestLog::addFail(message, file, line);
QTest::failed = true;
}
diff --git a/src/testlib/qtestresult_p.h b/src/testlib/qtestresult_p.h
index ea8173b169..8454acd5f8 100644
--- a/src/testlib/qtestresult_p.h
+++ b/src/testlib/qtestresult_p.h
@@ -74,6 +74,7 @@ public:
static void finishedCurrentTestDataCleanup();
static void finishedCurrentTestFunction();
static void reset();
+ static void setBlacklistCurrentTest(bool b);
static void addFailure(const char *message, const char *file, int line);
static bool compare(bool success, const char *failureMsg,
diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp
index 3fff753c5c..52dc5db69f 100644
--- a/src/testlib/qxmltestlogger.cpp
+++ b/src/testlib/qxmltestlogger.cpp
@@ -42,6 +42,7 @@
#include <stdio.h>
#include <string.h>
#include <QtCore/qglobal.h>
+#include <QtCore/qlibraryinfo.h>
#include <QtTest/private/qxmltestlogger_p.h>
#include <QtTest/private/qtestresult_p.h>
@@ -85,6 +86,10 @@ namespace QTest {
return "fail";
case QAbstractTestLogger::XPass:
return "xpass";
+ case QAbstractTestLogger::BlacklistedPass:
+ return "bpass";
+ case QAbstractTestLogger::BlacklistedFail:
+ return "bfail";
}
return "??????";
}
@@ -115,11 +120,15 @@ void QXmlTestLogger::startLogging()
outputString(buf.constData());
}
+ QTestCharBuffer quotedBuild;
+ xmlQuote(&quotedBuild, QLibraryInfo::build());
+
QTest::qt_asprintf(&buf,
"<Environment>\n"
" <QtVersion>%s</QtVersion>\n"
+ " <QtBuild>%s</QtBuild>\n"
" <QTestVersion>" QTEST_VERSION_STR "</QTestVersion>\n"
- "</Environment>\n", qVersion());
+ "</Environment>\n", qVersion(), quotedBuild.constData());
outputString(buf.constData());
m_totalTime.start();
}
diff --git a/src/testlib/qxunittestlogger.cpp b/src/testlib/qxunittestlogger.cpp
index a47f77ae49..5d860cf1c9 100644
--- a/src/testlib/qxunittestlogger.cpp
+++ b/src/testlib/qxunittestlogger.cpp
@@ -46,6 +46,15 @@
#include <QtTest/private/qtestresult_p.h>
#include <QtTest/private/qbenchmark_p.h>
+#ifdef min // windows.h without NOMINMAX is included by the benchmark headers.
+# undef min
+#endif
+#ifdef max
+# undef max
+#endif
+
+#include <QtCore/qlibraryinfo.h>
+
#include <string.h>
QT_BEGIN_NAMESPACE
@@ -108,6 +117,11 @@ void QXunitTestLogger::stopLogging()
property->addAttribute(QTest::AI_PropertyValue, qVersion());
properties->addLogElement(property);
+ property = new QTestElement(QTest::LET_Property);
+ property->addAttribute(QTest::AI_Name, "QtBuild");
+ property->addAttribute(QTest::AI_PropertyValue, QLibraryInfo::build());
+ properties->addLogElement(property);
+
currentLogElement->addLogElement(properties);
currentLogElement->addLogElement(iterator);
@@ -161,6 +175,13 @@ void QXunitTestLogger::addIncident(IncidentTypes type, const char *description,
++failureCounter;
typeBuf = "fail";
break;
+ case QAbstractTestLogger::BlacklistedPass:
+ typeBuf = "bpass";
+ break;
+ case QAbstractTestLogger::BlacklistedFail:
+ ++failureCounter;
+ typeBuf = "bfail";
+ break;
default:
typeBuf = "??????";
break;
@@ -193,6 +214,13 @@ void QXunitTestLogger::addIncident(IncidentTypes type, const char *description,
if (!strcmp(oldResult, "pass")) {
overwrite = true;
}
+ else if (!strcmp(oldResult, "bpass")) {
+ overwrite = (type == QAbstractTestLogger::XPass || type == QAbstractTestLogger::Fail) || (type == QAbstractTestLogger::XFail)
+ || (type == QAbstractTestLogger::BlacklistedFail);
+ }
+ else if (!strcmp(oldResult, "bfail")) {
+ overwrite = (type == QAbstractTestLogger::XPass || type == QAbstractTestLogger::Fail) || (type == QAbstractTestLogger::XFail);
+ }
else if (!strcmp(oldResult, "xfail")) {
overwrite = (type == QAbstractTestLogger::XPass || type == QAbstractTestLogger::Fail);
}
diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro
index 1fb6d6df18..17a03781c2 100644
--- a/src/testlib/testlib.pro
+++ b/src/testlib/testlib.pro
@@ -33,7 +33,8 @@ HEADERS = qbenchmark.h \
qtestmouse.h \
qtestspontaneevent.h \
qtestsystem.h \
- qtesttouch.h
+ qtesttouch.h \
+ qtestblacklist_p.h
SOURCES = qtestcase.cpp \
qtestlog.cpp \
@@ -55,7 +56,9 @@ SOURCES = qtestcase.cpp \
qtestelement.cpp \
qtestelementattribute.cpp \
qtestxunitstreamer.cpp \
- qxunittestlogger.cpp
+ qxunittestlogger.cpp \
+ qtestblacklist.cpp
+
DEFINES *= QT_NO_CAST_TO_ASCII \
QT_NO_CAST_FROM_ASCII \
QT_NO_DATASTREAM