summaryrefslogtreecommitdiffstats
path: root/src/testlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/testlib')
-rw-r--r--src/testlib/3rdparty/cycle_p.h17
-rw-r--r--src/testlib/doc/qttestlib.qdocconf1
-rw-r--r--src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp8
-rw-r--r--src/testlib/doc/src/qttest-index.qdoc4
-rw-r--r--src/testlib/qabstractitemmodeltester.cpp807
-rw-r--r--src/testlib/qabstractitemmodeltester.h131
-rw-r--r--src/testlib/qbenchmarkmetric.cpp190
-rw-r--r--src/testlib/qbenchmarkperfevents.cpp4
-rw-r--r--src/testlib/qbenchmarkperfevents_p.h20
-rw-r--r--src/testlib/qcsvbenchmarklogger_p.h14
-rw-r--r--src/testlib/qplaintestlogger.cpp47
-rw-r--r--src/testlib/qsignalspy.h9
-rw-r--r--src/testlib/qsignalspy.qdoc2
-rw-r--r--src/testlib/qtest.h31
-rw-r--r--src/testlib/qtest_gui.h57
-rw-r--r--src/testlib/qtest_network.h15
-rw-r--r--src/testlib/qtestaccessible.h8
-rw-r--r--src/testlib/qtestblacklist.cpp14
-rw-r--r--src/testlib/qtestcase.cpp218
-rw-r--r--src/testlib/qtestcase.h36
-rw-r--r--src/testlib/qtestcase.qdoc108
-rw-r--r--src/testlib/qtesteventloop.h6
-rw-r--r--src/testlib/qtestkeyboard.h20
-rw-r--r--src/testlib/qtestmouse.h37
-rw-r--r--src/testlib/qtestsystem.h71
-rw-r--r--src/testlib/qtesttable.cpp6
-rw-r--r--src/testlib/qtesttouch.h24
-rw-r--r--src/testlib/qtestutil_macos.mm27
-rw-r--r--src/testlib/qtestutil_macos_p.h11
-rw-r--r--src/testlib/qxctestlogger_p.h16
-rw-r--r--src/testlib/testlib.pro8
31 files changed, 1572 insertions, 395 deletions
diff --git a/src/testlib/3rdparty/cycle_p.h b/src/testlib/3rdparty/cycle_p.h
index a2924230ad..95e741a82a 100644
--- a/src/testlib/3rdparty/cycle_p.h
+++ b/src/testlib/3rdparty/cycle_p.h
@@ -493,21 +493,4 @@ INLINE_ELAPSED(inline)
#define HAVE_TICK_COUNTER
#endif
-/*----------------------------------------------------------------*/
-/* Symbian */
-#if defined(__SYMBIAN32__) && !defined(HAVE_TICK_COUNTER)
-#include <e32std.h>
-
-typedef TUint32 CycleCounterTicks;
-
-static inline CycleCounterTicks getticks(void)
-{
- return User::FastCounter();
-}
-
-INLINE_ELAPSED(inline)
-
-#define HAVE_TICK_COUNTER
-#endif
-
#endif // QBENCHLIB_CYCLE_H
diff --git a/src/testlib/doc/qttestlib.qdocconf b/src/testlib/doc/qttestlib.qdocconf
index 899f94ec53..1fdb136e78 100644
--- a/src/testlib/doc/qttestlib.qdocconf
+++ b/src/testlib/doc/qttestlib.qdocconf
@@ -1,6 +1,7 @@
include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtTestLib
+moduleheader = QtTest
description = Qt Test Reference Documentation
version = $QT_VERSION
diff --git a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp
index 01ee8102f4..990b7a38d7 100644
--- a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp
+++ b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp
@@ -306,5 +306,13 @@ QTest::keyClick(myWindow, Qt::Key_Escape);
QTest::keyClick(myWindow, Qt::Key_Escape, Qt::ShiftModifier, 200);
//! [29]
+//! [30]
+MyObject obj;
+obj.startup();
+QTest::qWaitFor([&]() {
+ return obj.isReady();
+}, 3000);
+//! [30]
+
}
diff --git a/src/testlib/doc/src/qttest-index.qdoc b/src/testlib/doc/src/qttest-index.qdoc
index f5b077e8e8..b3c2be7375 100644
--- a/src/testlib/doc/src/qttest-index.qdoc
+++ b/src/testlib/doc/src/qttest-index.qdoc
@@ -31,7 +31,9 @@
Qt Test provides classes for unit testing Qt applications and libraries.
All public methods are in the \l QTest namespace. In addition, the
- \l QSignalSpy class provides easy introspection for Qt's signals and slots.
+ \l QSignalSpy class provides easy introspection for Qt's signals and slots,
+ and the \l QAbstractItemModelTester allows for non-destructive testing
+ of item models.
\section1 Getting Started
diff --git a/src/testlib/qabstractitemmodeltester.cpp b/src/testlib/qabstractitemmodeltester.cpp
new file mode 100644
index 0000000000..18ae14be3a
--- /dev/null
+++ b/src/testlib/qabstractitemmodeltester.cpp
@@ -0,0 +1,807 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractitemmodeltester.h"
+
+#include <private/qobject_p.h>
+#include <QtCore/QPointer>
+#include <QtCore/QAbstractItemModel>
+#include <QtCore/QStack>
+#include <QtTest/QtTest>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcModelTest, "qt.modeltest")
+
+#define MODELTESTER_VERIFY(statement) \
+do { \
+ if (!verify(static_cast<bool>(statement), #statement, "", __FILE__, __LINE__)) \
+ return; \
+} while (false)
+
+#define MODELTESTER_COMPARE(actual, expected) \
+do { \
+ if (!compare((actual), (expected), #actual, #expected, __FILE__, __LINE__)) \
+ return; \
+} while (false)
+
+class QAbstractItemModelTesterPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QAbstractItemModelTester)
+public:
+ QAbstractItemModelTesterPrivate(QAbstractItemModel *model, QAbstractItemModelTester::FailureReportingMode failureReportingMode);
+
+ void nonDestructiveBasicTest();
+ void rowAndColumnCount();
+ void hasIndex();
+ void index();
+ void parent();
+ void data();
+
+ void runAllTests();
+ void layoutAboutToBeChanged();
+ void layoutChanged();
+ void rowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
+ void rowsInserted(const QModelIndex &parent, int start, int end);
+ void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ void rowsRemoved(const QModelIndex &parent, int start, int end);
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void headerDataChanged(Qt::Orientation orientation, int start, int end);
+
+private:
+ void checkChildren(const QModelIndex &parent, int currentDepth = 0);
+
+ bool verify(bool statement, const char *statementStr, const char *description, const char *file, int line);
+
+ template<typename T1, typename T2>
+ bool compare(const T1 &t1, const T2 &t2,
+ const char *actual, const char *expected,
+ const char *file, int line);
+
+ QPointer<QAbstractItemModel> model;
+ QAbstractItemModelTester::FailureReportingMode failureReportingMode;
+
+ struct Changing {
+ QModelIndex parent;
+ int oldSize;
+ QVariant last;
+ QVariant next;
+ };
+ QStack<Changing> insert;
+ QStack<Changing> remove;
+
+ bool fetchingMore;
+
+ QList<QPersistentModelIndex> changing;
+};
+
+/*!
+ \class QAbstractItemModelTester
+ \since 5.11
+ \inmodule QtTest
+
+ \brief The QAbstractItemModelTester class helps testing QAbstractItemModel subclasses.
+
+ The QAbstractItemModelTester class is a utility class to test item models.
+
+ When implementing an item model (that is, a concrete QAbstractItemModel
+ subclass) one must abide to a very strict set of rules that ensure
+ consistency for users of the model (views, proxy models, and so on).
+
+ For instance, for a given index, a model's reimplementation of
+ \l{QAbstractItemModel::hasChildren()}{hasChildren()} must be consistent
+ with the values returned by \l{QAbstractItemModel::rowCount()}{rowCount()}
+ and \l{QAbstractItemModel::columnCount()}{columnCount()}.
+
+ QAbstractItemModelTester helps catching the most common errors in custom
+ item model classes. By performing a series of tests, it
+ will try to check that the model status is consistent at all times. The
+ tests will be repeated automatically every time the model is modified.
+
+ QAbstractItemModelTester employs non-destructive tests, which typically
+ consist in reading data and metadata out of a given item model.
+ QAbstractItemModelTester will also attempt illegal modifications of
+ the model. In models which are properly implemented, such attempts
+ should be rejected, and no data should be changed as a consequence.
+
+ \section1 Usage
+
+ Using QAbstractItemModelTester is straightforward. In a \l{Qt Test Overview}{test case}
+ it is sufficient to create an instance, passing the model that
+ needs to be tested to the constructor:
+
+ \code
+ MyModel *modelToBeTested = ...;
+ auto tester = new QAbstractItemModelTester(modelToBeTested);
+ \endcode
+
+ QAbstractItemModelTester will report testing failures through the
+ Qt Test logging mechanisms.
+
+ It is also possible to use QAbstractItemModelTester outside of a test case.
+ For instance, it may be useful to test an item model used by an application
+ without the need of building an explicit unit test for such a model (which
+ might be challenging). In order to use QAbstractItemModelTester outside of
+ a test case, pass one of the \c QAbstractItemModelTester::FailureReportingMode
+ enumerators to its constructor, therefore specifying how failures should
+ be logged.
+
+ QAbstractItemModelTester may also report additional debugging information
+ as logging messages under the \c qt.modeltest logging category. Such
+ debug logging is disabled by default; refer to the
+ QLoggingCategory documentation to learn how to enable it.
+
+ \note While QAbstractItemModelTester is a valid help for development and
+ testing of custom item models, it does not (and cannot) catch all possible
+ problems in QAbstractItemModel subclasses. Notably, it will never perform
+ meaningful destructive testing of a model, which must be therefore tested
+ separately.
+
+ \sa {Model/View Programming}, QAbstractItemModel
+*/
+
+/*!
+ \enum QAbstractItemModelTester::FailureReportingMode
+
+ This enumeration specifies how QAbstractItemModelTester should report
+ a failure when it tests a QAbstractItemModel subclass.
+
+ \value QtTest The failures will be reported through
+ QtTest's logging mechanism.
+
+ \value Warning The failures will be reported as
+ warning messages in the \c{qt.modeltest} logging category.
+
+ \value Fatal A failure will cause immediate and
+ abnormal program termination. The reason for the failure will be reported
+ using \c{qFatal()}.
+*/
+
+/*!
+ Creates a model tester instance, with the given \a parent, that will test
+ the model \a model.
+*/
+QAbstractItemModelTester::QAbstractItemModelTester(QAbstractItemModel *model, QObject *parent)
+ : QAbstractItemModelTester(model, FailureReportingMode::QtTest, parent)
+{
+}
+
+/*!
+ Creates a model tester instance, with the given \a parent, that will test
+ the model \a model, using the specified \a mode to report test failures.
+
+ \sa QAbstractItemModelTester::FailureReportingMode
+*/
+QAbstractItemModelTester::QAbstractItemModelTester(QAbstractItemModel *model, FailureReportingMode mode, QObject *parent)
+ : QObject(*new QAbstractItemModelTesterPrivate(model, mode), parent)
+{
+ if (!model)
+ qFatal("%s: model must not be null", Q_FUNC_INFO);
+
+ Q_D(QAbstractItemModelTester);
+
+ const auto &runAllTests = [d] { d->runAllTests(); };
+
+ connect(model, &QAbstractItemModel::columnsAboutToBeInserted,
+ this, runAllTests);
+ connect(model, &QAbstractItemModel::columnsAboutToBeRemoved,
+ this, runAllTests);
+ connect(model, &QAbstractItemModel::columnsInserted,
+ this, runAllTests);
+ connect(model, &QAbstractItemModel::columnsRemoved,
+ this, runAllTests);
+ connect(model, &QAbstractItemModel::dataChanged,
+ this, runAllTests);
+ connect(model, &QAbstractItemModel::headerDataChanged,
+ this, runAllTests);
+ connect(model, &QAbstractItemModel::layoutAboutToBeChanged,
+ this, runAllTests);
+ connect(model, &QAbstractItemModel::layoutChanged,
+ this, runAllTests);
+ connect(model, &QAbstractItemModel::modelReset,
+ this, runAllTests);
+ connect(model, &QAbstractItemModel::rowsAboutToBeInserted,
+ this, runAllTests);
+ connect(model, &QAbstractItemModel::rowsAboutToBeRemoved,
+ this, runAllTests);
+ connect(model, &QAbstractItemModel::rowsInserted,
+ this, runAllTests);
+ connect(model, &QAbstractItemModel::rowsRemoved,
+ this, runAllTests);
+
+ // Special checks for changes
+ connect(model, &QAbstractItemModel::layoutAboutToBeChanged,
+ this, [d]{ d->layoutAboutToBeChanged(); });
+ connect(model, &QAbstractItemModel::layoutChanged,
+ this, [d]{ d->layoutChanged(); });
+
+ connect(model, &QAbstractItemModel::rowsAboutToBeInserted,
+ this, [d](const QModelIndex &parent, int start, int end) { d->rowsAboutToBeInserted(parent, start, end); });
+ connect(model, &QAbstractItemModel::rowsAboutToBeRemoved,
+ this, [d](const QModelIndex &parent, int start, int end) { d->rowsAboutToBeRemoved(parent, start, end); });
+ connect(model, &QAbstractItemModel::rowsInserted,
+ this, [d](const QModelIndex &parent, int start, int end) { d->rowsInserted(parent, start, end); });
+ connect(model, &QAbstractItemModel::rowsRemoved,
+ this, [d](const QModelIndex &parent, int start, int end) { d->rowsRemoved(parent, start, end); });
+ connect(model, &QAbstractItemModel::dataChanged,
+ this, [d](const QModelIndex &topLeft, const QModelIndex &bottomRight) { d->dataChanged(topLeft, bottomRight); });
+ connect(model, &QAbstractItemModel::headerDataChanged,
+ this, [d](Qt::Orientation orientation, int start, int end) { d->headerDataChanged(orientation, start, end); });
+
+ runAllTests();
+}
+
+/*!
+ Returns the model that this instance is testing.
+*/
+QAbstractItemModel *QAbstractItemModelTester::model() const
+{
+ Q_D(const QAbstractItemModelTester);
+ return d->model.data();
+}
+
+/*!
+ Returns the mode that this instancing is using to report test failures.
+
+ \sa QAbstractItemModelTester::FailureReportingMode
+*/
+QAbstractItemModelTester::FailureReportingMode QAbstractItemModelTester::failureReportingMode() const
+{
+ Q_D(const QAbstractItemModelTester);
+ return d->failureReportingMode;
+}
+
+QAbstractItemModelTesterPrivate::QAbstractItemModelTesterPrivate(QAbstractItemModel *model, QAbstractItemModelTester::FailureReportingMode failureReportingMode)
+ : model(model),
+ failureReportingMode(failureReportingMode),
+ fetchingMore(false)
+{
+}
+
+void QAbstractItemModelTesterPrivate::runAllTests()
+{
+ if (fetchingMore)
+ return;
+ nonDestructiveBasicTest();
+ rowAndColumnCount();
+ hasIndex();
+ index();
+ parent();
+ data();
+}
+
+/*
+ nonDestructiveBasicTest tries to call a number of the basic functions (not all)
+ to make sure the model doesn't outright segfault, testing the functions that makes sense.
+*/
+void QAbstractItemModelTesterPrivate::nonDestructiveBasicTest()
+{
+ MODELTESTER_VERIFY(!model->buddy(QModelIndex()).isValid());
+ model->canFetchMore(QModelIndex());
+ MODELTESTER_VERIFY(model->columnCount(QModelIndex()) >= 0);
+ fetchingMore = true;
+ model->fetchMore(QModelIndex());
+ fetchingMore = false;
+ Qt::ItemFlags flags = model->flags(QModelIndex());
+ MODELTESTER_VERIFY(flags == Qt::ItemIsDropEnabled || flags == 0);
+ model->hasChildren(QModelIndex());
+ model->hasIndex(0, 0);
+ QVariant cache;
+ model->match(QModelIndex(), -1, cache);
+ model->mimeTypes();
+ MODELTESTER_VERIFY(!model->parent(QModelIndex()).isValid());
+ MODELTESTER_VERIFY(model->rowCount() >= 0);
+ model->span(QModelIndex());
+ model->supportedDropActions();
+ model->roleNames();
+}
+
+/*
+ Tests model's implementation of QAbstractItemModel::rowCount(),
+ columnCount() and hasChildren().
+
+ Models that are dynamically populated are not as fully tested here.
+ */
+void QAbstractItemModelTesterPrivate::rowAndColumnCount()
+{
+ if (!model->hasChildren())
+ return;
+
+ QModelIndex topIndex = model->index(0, 0, QModelIndex());
+
+ // check top row
+ int rows = model->rowCount(topIndex);
+ MODELTESTER_VERIFY(rows >= 0);
+
+ int columns = model->columnCount(topIndex);
+ MODELTESTER_VERIFY(columns >= 0);
+
+ if (rows == 0 || columns == 0)
+ return;
+
+ MODELTESTER_VERIFY(model->hasChildren(topIndex));
+
+ QModelIndex secondLevelIndex = model->index(0, 0, topIndex);
+ MODELTESTER_VERIFY(secondLevelIndex.isValid());
+
+ rows = model->rowCount(secondLevelIndex);
+ MODELTESTER_VERIFY(rows >= 0);
+
+ columns = model->columnCount(secondLevelIndex);
+ MODELTESTER_VERIFY(columns >= 0);
+
+ if (rows == 0 || columns == 0)
+ return;
+
+ MODELTESTER_VERIFY(model->hasChildren(secondLevelIndex));
+
+ // rowCount() / columnCount() are tested more extensively in checkChildren()
+}
+
+/*
+ Tests model's implementation of QAbstractItemModel::hasIndex()
+ */
+void QAbstractItemModelTesterPrivate::hasIndex()
+{
+ // Make sure that invalid values returns an invalid index
+ MODELTESTER_VERIFY(!model->hasIndex(-2, -2));
+ MODELTESTER_VERIFY(!model->hasIndex(-2, 0));
+ MODELTESTER_VERIFY(!model->hasIndex(0, -2));
+
+ const int rows = model->rowCount();
+ const int columns = model->columnCount();
+
+ // check out of bounds
+ MODELTESTER_VERIFY(!model->hasIndex(rows, columns));
+ MODELTESTER_VERIFY(!model->hasIndex(rows + 1, columns + 1));
+
+ if (rows > 0 && columns > 0)
+ MODELTESTER_VERIFY(model->hasIndex(0, 0));
+
+ // hasIndex() is tested more extensively in checkChildren(),
+ // but this catches the big mistakes
+}
+
+/*
+ Tests model's implementation of QAbstractItemModel::index()
+ */
+void QAbstractItemModelTesterPrivate::index()
+{
+ const int rows = model->rowCount();
+ const int columns = model->columnCount();
+
+ for (int row = 0; row < rows; ++row) {
+ for (int column = 0; column < columns; ++column) {
+ // Make sure that the same index is *always* returned
+ QModelIndex a = model->index(row, column);
+ QModelIndex b = model->index(row, column);
+ MODELTESTER_VERIFY(a.isValid());
+ MODELTESTER_VERIFY(b.isValid());
+ MODELTESTER_COMPARE(a, b);
+ }
+ }
+
+ // index() is tested more extensively in checkChildren(),
+ // but this catches the big mistakes
+}
+
+/*
+ Tests model's implementation of QAbstractItemModel::parent()
+ */
+void QAbstractItemModelTesterPrivate::parent()
+{
+ // Make sure the model won't crash and will return an invalid QModelIndex
+ // when asked for the parent of an invalid index.
+ MODELTESTER_VERIFY(!model->parent(QModelIndex()).isValid());
+
+ if (!model->hasChildren())
+ return;
+
+ // Column 0 | Column 1 |
+ // QModelIndex() | |
+ // \- topIndex | topIndex1 |
+ // \- childIndex | childIndex1 |
+
+ // Common error test #1, make sure that a top level index has a parent
+ // that is a invalid QModelIndex.
+ QModelIndex topIndex = model->index(0, 0, QModelIndex());
+ MODELTESTER_VERIFY(!model->parent(topIndex).isValid());
+
+ // Common error test #2, make sure that a second level index has a parent
+ // that is the first level index.
+ if (model->hasChildren(topIndex)) {
+ QModelIndex childIndex = model->index(0, 0, topIndex);
+ MODELTESTER_VERIFY(childIndex.isValid());
+ MODELTESTER_COMPARE(model->parent(childIndex), topIndex);
+ }
+
+ // Common error test #3, the second column should NOT have the same children
+ // as the first column in a row.
+ // Usually the second column shouldn't have children.
+ if (model->hasIndex(0, 1)) {
+ QModelIndex topIndex1 = model->index(0, 1, QModelIndex());
+ MODELTESTER_VERIFY(topIndex1.isValid());
+ if (model->hasChildren(topIndex) && model->hasChildren(topIndex1)) {
+ QModelIndex childIndex = model->index(0, 0, topIndex);
+ MODELTESTER_VERIFY(childIndex.isValid());
+ QModelIndex childIndex1 = model->index(0, 0, topIndex1);
+ MODELTESTER_VERIFY(childIndex1.isValid());
+ MODELTESTER_VERIFY(childIndex != childIndex1);
+ }
+ }
+
+ // Full test, walk n levels deep through the model making sure that all
+ // parent's children correctly specify their parent.
+ checkChildren(QModelIndex());
+}
+
+/*
+ Called from the parent() test.
+
+ A model that returns an index of parent X should also return X when asking
+ for the parent of the index.
+
+ This recursive function does pretty extensive testing on the whole model in an
+ effort to catch edge cases.
+
+ This function assumes that rowCount(), columnCount() and index() already work.
+ If they have a bug it will point it out, but the above tests should have already
+ found the basic bugs because it is easier to figure out the problem in
+ those tests then this one.
+ */
+void QAbstractItemModelTesterPrivate::checkChildren(const QModelIndex &parent, int currentDepth)
+{
+ // First just try walking back up the tree.
+ QModelIndex p = parent;
+ while (p.isValid())
+ p = p.parent();
+
+ // For models that are dynamically populated
+ if (model->canFetchMore(parent)) {
+ fetchingMore = true;
+ model->fetchMore(parent);
+ fetchingMore = false;
+ }
+
+ const int rows = model->rowCount(parent);
+ const int columns = model->columnCount(parent);
+
+ if (rows > 0)
+ MODELTESTER_VERIFY(model->hasChildren(parent));
+
+ // Some further testing against rows(), columns(), and hasChildren()
+ MODELTESTER_VERIFY(rows >= 0);
+ MODELTESTER_VERIFY(columns >= 0);
+ if (rows > 0 && columns > 0)
+ MODELTESTER_VERIFY(model->hasChildren(parent));
+
+ const QModelIndex topLeftChild = model->index(0, 0, parent);
+
+ MODELTESTER_VERIFY(!model->hasIndex(rows, 0, parent));
+ MODELTESTER_VERIFY(!model->hasIndex(rows + 1, 0, parent));
+
+ for (int r = 0; r < rows; ++r) {
+ MODELTESTER_VERIFY(!model->hasIndex(r, columns, parent));
+ MODELTESTER_VERIFY(!model->hasIndex(r, columns + 1, parent));
+ for (int c = 0; c < columns; ++c) {
+ MODELTESTER_VERIFY(model->hasIndex(r, c, parent));
+ QModelIndex index = model->index(r, c, parent);
+ // rowCount() and columnCount() said that it existed...
+ if (!index.isValid())
+ qCWarning(lcModelTest) << "Got invalid index at row=" << r << "col=" << c << "parent=" << parent;
+ MODELTESTER_VERIFY(index.isValid());
+
+ // index() should always return the same index when called twice in a row
+ QModelIndex modifiedIndex = model->index(r, c, parent);
+ MODELTESTER_COMPARE(index, modifiedIndex);
+
+ {
+ const QModelIndex sibling = model->sibling(r, c, topLeftChild);
+ MODELTESTER_COMPARE(index, sibling);
+ }
+ {
+ const QModelIndex sibling = topLeftChild.sibling(r, c);
+ MODELTESTER_COMPARE(index, sibling);
+ }
+
+ // Some basic checking on the index that is returned
+ MODELTESTER_COMPARE(index.model(), model);
+ MODELTESTER_COMPARE(index.row(), r);
+ MODELTESTER_COMPARE(index.column(), c);
+
+ // If the next test fails here is some somewhat useful debug you play with.
+ if (model->parent(index) != parent) {
+ qCWarning(lcModelTest) << "Inconsistent parent() implementation detected:";
+ qCWarning(lcModelTest) << " index=" << index << "exp. parent=" << parent << "act. parent=" << model->parent(index);
+ qCWarning(lcModelTest) << " row=" << r << "col=" << c << "depth=" << currentDepth;
+ qCWarning(lcModelTest) << " data for child" << model->data(index).toString();
+ qCWarning(lcModelTest) << " data for parent" << model->data(parent).toString();
+ }
+
+ // Check that we can get back our real parent.
+ MODELTESTER_COMPARE(model->parent(index), parent);
+
+ QPersistentModelIndex persistentIndex = index;
+
+ // recursively go down the children
+ if (model->hasChildren(index) && currentDepth < 10)
+ checkChildren(index, ++currentDepth);
+
+ // make sure that after testing the children that the index doesn't change.
+ QModelIndex newerIndex = model->index(r, c, parent);
+ MODELTESTER_COMPARE(persistentIndex, newerIndex);
+ }
+ }
+}
+
+/*
+ Tests model's implementation of QAbstractItemModel::data()
+ */
+void QAbstractItemModelTesterPrivate::data()
+{
+ if (!model->hasChildren())
+ return;
+
+ MODELTESTER_VERIFY(model->index(0, 0).isValid());
+
+ // General Purpose roles that should return a QString
+ QVariant variant;
+ variant = model->data(model->index(0, 0), Qt::DisplayRole);
+ if (variant.isValid())
+ MODELTESTER_VERIFY(variant.canConvert<QString>());
+ variant = model->data(model->index(0, 0), Qt::ToolTipRole);
+ if (variant.isValid())
+ MODELTESTER_VERIFY(variant.canConvert<QString>());
+ variant = model->data(model->index(0, 0), Qt::StatusTipRole);
+ if (variant.isValid())
+ MODELTESTER_VERIFY(variant.canConvert<QString>());
+ variant = model->data(model->index(0, 0), Qt::WhatsThisRole);
+ if (variant.isValid())
+ MODELTESTER_VERIFY(variant.canConvert<QString>());
+
+ // General Purpose roles that should return a QSize
+ variant = model->data(model->index(0, 0), Qt::SizeHintRole);
+ if (variant.isValid())
+ MODELTESTER_VERIFY(variant.canConvert<QSize>());
+
+ // Check that the alignment is one we know about
+ QVariant textAlignmentVariant = model->data(model->index(0, 0), Qt::TextAlignmentRole);
+ if (textAlignmentVariant.isValid()) {
+ Qt::Alignment alignment = textAlignmentVariant.value<Qt::Alignment>();
+ MODELTESTER_COMPARE(alignment, (alignment & (Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask)));
+ }
+
+ // Check that the "check state" is one we know about.
+ QVariant checkStateVariant = model->data(model->index(0, 0), Qt::CheckStateRole);
+ if (checkStateVariant.isValid()) {
+ int state = checkStateVariant.toInt();
+ MODELTESTER_VERIFY(state == Qt::Unchecked
+ || state == Qt::PartiallyChecked
+ || state == Qt::Checked);
+ }
+
+ Q_Q(QAbstractItemModelTester);
+
+ if (!QTestPrivate::testDataGuiRoles(q))
+ return;
+}
+
+/*
+ Store what is about to be inserted to make sure it actually happens
+
+ \sa rowsInserted()
+ */
+void QAbstractItemModelTesterPrivate::rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
+{
+ qCDebug(lcModelTest) << "rowsAboutToBeInserted"
+ << "start=" << start << "end=" << end << "parent=" << parent
+ << "parent data=" << model->data(parent).toString()
+ << "current count of parent=" << model->rowCount(parent)
+ << "last before insertion=" << model->index(start - 1, 0, parent) << model->data(model->index(start - 1, 0, parent));
+
+ Changing c;
+ c.parent = parent;
+ c.oldSize = model->rowCount(parent);
+ c.last = (start - 1 >= 0) ? model->index(start - 1, 0, parent).data() : QVariant();
+ c.next = (start < c.oldSize) ? model->index(start, 0, parent).data() : QVariant();
+ insert.push(c);
+}
+
+/*
+ Confirm that what was said was going to happen actually did
+
+ \sa rowsAboutToBeInserted()
+ */
+void QAbstractItemModelTesterPrivate::rowsInserted(const QModelIndex &parent, int start, int end)
+{
+ qCDebug(lcModelTest) << "rowsInserted"
+ << "start=" << start << "end=" << end << "parent=" << parent
+ << "parent data=" << model->data(parent).toString()
+ << "current count of parent=" << model->rowCount(parent);
+
+ for (int i = start; i <= end; ++i) {
+ qCDebug(lcModelTest) << " itemWasInserted:" << i
+ << model->index(i, 0, parent).data();
+ }
+
+
+ Changing c = insert.pop();
+ MODELTESTER_COMPARE(parent, c.parent);
+
+ MODELTESTER_COMPARE(model->rowCount(parent), c.oldSize + (end - start + 1));
+ if (start - 1 >= 0)
+ MODELTESTER_COMPARE(model->data(model->index(start - 1, 0, c.parent)), c.last);
+
+ if (end + 1 < model->rowCount(c.parent)) {
+ if (c.next != model->data(model->index(end + 1, 0, c.parent))) {
+ qDebug() << start << end;
+ for (int i = 0; i < model->rowCount(); ++i)
+ qDebug() << model->index(i, 0).data().toString();
+ qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent));
+ }
+
+ MODELTESTER_COMPARE(model->data(model->index(end + 1, 0, c.parent)), c.next);
+ }
+}
+
+void QAbstractItemModelTesterPrivate::layoutAboutToBeChanged()
+{
+ for (int i = 0; i < qBound(0, model->rowCount(), 100); ++i)
+ changing.append(QPersistentModelIndex(model->index(i, 0)));
+}
+
+void QAbstractItemModelTesterPrivate::layoutChanged()
+{
+ for (int i = 0; i < changing.count(); ++i) {
+ QPersistentModelIndex p = changing[i];
+ MODELTESTER_COMPARE(model->index(p.row(), p.column(), p.parent()), QModelIndex(p));
+ }
+ changing.clear();
+}
+
+/*
+ Store what is about to be inserted to make sure it actually happens
+
+ \sa rowsRemoved()
+ */
+void QAbstractItemModelTesterPrivate::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+{
+ qCDebug(lcModelTest) << "rowsAboutToBeRemoved"
+ << "start=" << start << "end=" << end << "parent=" << parent
+ << "parent data=" << model->data(parent).toString()
+ << "current count of parent=" << model->rowCount(parent)
+ << "last before removal=" << model->index(start - 1, 0, parent) << model->data(model->index(start - 1, 0, parent));
+
+ Changing c;
+ c.parent = parent;
+ c.oldSize = model->rowCount(parent);
+ c.last = model->data(model->index(start - 1, 0, parent));
+ c.next = model->data(model->index(end + 1, 0, parent));
+ remove.push(c);
+}
+
+/*
+ Confirm that what was said was going to happen actually did
+
+ \sa rowsAboutToBeRemoved()
+ */
+void QAbstractItemModelTesterPrivate::rowsRemoved(const QModelIndex &parent, int start, int end)
+{
+ qCDebug(lcModelTest) << "rowsRemoved"
+ << "start=" << start << "end=" << end << "parent=" << parent
+ << "parent data=" << model->data(parent).toString()
+ << "current count of parent=" << model->rowCount(parent);
+
+ Changing c = remove.pop();
+ MODELTESTER_COMPARE(parent, c.parent);
+ MODELTESTER_COMPARE(model->rowCount(parent), c.oldSize - (end - start + 1));
+ MODELTESTER_COMPARE(model->data(model->index(start - 1, 0, c.parent)), c.last);
+ MODELTESTER_COMPARE(model->data(model->index(start, 0, c.parent)), c.next);
+}
+
+void QAbstractItemModelTesterPrivate::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+{
+ MODELTESTER_VERIFY(topLeft.isValid());
+ MODELTESTER_VERIFY(bottomRight.isValid());
+ QModelIndex commonParent = bottomRight.parent();
+ MODELTESTER_COMPARE(topLeft.parent(), commonParent);
+ MODELTESTER_VERIFY(topLeft.row() <= bottomRight.row());
+ MODELTESTER_VERIFY(topLeft.column() <= bottomRight.column());
+ int rowCount = model->rowCount(commonParent);
+ int columnCount = model->columnCount(commonParent);
+ MODELTESTER_VERIFY(bottomRight.row() < rowCount);
+ MODELTESTER_VERIFY(bottomRight.column() < columnCount);
+}
+
+void QAbstractItemModelTesterPrivate::headerDataChanged(Qt::Orientation orientation, int start, int end)
+{
+ MODELTESTER_VERIFY(start >= 0);
+ MODELTESTER_VERIFY(end >= 0);
+ MODELTESTER_VERIFY(start <= end);
+ int itemCount = orientation == Qt::Vertical ? model->rowCount() : model->columnCount();
+ MODELTESTER_VERIFY(start < itemCount);
+ MODELTESTER_VERIFY(end < itemCount);
+}
+
+bool QAbstractItemModelTesterPrivate::verify(bool statement,
+ const char *statementStr, const char *description,
+ const char *file, int line)
+{
+ static const char formatString[] = "FAIL! %s (%s) returned FALSE (%s:%d)";
+
+ switch (failureReportingMode) {
+ case QAbstractItemModelTester::FailureReportingMode::QtTest:
+ return QTest::qVerify(statement, statementStr, description, file, line);
+ break;
+
+ case QAbstractItemModelTester::FailureReportingMode::Warning:
+ if (!statement)
+ qCWarning(lcModelTest, formatString, statementStr, description, file, line);
+ break;
+
+ case QAbstractItemModelTester::FailureReportingMode::Fatal:
+ if (!statement)
+ qFatal(formatString, statementStr, description, file, line);
+ break;
+ }
+
+ return statement;
+}
+
+
+template<typename T1, typename T2>
+bool QAbstractItemModelTesterPrivate::compare(const T1 &t1, const T2 &t2,
+ const char *actual, const char *expected,
+ const char *file, int line)
+{
+ const bool result = static_cast<bool>(t1 == t2);
+
+ static const char formatString[] = "FAIL! Compared values are not the same:\n Actual (%s) %s\n Expected (%s) %s\n (%s:%d)";
+
+ switch (failureReportingMode) {
+ case QAbstractItemModelTester::FailureReportingMode::QtTest:
+ return QTest::qCompare(t1, t2, actual, expected, file, line);
+ break;
+
+ case QAbstractItemModelTester::FailureReportingMode::Warning:
+ if (!result)
+ qCWarning(lcModelTest, formatString, actual, QTest::toString(t1), expected, QTest::toString(t2), file, line);
+ break;
+
+ case QAbstractItemModelTester::FailureReportingMode::Fatal:
+ if (!result)
+ qFatal(formatString, actual, QTest::toString(t1), expected, QTest::toString(t2), file, line);
+ break;
+ }
+
+ return result;
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/testlib/qabstractitemmodeltester.h b/src/testlib/qabstractitemmodeltester.h
new file mode 100644
index 0000000000..617e189817
--- /dev/null
+++ b/src/testlib/qabstractitemmodeltester.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTITEMMODELTESTER_H
+#define QABSTRACTITEMMODELTESTER_H
+
+#include <QtCore/QObject>
+#include <QtTest/qtest_global.h>
+
+#ifdef QT_GUI_LIB
+#include <QtGui/QFont>
+#include <QtGui/QColor>
+#include <QtGui/QBrush>
+#include <QtGui/QPixmap>
+#include <QtGui/QImage>
+#include <QtGui/QIcon>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractItemModel;
+class QAbstractItemModelTester;
+class QAbstractItemModelTesterPrivate;
+
+namespace QTestPrivate {
+inline bool testDataGuiRoles(QAbstractItemModelTester *tester);
+}
+
+class Q_TESTLIB_EXPORT QAbstractItemModelTester : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QAbstractItemModelTester)
+
+public:
+ enum class FailureReportingMode {
+ QtTest,
+ Warning,
+ Fatal
+ };
+
+ QAbstractItemModelTester(QAbstractItemModel *model, QObject *parent = nullptr);
+ QAbstractItemModelTester(QAbstractItemModel *model, FailureReportingMode mode, QObject *parent = nullptr);
+
+ QAbstractItemModel *model() const;
+ FailureReportingMode failureReportingMode() const;
+
+private:
+ friend inline bool QTestPrivate::testDataGuiRoles(QAbstractItemModelTester *tester);
+ bool verify(bool statement, const char *statementStr, const char *description, const char *file, int line);
+};
+
+namespace QTestPrivate {
+inline bool testDataGuiRoles(QAbstractItemModelTester *tester)
+{
+#ifdef QT_GUI_LIB
+
+#define MODELTESTER_VERIFY(statement) \
+do { \
+ if (!tester->verify(static_cast<bool>(statement), #statement, "", __FILE__, __LINE__)) \
+ return false; \
+} while (false)
+
+ const auto model = tester->model();
+ Q_ASSERT(model);
+
+ if (!model->hasChildren())
+ return true;
+
+ QVariant variant;
+
+ variant = model->data(model->index(0, 0), Qt::DecorationRole);
+ if (variant.isValid()) {
+ MODELTESTER_VERIFY(variant.canConvert<QPixmap>()
+ || variant.canConvert<QImage>()
+ || variant.canConvert<QIcon>()
+ || variant.canConvert<QColor>()
+ || variant.canConvert<QBrush>());
+ }
+
+ // General Purpose roles that should return a QFont
+ variant = model->data(model->index(0, 0), Qt::FontRole);
+ if (variant.isValid())
+ MODELTESTER_VERIFY(variant.canConvert<QFont>());
+
+ // General Purpose roles that should return a QColor or a QBrush
+ variant = model->data(model->index(0, 0), Qt::BackgroundColorRole);
+ if (variant.isValid())
+ MODELTESTER_VERIFY(variant.canConvert<QColor>() || variant.canConvert<QBrush>());
+
+ variant = model->data(model->index(0, 0), Qt::TextColorRole);
+ if (variant.isValid())
+ MODELTESTER_VERIFY(variant.canConvert<QColor>() || variant.canConvert<QBrush>());
+
+#undef MODELTESTER_VERIFY
+
+#else
+ Q_UNUSED(tester);
+#endif // QT_GUI_LIB
+
+ return true;
+}
+} // namespaceQTestPrivate
+
+QT_END_NAMESPACE
+
+#endif // QABSTRACTITEMMODELTESTER_H
diff --git a/src/testlib/qbenchmarkmetric.cpp b/src/testlib/qbenchmarkmetric.cpp
index 0ba55dbeb7..0f4f915ed3 100644
--- a/src/testlib/qbenchmarkmetric.cpp
+++ b/src/testlib/qbenchmarkmetric.cpp
@@ -40,6 +40,53 @@
#include <QtTest/private/qbenchmarkmetric_p.h>
+QT_BEGIN_NAMESPACE
+
+namespace QTest {
+
+struct QBenchmarkMetricKey {
+ int metric;
+ const char * name;
+ const char * unit;
+};
+
+static const QBenchmarkMetricKey entries[] = {
+ { FramesPerSecond, "FramesPerSecond", "fps" },
+ { BitsPerSecond, "BitsPerSecond", "bits/s" },
+ { BytesPerSecond, "BytesPerSecond", "bytes/s" },
+ { WalltimeMilliseconds, "WalltimeMilliseconds", "msecs" },
+ { CPUTicks, "CPUTicks", "CPU ticks" },
+ { InstructionReads, "InstructionReads", "instruction reads" },
+ { Events, "Events", "events" },
+ { WalltimeNanoseconds, "WalltimeNanoseconds", "nsecs" },
+ { BytesAllocated, "BytesAllocated", "bytes" },
+ { CPUMigrations, "CPUMigrations", "CPU migrations" },
+ { CPUCycles, "CPUCycles", "CPU cycles" },
+ { BusCycles, "BusCycles", "bus cycles" },
+ { StalledCycles, "StalledCycles", "stalled cycles" },
+ { Instructions, "Instructions", "instructions" },
+ { BranchInstructions, "BranchInstructions", "branch instructions" },
+ { BranchMisses, "BranchMisses", "branch misses" },
+ { CacheReferences, "CacheReferences", "cache references" },
+ { CacheReads, "CacheReads", "cache loads" },
+ { CacheWrites, "CacheWrites", "cache stores" },
+ { CachePrefetches, "CachePrefetches", "cache prefetches" },
+ { CacheMisses, "CacheMisses", "cache misses" },
+ { CacheReadMisses, "CacheReadMisses", "cache load misses" },
+ { CacheWriteMisses, "CacheWriteMisses", "cache store misses" },
+ { CachePrefetchMisses, "CachePrefetchMisses", "cache prefetch misses" },
+ { ContextSwitches, "ContextSwitches", "context switches" },
+ { PageFaults, "PageFaults", "page faults" },
+ { MinorPageFaults, "MinorPageFaults", "minor page faults" },
+ { MajorPageFaults, "MajorPageFaults", "major page faults" },
+ { AlignmentFaults, "AlignmentFaults", "alignment faults" },
+ { EmulationFaults, "EmulationFaults", "emulation faults" },
+ { RefCPUCycles, "RefCPUCycles", "Reference CPU cycles" },
+};
+static const int NumEntries = sizeof(entries) / sizeof(entries[0]);
+
+}
+
/*!
\enum QTest::QBenchmarkMetric
\since 4.7
@@ -92,73 +139,11 @@
*/
const char * QTest::benchmarkMetricName(QBenchmarkMetric metric)
{
- switch (metric) {
- case FramesPerSecond:
- return "FramesPerSecond";
- case BitsPerSecond:
- return "BitsPerSecond";
- case BytesPerSecond:
- return "BytesPerSecond";
- case WalltimeMilliseconds:
- return "WalltimeMilliseconds";
- case Events:
- return "Events";
- case CPUTicks:
- return "CPUTicks";
- case CPUMigrations:
- return "CPUMigrations";
- case CPUCycles:
- return "CPUCycles";
- case RefCPUCycles:
- return "RefCPUCycles";
- case BusCycles:
- return "BusCycles";
- case StalledCycles:
- return "StalledCycles";
- case InstructionReads:
- return "InstructionReads";
- case Instructions:
- return "Instructions";
- case WalltimeNanoseconds:
- return "WalltimeNanoseconds";
- case BytesAllocated:
- return "BytesAllocated";
- case BranchInstructions:
- return "BranchInstructions";
- case BranchMisses:
- return "BranchMisses";
- case CacheReferences:
- return "CacheReferences";
- case CacheReads:
- return "CacheReads";
- case CacheWrites:
- return "CacheWrites";
- case CachePrefetches:
- return "CachePrefetches";
- case CacheMisses:
- return "CacheMisses";
- case CacheReadMisses:
- return "CacheReadMisses";
- case CacheWriteMisses:
- return "CacheWriteMisses";
- case CachePrefetchMisses:
- return "CachePrefetchMisses";
- case ContextSwitches:
- return "ContextSwitches";
- case PageFaults:
- return "PageFaults";
- case MinorPageFaults:
- return "MinorPageFaults";
- case MajorPageFaults:
- return "MajorPageFaults";
- case AlignmentFaults:
- return "AlignmentFaults";
- case EmulationFaults:
- return "EmulationFaults";
- default:
- return "";
- }
-};
+ if (metric >= 0 && metric < QTest::NumEntries)
+ return entries[metric].name;
+
+ return "";
+}
/*!
\since 4.7
@@ -166,71 +151,10 @@ const char * QTest::benchmarkMetricName(QBenchmarkMetric metric)
*/
const char * QTest::benchmarkMetricUnit(QBenchmarkMetric metric)
{
- switch (metric) {
- case FramesPerSecond:
- return "fps";
- case BitsPerSecond:
- return "bits/s";
- case BytesPerSecond:
- return "bytes/s";
- case WalltimeMilliseconds:
- return "msecs";
- case Events:
- return "events";
- case CPUTicks:
- return "CPU ticks";
- case CPUMigrations:
- return "CPU migrations";
- case CPUCycles:
- return "CPU cycles";
- case RefCPUCycles:
- return "Reference CPU cycles";
- case BusCycles:
- return "bus cycles";
- case StalledCycles:
- return "stalled cycles";
- case InstructionReads:
- return "instruction reads";
- case Instructions:
- return "instructions";
- case WalltimeNanoseconds:
- return "nsecs";
- case BytesAllocated:
- return "bytes";
- case BranchInstructions:
- return "branch instructions";
- case BranchMisses:
- return "branch misses";
- case CacheReferences:
- return "cache references";
- case CacheReads:
- return "cache loads";
- case CacheWrites:
- return "cache stores";
- case CachePrefetches:
- return "cache prefetches";
- case CacheMisses:
- return "cache misses";
- case CacheReadMisses:
- return "cache load misses";
- case CacheWriteMisses:
- return "cache store misses";
- case CachePrefetchMisses:
- return "cache prefetch misses";
- case ContextSwitches:
- return "context switches";
- case PageFaults:
- return "page faults";
- case MinorPageFaults:
- return "minor page faults";
- case MajorPageFaults:
- return "major page faults";
- case AlignmentFaults:
- return "alignment faults";
- case EmulationFaults:
- return "emulation faults";
- default:
- return "";
- }
+ if (metric >= 0 && metric < QTest::NumEntries)
+ return entries[metric].unit;
+
+ return "";
}
+QT_END_NAMESPACE
diff --git a/src/testlib/qbenchmarkperfevents.cpp b/src/testlib/qbenchmarkperfevents.cpp
index d6db40ce52..91f0792338 100644
--- a/src/testlib/qbenchmarkperfevents.cpp
+++ b/src/testlib/qbenchmarkperfevents.cpp
@@ -106,7 +106,9 @@ static void initPerf()
}
}
-/*!
+// This class does not exist in the API so it's qdoc comment marker was removed.
+
+/*
\class QBenchmarkPerfEvents
\brief The Linux perf events benchmark backend
diff --git a/src/testlib/qbenchmarkperfevents_p.h b/src/testlib/qbenchmarkperfevents_p.h
index 085dc620d7..86ba556549 100644
--- a/src/testlib/qbenchmarkperfevents_p.h
+++ b/src/testlib/qbenchmarkperfevents_p.h
@@ -60,16 +60,16 @@ class QBenchmarkPerfEventsMeasurer : public QBenchmarkMeasurerBase
public:
QBenchmarkPerfEventsMeasurer();
~QBenchmarkPerfEventsMeasurer();
- virtual void init() Q_DECL_OVERRIDE;
- virtual void start() Q_DECL_OVERRIDE;
- virtual qint64 checkpoint() Q_DECL_OVERRIDE;
- virtual qint64 stop() Q_DECL_OVERRIDE;
- virtual bool isMeasurementAccepted(qint64 measurement) Q_DECL_OVERRIDE;
- virtual int adjustIterationCount(int suggestion) Q_DECL_OVERRIDE;
- virtual int adjustMedianCount(int suggestion) Q_DECL_OVERRIDE;
- virtual bool repeatCount() Q_DECL_OVERRIDE { return 1; }
- virtual bool needsWarmupIteration() Q_DECL_OVERRIDE { return true; }
- virtual QTest::QBenchmarkMetric metricType() Q_DECL_OVERRIDE;
+ virtual void init() override;
+ virtual void start() override;
+ virtual qint64 checkpoint() override;
+ virtual qint64 stop() override;
+ virtual bool isMeasurementAccepted(qint64 measurement) override;
+ virtual int adjustIterationCount(int suggestion) override;
+ virtual int adjustMedianCount(int suggestion) override;
+ virtual bool repeatCount() override { return 1; }
+ virtual bool needsWarmupIteration() override { return true; }
+ virtual QTest::QBenchmarkMetric metricType() override;
static bool isAvailable();
static QTest::QBenchmarkMetric metricForEvent(quint32 type, quint64 event_id);
diff --git a/src/testlib/qcsvbenchmarklogger_p.h b/src/testlib/qcsvbenchmarklogger_p.h
index f321494e8a..5840aee0f5 100644
--- a/src/testlib/qcsvbenchmarklogger_p.h
+++ b/src/testlib/qcsvbenchmarklogger_p.h
@@ -61,18 +61,18 @@ public:
QCsvBenchmarkLogger(const char *filename);
~QCsvBenchmarkLogger();
- void startLogging() Q_DECL_OVERRIDE;
- void stopLogging() Q_DECL_OVERRIDE;
+ void startLogging() override;
+ void stopLogging() override;
- void enterTestFunction(const char *function) Q_DECL_OVERRIDE;
- void leaveTestFunction() Q_DECL_OVERRIDE;
+ void enterTestFunction(const char *function) override;
+ void leaveTestFunction() override;
void addIncident(IncidentTypes type, const char *description,
- const char *file = 0, int line = 0) Q_DECL_OVERRIDE;
- void addBenchmarkResult(const QBenchmarkResult &result) Q_DECL_OVERRIDE;
+ const char *file = 0, int line = 0) override;
+ void addBenchmarkResult(const QBenchmarkResult &result) override;
void addMessage(MessageTypes type, const QString &message,
- const char *file = 0, int line = 0) Q_DECL_OVERRIDE;
+ const char *file = 0, int line = 0) override;
};
QT_END_NAMESPACE
diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp
index 77959341cf..25c9655691 100644
--- a/src/testlib/qplaintestlogger.cpp
+++ b/src/testlib/qplaintestlogger.cpp
@@ -223,38 +223,47 @@ void QPlainTestLogger::outputMessage(const char *str)
outputString(str);
}
+static QTestCharBuffer testIdentifier()
+{
+ QTestCharBuffer identifier;
+
+ const char *testObject = QTestResult::currentTestObjectName();
+ const char *testFunction = QTestResult::currentTestFunction() ? QTestResult::currentTestFunction() : "UnknownTestFunc";
+
+ const char *dataTag = QTestResult::currentDataTag() ? QTestResult::currentDataTag() : "";
+ const char *globalDataTag = QTestResult::currentGlobalDataTag() ? QTestResult::currentGlobalDataTag() : "";
+ const char *tagFiller = (dataTag[0] && globalDataTag[0]) ? ":" : "";
+
+ QTest::qt_asprintf(&identifier, "%s::%s(%s%s%s)", testObject, testFunction, globalDataTag, tagFiller, dataTag);
+ return identifier;
+}
+
void QPlainTestLogger::printMessage(const char *type, const char *msg, const char *file, int line)
{
QTEST_ASSERT(type);
QTEST_ASSERT(msg);
- QTestCharBuffer buf;
+ QTestCharBuffer messagePrefix;
- const char *fn = QTestResult::currentTestFunction() ? QTestResult::currentTestFunction()
- : "UnknownTestFunc";
- const char *tag = QTestResult::currentDataTag() ? QTestResult::currentDataTag() : "";
- const char *gtag = QTestResult::currentGlobalDataTag()
- ? QTestResult::currentGlobalDataTag()
- : "";
- const char *filler = (tag[0] && gtag[0]) ? ":" : "";
+ QTestCharBuffer failureLocation;
if (file) {
- QTest::qt_asprintf(&buf, "%s: %s::%s(%s%s%s)%s%s\n"
#ifdef Q_OS_WIN
- "%s(%d) : failure location\n"
+#define FAILURE_LOCATION_STR "\n%s(%d) : failure location"
#else
- " Loc: [%s(%d)]\n"
+#define FAILURE_LOCATION_STR "\n Loc: [%s(%d)]"
#endif
- , type, QTestResult::currentTestObjectName(), fn, gtag, filler, tag,
- msg[0] ? " " : "", msg, file, line);
- } else {
- QTest::qt_asprintf(&buf, "%s: %s::%s(%s%s%s)%s%s\n",
- type, QTestResult::currentTestObjectName(), fn, gtag, filler, tag,
- msg[0] ? " " : "", msg);
+ QTest::qt_asprintf(&failureLocation, FAILURE_LOCATION_STR, file, line);
}
+
+ const char *msgFiller = msg[0] ? " " : "";
+ QTest::qt_asprintf(&messagePrefix, "%s: %s%s%s%s\n",
+ type, testIdentifier().data(), msgFiller, msg, failureLocation.data());
+
// In colored mode, printf above stripped our nonprintable control characters.
// Put them back.
- memcpy(buf.data(), type, strlen(type));
- outputMessage(buf.data());
+ memcpy(messagePrefix.data(), type, strlen(type));
+
+ outputMessage(messagePrefix.data());
}
void QPlainTestLogger::printBenchmarkResult(const QBenchmarkResult &result)
diff --git a/src/testlib/qsignalspy.h b/src/testlib/qsignalspy.h
index 6b1b7e6922..824dc6aaed 100644
--- a/src/testlib/qsignalspy.h
+++ b/src/testlib/qsignalspy.h
@@ -88,7 +88,7 @@ public:
}
if (!QMetaObject::connect(obj, sigIndex, this, memberOffset,
- Qt::DirectConnection, Q_NULLPTR)) {
+ Qt::DirectConnection, nullptr)) {
qWarning("QSignalSpy: QMetaObject::connect returned false. Unable to connect.");
return;
}
@@ -96,7 +96,8 @@ public:
initArgs(mo->method(sigIndex), obj);
}
-#ifdef Q_QDOC
+#ifdef Q_CLANG_QDOC
+ template <typename PointerToMemberFunction>
QSignalSpy(const QObject *object, PointerToMemberFunction signal);
#else
template <typename Func>
@@ -136,7 +137,7 @@ public:
sig = signalMetaMethod.methodSignature();
initArgs(mo->method(sigIndex), obj);
}
-#endif // Q_QDOC
+#endif // Q_CLANG_QDOC
inline bool isValid() const { return !sig.isEmpty(); }
inline QByteArray signal() const { return sig; }
@@ -151,7 +152,7 @@ public:
return count() > origCount;
}
- int qt_metacall(QMetaObject::Call call, int methodId, void **a) Q_DECL_OVERRIDE
+ int qt_metacall(QMetaObject::Call call, int methodId, void **a) override
{
methodId = QObject::qt_metacall(call, methodId, a);
if (methodId < 0)
diff --git a/src/testlib/qsignalspy.qdoc b/src/testlib/qsignalspy.qdoc
index f5c8ad32b3..77affc9a4b 100644
--- a/src/testlib/qsignalspy.qdoc
+++ b/src/testlib/qsignalspy.qdoc
@@ -72,7 +72,7 @@
\snippet code/doc_src_qsignalspy.cpp 4
*/
-/*! \fn QSignalSpy::QSignalSpy(const QObject *object, PointerToMemberFunction signal)
+/*! \fn template <typename PointerToMemberFunction> QSignalSpy::QSignalSpy(const QObject *object, PointerToMemberFunction signal)
\since 5.4
Constructs a new QSignalSpy that listens for emissions of the \a signal
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index ba63df5f36..a5df27e3b9 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -65,9 +65,14 @@ QT_BEGIN_NAMESPACE
namespace QTest
{
+template <> inline char *toString(const QStringView &str)
+{
+ return QTest::toPrettyUnicode(str);
+}
+
template<> inline char *toString(const QString &str)
{
- return QTest::toPrettyUnicode(reinterpret_cast<const ushort *>(str.constData()), str.length());
+ return toString(QStringView(str));
}
template<> inline char *toString(const QLatin1String &str)
@@ -84,21 +89,21 @@ template<> inline char *toString(const QByteArray &ba)
template<> inline char *toString(const QTime &time)
{
return time.isValid()
- ? qstrdup(qPrintable(time.toString(QLatin1String("hh:mm:ss.zzz"))))
+ ? qstrdup(qPrintable(time.toString(QStringViewLiteral("hh:mm:ss.zzz"))))
: qstrdup("Invalid QTime");
}
template<> inline char *toString(const QDate &date)
{
return date.isValid()
- ? qstrdup(qPrintable(date.toString(QLatin1String("yyyy/MM/dd"))))
+ ? qstrdup(qPrintable(date.toString(QStringViewLiteral("yyyy/MM/dd"))))
: qstrdup("Invalid QDate");
}
template<> inline char *toString(const QDateTime &dateTime)
{
return dateTime.isValid()
- ? qstrdup(qPrintable(dateTime.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz[t]"))))
+ ? qstrdup(qPrintable(dateTime.toString(QStringViewLiteral("yyyy/MM/dd hh:mm:ss.zzz[t]"))))
: qstrdup("Invalid QDateTime");
}
#endif // QT_NO_DATESTRING
@@ -194,6 +199,22 @@ template<> inline char *toString(const QVariant &v)
return qstrdup(vstring.constData());
}
+template <typename T1, typename T2>
+inline char *toString(const QPair<T1, T2> &pair)
+{
+ const QScopedArrayPointer<char> first(toString(pair.first));
+ const QScopedArrayPointer<char> second(toString(pair.second));
+ return toString(QString::asprintf("QPair(%s,%s)", first.data(), second.data()));
+}
+
+template <typename T1, typename T2>
+inline char *toString(const std::pair<T1, T2> &pair)
+{
+ const QScopedArrayPointer<char> first(toString(pair.first));
+ const QScopedArrayPointer<char> second(toString(pair.second));
+ return toString(QString::asprintf("std::pair(%s,%s)", first.data(), second.data()));
+}
+
inline char *toString(std::nullptr_t)
{
return toString(QLatin1String("nullptr"));
@@ -242,7 +263,7 @@ inline bool qCompare(QList<T> const &t1, QList<T> const &t2, const char *actual,
delete [] val2;
}
}
- return compare_helper(isOk, msg, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line);
+ return compare_helper(isOk, msg, nullptr, nullptr, actual, expected, file, line);
}
template <>
diff --git a/src/testlib/qtest_gui.h b/src/testlib/qtest_gui.h
index d0d56e7bd0..e5101e6955 100644
--- a/src/testlib/qtest_gui.h
+++ b/src/testlib/qtest_gui.h
@@ -59,10 +59,10 @@
#include <QtGui/qpixmap.h>
#include <QtGui/qimage.h>
#include <QtGui/qregion.h>
-
-#ifdef QT_WIDGETS_LIB
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
#include <QtGui/qicon.h>
-#endif
#if 0
// inform syncqt
@@ -75,12 +75,9 @@ QT_BEGIN_NAMESPACE
namespace QTest
{
-/*!
- \internal
- */
template<> inline char *toString(const QColor &color)
{
- return qstrdup(color.name().toLocal8Bit().constData());
+ return qstrdup(color.name(QColor::HexArgb).toLocal8Bit().constData());
}
template<> inline char *toString(const QRegion &region)
@@ -91,8 +88,8 @@ template<> inline char *toString(const QRegion &region)
} else if (region.isEmpty()) {
result += "empty";
} else {
- const QVector<QRect> &rects = region.rects();
- const int rectCount = rects.size();
+ const auto rects = region.begin();
+ const int rectCount = region.rectCount();
if (rectCount > 1) {
result += QByteArray::number(rectCount);
result += " rectangles, ";
@@ -100,7 +97,7 @@ template<> inline char *toString(const QRegion &region)
for (int i = 0; i < rectCount; ++i) {
if (i)
result += ", ";
- const QRect &r = rects.at(i);
+ const QRect &r = rects[i];
result += QByteArray::number(r.width());
result += 'x';
result += QByteArray::number(r.height());
@@ -116,6 +113,32 @@ template<> inline char *toString(const QRegion &region)
return qstrdup(result.constData());
}
+#if !defined(QT_NO_VECTOR2D) || defined(Q_CLANG_QDOC)
+template<> inline char *toString(const QVector2D &v)
+{
+ QByteArray result = "QVector2D(" + QByteArray::number(double(v.x())) + ", "
+ + QByteArray::number(double(v.y())) + ')';
+ return qstrdup(result.constData());
+}
+#endif // !QT_NO_VECTOR2D
+#if !defined(QT_NO_VECTOR3D) || defined(Q_CLANG_QDOC)
+template<> inline char *toString(const QVector3D &v)
+{
+ QByteArray result = "QVector3D(" + QByteArray::number(double(v.x())) + ", "
+ + QByteArray::number(double(v.y())) + ", " + QByteArray::number(double(v.z())) + ')';
+ return qstrdup(result.constData());
+}
+#endif // !QT_NO_VECTOR3D
+#if !defined(QT_NO_VECTOR4D) || defined(Q_CLANG_QDOC)
+template<> inline char *toString(const QVector4D &v)
+{
+ QByteArray result = "QVector4D(" + QByteArray::number(double(v.x())) + ", "
+ + QByteArray::number(double(v.y())) + ", " + QByteArray::number(double(v.z()))
+ + ", " + QByteArray::number(double(v.w())) + ')';
+ return qstrdup(result.constData());
+}
+#endif // !QT_NO_VECTOR4D
+
inline bool qCompare(QIcon const &t1, QIcon const &t2, const char *actual, const char *expected,
const char *file, int line)
{
@@ -135,24 +158,24 @@ inline bool qCompare(QImage const &t1, QImage const &t2,
qsnprintf(msg, 1024, "Compared QImages differ.\n"
" Actual (%s).isNull(): %d\n"
" Expected (%s).isNull(): %d", actual, t1Null, expected, t2Null);
- return compare_helper(false, msg, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line);
+ return compare_helper(false, msg, nullptr, nullptr, actual, expected, file, line);
}
if (t1Null && t2Null)
- return compare_helper(true, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line);
+ return compare_helper(true, nullptr, nullptr, nullptr, actual, expected, file, line);
if (t1.width() != t2.width() || t1.height() != t2.height()) {
qsnprintf(msg, 1024, "Compared QImages differ in size.\n"
" Actual (%s): %dx%d\n"
" Expected (%s): %dx%d",
actual, t1.width(), t1.height(),
expected, t2.width(), t2.height());
- return compare_helper(false, msg, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line);
+ return compare_helper(false, msg, nullptr, nullptr, actual, expected, file, line);
}
if (t1.format() != t2.format()) {
qsnprintf(msg, 1024, "Compared QImages differ in format.\n"
" Actual (%s): %d\n"
" Expected (%s): %d",
actual, t1.format(), expected, t2.format());
- return compare_helper(false, msg, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line);
+ return compare_helper(false, msg, nullptr, nullptr, actual, expected, file, line);
}
return compare_helper(t1 == t2, "Compared values are not the same",
toString(t1), toString(t2), actual, expected, file, line);
@@ -169,17 +192,17 @@ inline bool qCompare(QPixmap const &t1, QPixmap const &t2, const char *actual, c
qsnprintf(msg, 1024, "Compared QPixmaps differ.\n"
" Actual (%s).isNull(): %d\n"
" Expected (%s).isNull(): %d", actual, t1Null, expected, t2Null);
- return compare_helper(false, msg, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line);
+ return compare_helper(false, msg, nullptr, nullptr, actual, expected, file, line);
}
if (t1Null && t2Null)
- return compare_helper(true, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line);
+ return compare_helper(true, nullptr, nullptr, nullptr, actual, expected, file, line);
if (t1.width() != t2.width() || t1.height() != t2.height()) {
qsnprintf(msg, 1024, "Compared QPixmaps differ in size.\n"
" Actual (%s): %dx%d\n"
" Expected (%s): %dx%d",
actual, t1.width(), t1.height(),
expected, t2.width(), t2.height());
- return compare_helper(false, msg, Q_NULLPTR, Q_NULLPTR, actual, expected, file, line);
+ return compare_helper(false, msg, nullptr, nullptr, actual, expected, file, line);
}
return qCompare(t1.toImage(), t2.toImage(), actual, expected, file, line);
}
diff --git a/src/testlib/qtest_network.h b/src/testlib/qtest_network.h
index 6f6b4c1b8e..b417f03a7f 100644
--- a/src/testlib/qtest_network.h
+++ b/src/testlib/qtest_network.h
@@ -64,10 +64,8 @@ QT_BEGIN_NAMESPACE
namespace QTest
{
-/*!
- \internal
- */
-inline char *toString(const QHostAddress &addr)
+template<>
+inline char *toString<QHostAddress>(const QHostAddress &addr)
{
switch (addr.protocol()) {
case QAbstractSocket::UnknownNetworkLayerProtocol:
@@ -82,9 +80,6 @@ inline char *toString(const QHostAddress &addr)
return toString(addr.toString());
}
-/*!
- \internal
- */
inline char *toString(QNetworkReply::NetworkError code)
{
const QMetaObject *mo = &QNetworkReply::staticMetaObject;
@@ -96,17 +91,11 @@ inline char *toString(QNetworkReply::NetworkError code)
return qstrdup(qme.valueToKey(code));
}
-/*!
- \internal
- */
inline char *toString(const QNetworkCookie &cookie)
{
return toString(cookie.toRawForm());
}
-/*!
- \internal
- */
inline char *toString(const QList<QNetworkCookie> &list)
{
QByteArray result = "QList(";
diff --git a/src/testlib/qtestaccessible.h b/src/testlib/qtestaccessible.h
index 464f87fb5c..0470d15ed7 100644
--- a/src/testlib/qtestaccessible.h
+++ b/src/testlib/qtestaccessible.h
@@ -132,7 +132,7 @@ public:
static void cleanup()
{
delete instance();
- instance() = Q_NULLPTR;
+ instance() = nullptr;
}
static void clearEvents() { eventList().clear(); }
static EventList events() { return eventList(); }
@@ -167,8 +167,8 @@ private:
~QTestAccessibility()
{
- QAccessible::installUpdateHandler(Q_NULLPTR);
- QAccessible::installRootObjectHandler(Q_NULLPTR);
+ QAccessible::installUpdateHandler(nullptr);
+ QAccessible::installRootObjectHandler(nullptr);
}
static void rootObjectHandler(QObject *object)
@@ -273,7 +273,7 @@ private:
static QTestAccessibility *&instance()
{
- static QTestAccessibility *ta = Q_NULLPTR;
+ static QTestAccessibility *ta = nullptr;
return ta;
}
diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp
index 8ad0f13dc2..f430294142 100644
--- a/src/testlib/qtestblacklist.cpp
+++ b/src/testlib/qtestblacklist.cpp
@@ -58,9 +58,10 @@ QT_BEGIN_NAMESPACE
referring to this documentation is kind to readers. Comments can also be used
to indicate the reasons for ignoring particular cases.
- A key names a platform, O/S, distribution, tool-chain or architecture; a !
- prefix reverses what it checks. A version, joined to a key (at present, only
- for distributions and for msvc) with a hyphen, limits the key to the specific
+ The key "ci" applies only when run by COIN. Other keys name platforms,
+ operating systems, distributions, tool-chains or architectures; a ! prefix
+ reverses what it checks. A version, joined to a key (at present, only for
+ distributions and for msvc) with a hyphen, limits the key to the specific
version. A keyword line matches if every key on it applies to the present
run. Successive lines are alternate conditions for ignoring a test.
@@ -70,13 +71,18 @@ QT_BEGIN_NAMESPACE
Subsequent lines give conditions for ignoring this test.
# See qtbase/src/testlib/qtestblacklist.cpp for format
- osx
+ # Test doesn't work on QNX at all
+ qnx
# QTBUG-12345
[testFunction]
linux
windows 64bit
+ # Flaky in COIN on macOS, not reproducible by developers
+ [testSlowly]
+ ci osx
+
# Needs basic C++11 support
[testfunction2:testData]
msvc-2010
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 4c5c9e1eb8..497470464f 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -275,6 +275,11 @@ namespace QTest
static QObject *currentTestObject = 0;
static QString mainSourcePath;
+#if defined(Q_OS_MACOS)
+ bool macNeedsActivate = false;
+ IOPMAssertionID powerID;
+#endif
+
class TestMethods {
Q_DISABLE_COPY(TestMethods)
public:
@@ -578,6 +583,7 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
" -plugins dir : Specify a directory where to search for plugins.\n"
" -input dir/file : Specify the root directory for test cases or a single test case file.\n"
" -translation file : Specify the translation file.\n"
+ " -file-selector dir : Specify a file selector for the QML engine.\n"
);
}
@@ -896,6 +902,10 @@ void TestMethods::invokeTestOnData(int index) const
if (m_cleanupMethod.isValid())
m_cleanupMethod.invoke(QTest::currentTestObject, Qt::DirectConnection);
+ // Process any deleteLater(), like event-loop based apps would do. Fixes memleak reports.
+ if (QCoreApplication::instance())
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+
// If the test isn't a benchmark, finalize the result after cleanup() has finished.
if (!isBenchmark)
QTestResult::finishedCurrentTestDataCleanup();
@@ -1269,6 +1279,16 @@ char *toPrettyCString(const char *p, int length)
return buffer.take();
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+// this used to be the signature up to and including Qt 5.9
+// keep it for BC reasons:
+Q_TESTLIB_EXPORT
+char *toPrettyUnicode(const ushort *p, int length)
+{
+ return toPrettyUnicode(QStringView(p, length));
+}
+#endif
+
/*!
\internal
Returns the same QString but with only the ASCII characters still shown;
@@ -1276,8 +1296,10 @@ char *toPrettyCString(const char *p, int length)
Similar to QDebug::putString().
*/
-char *toPrettyUnicode(const ushort *p, int length)
+char *toPrettyUnicode(QStringView string)
{
+ auto p = reinterpret_cast<const ushort *>(string.utf16());
+ auto length = string.size();
// keep it simple for the vast majority of cases
bool trimmed = false;
QScopedArrayPointer<char> buffer(new char[256]);
@@ -1343,9 +1365,7 @@ void TestMethods::invokeTests(QObject *testObject) const
{
const QMetaObject *metaObject = testObject->metaObject();
QTEST_ASSERT(metaObject);
- QTestLog::startLogging();
QTestResult::setCurrentTestFunction("initTestCase");
- QTestTable::globalTestTable();
if (m_initTestCaseDataMethod.isValid())
m_initTestCaseDataMethod.invoke(testObject, Qt::DirectConnection);
@@ -1370,7 +1390,7 @@ void TestMethods::invokeTests(QObject *testObject) const
if (!QTestResult::skipCurrentTest() && !previousFailed) {
for (int i = 0, count = int(m_methods.size()); i < count; ++i) {
- const char *data = Q_NULLPTR;
+ const char *data = nullptr;
if (i < QTest::testTags.size() && !QTest::testTags.at(i).isEmpty())
data = qstrdup(QTest::testTags.at(i).toLatin1().constData());
const bool ok = invokeTest(i, data, watchDog.data());
@@ -1390,9 +1410,6 @@ void TestMethods::invokeTests(QObject *testObject) const
}
QTestResult::finishedCurrentTestFunction();
QTestResult::setCurrentTestFunction(0);
- QTestTable::clearGlobalTestTable();
-
- QTestLog::stopLogging();
}
#if defined(Q_OS_UNIX)
@@ -1518,7 +1535,7 @@ class DebugSymbolResolver
Q_DISABLE_COPY(DebugSymbolResolver)
public:
struct Symbol {
- Symbol() : name(Q_NULLPTR), address(0) {}
+ Symbol() : name(nullptr), address(0) {}
const char *name; // Must be freed by caller.
DWORD64 address;
@@ -1566,11 +1583,11 @@ void DebugSymbolResolver::cleanup()
if (m_dbgHelpLib)
FreeLibrary(m_dbgHelpLib);
m_dbgHelpLib = 0;
- m_symFromAddr = Q_NULLPTR;
+ m_symFromAddr = nullptr;
}
DebugSymbolResolver::DebugSymbolResolver(HANDLE process)
- : m_process(process), m_dbgHelpLib(0), m_symFromAddr(Q_NULLPTR)
+ : m_process(process), m_dbgHelpLib(0), m_symFromAddr(nullptr)
{
bool success = false;
m_dbgHelpLib = LoadLibraryW(L"dbghelp.dll");
@@ -1650,15 +1667,8 @@ static LONG WINAPI windowsFaultHandler(struct _EXCEPTION_POINTERS *exInfo)
}
#endif // Q_OS_WIN) && !Q_OS_WINRT
-static void qputenvIfEmpty(const char *name, const QByteArray &value)
-{
- if (qEnvironmentVariableIsEmpty(name))
- qputenv(name, value);
-}
-
static void initEnvironment()
{
- qputenvIfEmpty("QT_LOGGING_TO_CONSOLE", "1");
qputenv("QT_QTESTLIB_RUNNING", "1");
}
@@ -1702,23 +1712,27 @@ static void initEnvironment()
int QTest::qExec(QObject *testObject, int argc, char **argv)
{
- initEnvironment();
- QBenchmarkGlobalData benchmarkData;
- QBenchmarkGlobalData::current = &benchmarkData;
+ qInit(testObject, argc, argv);
+ int ret = qRun();
+ qCleanup();
+ return ret;
+}
-#ifdef QTESTLIB_USE_VALGRIND
- int callgrindChildExitCode = 0;
-#endif
+/*! \internal
+ */
+void QTest::qInit(QObject *testObject, int argc, char **argv)
+{
+ initEnvironment();
+ QBenchmarkGlobalData::current = new QBenchmarkGlobalData;
#if defined(Q_OS_MACX)
- bool macNeedsActivate = qApp && (qstrcmp(qApp->metaObject()->className(), "QApplication") == 0);
- IOPMAssertionID powerID;
+ macNeedsActivate = qApp && (qstrcmp(qApp->metaObject()->className(), "QApplication") == 0);
// Don't restore saved window state for auto tests.
QTestPrivate::disableWindowRestore();
-#endif
-#ifndef QT_NO_EXCEPTIONS
- try {
+
+ // Disable App Nap which may cause tests to stall.
+ QTestPrivate::AppNapDisabler appNapDisabler;
#endif
#if defined(Q_OS_MACX)
@@ -1749,6 +1763,24 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
qtest_qParseArgs(argc, argv, false);
+ QTestTable::globalTestTable();
+ QTestLog::startLogging();
+}
+
+/*! \internal
+ */
+int QTest::qRun()
+{
+ QTEST_ASSERT(currentTestObject);
+
+#ifdef QTESTLIB_USE_VALGRIND
+ int callgrindChildExitCode = 0;
+#endif
+
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+
#if defined(Q_OS_WIN)
if (!noCrashHandler) {
# ifndef Q_CC_MINGW
@@ -1784,17 +1816,17 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
for (const QString &tf : qAsConst(QTest::testFunctions)) {
const QByteArray tfB = tf.toLatin1();
const QByteArray signature = tfB + QByteArrayLiteral("()");
- QMetaMethod m = TestMethods::findMethod(testObject, signature.constData());
+ QMetaMethod m = TestMethods::findMethod(currentTestObject, signature.constData());
if (!m.isValid() || !isValidSlot(m)) {
fprintf(stderr, "Unknown test function: '%s'. Possible matches:\n", tfB.constData());
qPrintTestSlots(stderr, tfB.constData());
- fprintf(stderr, "\n%s -functions\nlists all available test functions.\n", argv[0]);
+ fprintf(stderr, "\n%s -functions\nlists all available test functions.\n", QTestResult::currentAppName());
exit(1);
}
commandLineMethods.push_back(m);
}
- TestMethods test(testObject, commandLineMethods);
- test.invokeTests(testObject);
+ TestMethods test(currentTestObject, commandLineMethods);
+ test.invokeTests(currentTestObject);
}
#ifndef QT_NO_EXCEPTIONS
@@ -1819,16 +1851,6 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
}
#endif
- currentTestObject = 0;
-
- QSignalDumper::endDump();
-
-#if defined(Q_OS_MACX)
- if (macNeedsActivate) {
- IOPMAssertionRelease(powerID);
- }
-#endif
-
#ifdef QTESTLIB_USE_VALGRIND
if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess)
return callgrindChildExitCode;
@@ -1838,6 +1860,26 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
return qMin(QTestLog::failCount(), 127);
}
+/*! \internal
+ */
+void QTest::qCleanup()
+{
+ currentTestObject = 0;
+
+ QTestTable::clearGlobalTestTable();
+ QTestLog::stopLogging();
+
+ delete QBenchmarkGlobalData::current;
+ QBenchmarkGlobalData::current = 0;
+
+ QSignalDumper::endDump();
+
+#if defined(Q_OS_MACOS)
+ if (macNeedsActivate)
+ IOPMAssertionRelease(powerID);
+#endif
+}
+
/*!
\overload
\since 4.4
@@ -2244,7 +2286,7 @@ QTestData &QTest::addRow(const char *format, ...)
return *tbl->newData(buf);
}
-/*! \fn void QTest::addColumn(const char *name, T *dummy = 0)
+/*! \fn template <typename T> void QTest::addColumn(const char *name, T *dummy = 0)
Adds a column with type \c{T} to the current test data.
\a name is the name of the column. \a dummy is a workaround
@@ -2375,7 +2417,7 @@ bool QTest::compare_helper(bool success, const char *failureMsg,
return QTestResult::compare(success, failureMsg, val1, val2, actual, expected, file, line);
}
-/*! \fn bool QTest::qCompare(float const &t1, float const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const float &t1, const float &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
bool QTest::qCompare(float const &t1, float const &t2, const char *actual, const char *expected,
@@ -2385,7 +2427,7 @@ bool QTest::qCompare(float const &t1, float const &t2, const char *actual, const
toString(t1), toString(t2), actual, expected, file, line);
}
-/*! \fn bool QTest::qCompare(double const &t1, double const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const double &t1, const double &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
bool QTest::qCompare(double const &t1, double const &t2, const char *actual, const char *expected,
@@ -2395,11 +2437,11 @@ bool QTest::qCompare(double const &t1, double const &t2, const char *actual, con
toString(t1), toString(t2), actual, expected, file, line);
}
-/*! \fn bool QTest::qCompare(double const &t1, float const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const double &t1, const float &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(float const &t1, double const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const float &t1, const double &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
@@ -2496,6 +2538,30 @@ char *QTest::toString(const void *p)
return msg;
}
+/*! \fn char *QTest::toString(const QColor &color)
+ \internal
+ */
+
+/*! \fn char *QTest::toString(const QRegion &region)
+ \internal
+ */
+
+/*! \fn char *QTest::toString(const QHostAddress &addr)
+ \internal
+ */
+
+/*! \fn char *QTest::toString(QNetworkReply::NetworkError code)
+ \internal
+ */
+
+/*! \fn char *QTest::toString(const QNetworkCookie &cookie)
+ \internal
+ */
+
+/*! \fn char *QTest::toString(const QList<QNetworkCookie> &list)
+ \internal
+ */
+
/*! \internal
*/
bool QTest::compare_string_helper(const char *t1, const char *t2, const char *actual,
@@ -2510,51 +2576,59 @@ bool QTest::compare_string_helper(const char *t1, const char *t2, const char *ac
\internal
*/
-/*! \fn bool QTest::compare_ptr_helper(const void *t1, const void *t2, const char *actual, const char *expected, const char *file, int line);
+/*! \fn bool QTest::compare_ptr_helper(const volatile void *t1, const volatile void *t2, const char *actual, const char *expected, const char *file, int line)
+ \internal
+*/
+
+/*! \fn bool QTest::compare_ptr_helper(const volatile void *t1, std::nullptr_t, const char *actual, const char *expected, const char *file, int line)
+ \internal
+*/
+
+/*! \fn bool QTest::compare_ptr_helper(std::nullptr_t, const volatile void *t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(T1 const &, T2 const &, const char *, const char *, const char *, int);
+/*! \fn template <typename T1, typename T2> bool QTest::qCompare(const T1 &t1, const T2 &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(QIcon const &t1, QIcon const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const QIcon &t1, const QIcon &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(QImage const &t1, QImage const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const QImage &t1, const QImage &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(QPixmap const &t1, QPixmap const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const QPixmap &t1, const QPixmap &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(T const &t1, T const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn template <typename T> bool QTest::qCompare(const T &t1, const T &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(const T *t1, const T *t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn template <typename T> bool QTest::qCompare(const T *t1, const T *t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(T *t, std::nullptr_t, const char *actual, const char *expected, const char *file, int line)
+/*! \fn template <typename T> bool QTest::qCompare(T *t, std::nullptr_t, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(std::nullptr_t, T *t, const char *actual, const char *expected, const char *file, int line)
+/*! \fn template <typename T> bool QTest::qCompare(std::nullptr_t, T *t, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(T *t1, T *t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn template <typename T> bool QTest::qCompare(T *t1, T *t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(const T1 *t1, const T2 *t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn template <typename T1, typename T2> bool QTest::qCompare(const T1 *t1, const T2 *t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(T1 *t1, T2 *t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn template <typename T1, typename T2> bool QTest::qCompare(T1 *t1, T2 *t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
@@ -2574,55 +2648,55 @@ bool QTest::compare_string_helper(const char *t1, const char *t2, const char *ac
\internal
*/
-/*! \fn bool QTest::qCompare(QString const &t1, QLatin1String const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const QString &t1, const QLatin1String &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(QLatin1String const &t1, QString const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const QLatin1String &t1, const QString &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(QStringList const &t1, QStringList const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const QStringList &t1, const QStringList &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(QList<T> const &t1, QList<T> const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn template <typename T> bool QTest::qCompare(const QList<T> &t1, const QList<T> &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(QFlags<T> const &t1, T const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn template <typename T> bool QTest::qCompare(const QFlags<T> &t1, const T &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(QFlags<T> const &t1, int const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn template <typename T> bool QTest::qCompare(const QFlags<T> &t1, const int &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(qint64 const &t1, qint32 const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const qint64 &t1, const qint32 &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(qint64 const &t1, quint32 const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const qint64 &t1, const quint32 &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(quint64 const &t1, quint32 const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const quint64 &t1, const quint32 &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(qint32 const &t1, qint64 const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const qint32 &t1, const qint64 &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(quint32 const &t1, qint64 const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const quint32 &t1, const qint64 &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qCompare(quint32 const &t1, quint64 const &t2, const char *actual, const char *expected, const char *file, int line)
+/*! \fn bool QTest::qCompare(const quint32 &t1, const quint64 &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
-/*! \fn bool QTest::qTest(const T& actual, const char *elementName, const char *actualStr, const char *expected, const char *file, int line)
+/*! \fn template <typename T> bool QTest::qTest(const T& actual, const char *elementName, const char *actualStr, const char *expected, const char *file, int line)
\internal
*/
diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h
index a59eb4ecb3..f38f7ed4df 100644
--- a/src/testlib/qtestcase.h
+++ b/src/testlib/qtestcase.h
@@ -147,6 +147,8 @@ do {\
} \
}
+// Ideally we'd use qWaitFor instead of QTRY_LOOP_IMPL, but due
+// to a compiler bug on MSVC < 2017 we can't (see QTBUG-59096)
#define QTRY_IMPL(expr, timeout)\
const int qt_test_step = 50; \
const int qt_test_timeoutValue = timeout; \
@@ -248,7 +250,7 @@ namespace QTest
template <typename T> // Fallback
inline typename std::enable_if<!QtPrivate::IsQEnumHelper<T>::Value, char*>::type toString(const T &)
{
- return Q_NULLPTR;
+ return nullptr;
}
} // namespace Internal
@@ -259,16 +261,26 @@ namespace QTest
return Internal::toString(t);
}
+ template <typename T1, typename T2>
+ inline char *toString(const QPair<T1, T2> &pair);
+
+ template <typename T1, typename T2>
+ inline char *toString(const std::pair<T1, T2> &pair);
+
Q_TESTLIB_EXPORT char *toHexRepresentation(const char *ba, int length);
Q_TESTLIB_EXPORT char *toPrettyCString(const char *unicode, int length);
- Q_TESTLIB_EXPORT char *toPrettyUnicode(const ushort *unicode, int length);
+ Q_TESTLIB_EXPORT char *toPrettyUnicode(QStringView string);
Q_TESTLIB_EXPORT char *toString(const char *);
Q_TESTLIB_EXPORT char *toString(const void *);
- Q_TESTLIB_EXPORT int qExec(QObject *testObject, int argc = 0, char **argv = Q_NULLPTR);
+ Q_TESTLIB_EXPORT void qInit(QObject *testObject, int argc = 0, char **argv = nullptr);
+ Q_TESTLIB_EXPORT int qRun();
+ Q_TESTLIB_EXPORT void qCleanup();
+
+ Q_TESTLIB_EXPORT int qExec(QObject *testObject, int argc = 0, char **argv = nullptr);
Q_TESTLIB_EXPORT int qExec(QObject *testObject, const QStringList &arguments);
- Q_TESTLIB_EXPORT void setMainSourcePath(const char *file, const char *builddir = Q_NULLPTR);
+ Q_TESTLIB_EXPORT void setMainSourcePath(const char *file, const char *builddir = nullptr);
Q_TESTLIB_EXPORT bool qVerify(bool statement, const char *statementStr, const char *description,
const char *file, int line);
@@ -276,7 +288,7 @@ namespace QTest
Q_TESTLIB_EXPORT void qSkip(const char *message, const char *file, int line);
Q_TESTLIB_EXPORT bool qExpectFail(const char *dataIndex, const char *comment, TestFailMode mode,
const char *file, int line);
- Q_TESTLIB_EXPORT void qWarn(const char *message, const char *file = Q_NULLPTR, int line = 0);
+ Q_TESTLIB_EXPORT void qWarn(const char *message, const char *file = nullptr, int line = 0);
Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message);
#ifndef QT_NO_REGULAREXPRESSION
Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const QRegularExpression &messagePattern);
@@ -285,8 +297,8 @@ namespace QTest
#if QT_CONFIG(temporaryfile)
Q_TESTLIB_EXPORT QSharedPointer<QTemporaryDir> qExtractTestData(const QString &dirName);
#endif
- Q_TESTLIB_EXPORT QString qFindTestData(const char* basepath, const char* file = Q_NULLPTR, int line = 0, const char* builddir = Q_NULLPTR);
- Q_TESTLIB_EXPORT QString qFindTestData(const QString& basepath, const char* file = Q_NULLPTR, int line = 0, const char* builddir = Q_NULLPTR);
+ Q_TESTLIB_EXPORT QString qFindTestData(const char* basepath, const char* file = nullptr, int line = 0, const char* builddir = nullptr);
+ Q_TESTLIB_EXPORT QString qFindTestData(const QString& basepath, const char* file = nullptr, int line = 0, const char* builddir = nullptr);
Q_TESTLIB_EXPORT void *qData(const char *tagName, int typeId);
Q_TESTLIB_EXPORT void *qGlobalData(const char *tagName, int typeId);
@@ -319,6 +331,8 @@ namespace QTest
Q_TESTLIB_EXPORT QTestData &newRow(const char *dataTag);
Q_TESTLIB_EXPORT QTestData &addRow(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ // kept after adding implementation of <T1, T2> out of paranoia:
template <typename T>
inline bool qCompare(T const &t1, T const &t2, const char *actual, const char *expected,
const char *file, int line)
@@ -326,6 +340,7 @@ namespace QTest
return compare_helper(t1 == t2, "Compared values are not the same",
toString(t1), toString(t2), actual, expected, file, line);
}
+#endif
Q_TESTLIB_EXPORT bool qCompare(float const &t1, float const &t2,
const char *actual, const char *expected, const char *file, int line);
@@ -376,7 +391,12 @@ namespace QTest
#endif
template <typename T1, typename T2>
- bool qCompare(T1 const &, T2 const &, const char *, const char *, const char *, int);
+ inline bool qCompare(const T1 &t1, const T2 &t2, const char *actual, const char *expected,
+ const char *file, int line)
+ {
+ return compare_helper(t1 == t2, "Compared values are not the same",
+ toString(t1), toString(t2), actual, expected, file, line);
+ }
inline bool qCompare(double const &t1, float const &t2, const char *actual,
const char *expected, const char *file, int line)
diff --git a/src/testlib/qtestcase.qdoc b/src/testlib/qtestcase.qdoc
index 8f3d140add..9a3c770e31 100644
--- a/src/testlib/qtestcase.qdoc
+++ b/src/testlib/qtestcase.qdoc
@@ -82,11 +82,6 @@
QCOMPARE tries to output the contents of the values if the comparison fails,
so it is visible from the test log why the comparison failed.
- QCOMPARE is very strict on the data types. Both \a actual and \a expected
- have to be of the same type, otherwise the test won't compile. This prohibits
- unspecified behavior from being introduced; that is behavior that usually
- occurs when the compiler implicitly casts the argument.
-
For your own classes, you can use \l QTest::toString() to format values for
outputting into the test log.
@@ -108,7 +103,7 @@
to catch an exception thrown from the \a expression. If the \a expression
throws an exception and its type is the same as \a exceptiontype
or \a exceptiontype is substitutable with the type of thrown exception
- (i.e. usually the type of thrown exception is publically derived
+ (i.e. usually the type of thrown exception is publicly derived
from \a exceptiontype) then execution will be continued. If not-substitutable
type of exception is thrown or the \a expression doesn't throw an exception
at all, then a failure will be recorded in the test log and
@@ -575,6 +570,15 @@
\sa QTest::keyClicks()
*/
+/*! \fn void QTest::keySequence(QWidget *widget, const QKeySequence &keySequence)
+ \overload
+ \since 5.10
+
+ Simulates typing of \a keySequence into a \a widget.
+
+ \sa QTest::keyClick(), QTest::keyClicks()
+*/
+
/*! \fn void QTest::keyClick(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
\overload
\since 5.0
@@ -611,6 +615,15 @@
\sa QTest::keyClicks()
*/
+/*! \fn void QTest::keySequence(QWindow *window, const QKeySequence &keySequence)
+ \overload
+ \since 5.10
+
+ Simulates typing of \a keySequence into a \a window.
+
+ \sa QTest::keyClick(), QTest::keyClicks()
+*/
+
/*! \fn void QTest::keyEvent(KeyAction action, QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
Sends a Qt key event to \a widget with the given \a key and an associated \a action.
@@ -864,7 +877,42 @@
*/
/*!
- \fn char *QTest::toString(const T &value)
+ \fn template <typename T1, typename T2> char *QTest::toString(const QPair<T1, T2> &pair)
+ \overload
+ \since 5.11
+ Returns a textual representation of the \a pair.
+*/
+
+/*!
+ \fn template <typename T1, typename T2> char *QTest::toString(const std::pair<T1, T2> &pair)
+ \overload
+ \since 5.11
+ Returns a textual representation of the \a pair.
+*/
+
+/*!
+ \fn char *QTest::toString(const QVector2D &v)
+ \overload
+ \since 5.11
+ Returns a textual representation of the 2D vector \a v.
+*/
+
+/*!
+ \fn char *QTest::toString(const QVector3D &v)
+ \overload
+ \since 5.11
+ Returns a textual representation of the 3D vector \a v.
+*/
+
+/*!
+ \fn char *QTest::toString(const QVector4D &v)
+ \overload
+ \since 5.11
+ Returns a textual representation of the 4D vector \a v.
+*/
+
+/*!
+ \fn template<typename T> char *QTest::toString(const T &value)
Returns a textual representation of \a value. This function is used by
\l QCOMPARE() to output verbose information in case of a test failure.
@@ -915,6 +963,22 @@
*/
/*!
+ \fn char *QTest::toString(const QStringView &string)
+ \overload
+ \since 5.11
+
+ Returns a textual representation of the given \a string.
+*/
+
+/*!
+ \fn char *QTest::toString(const QUuid &uuid)
+ \overload
+ \since 5.11
+
+ Returns a textual representation of the given \a uuid.
+*/
+
+/*!
\fn char *QTest::toString(const QString &string)
\overload
@@ -1062,6 +1126,21 @@
\sa QTest::qSleep(), QSignalSpy::wait()
*/
+/*! \fn template <typename Functor> bool QTest::qWaitFor(Functor predicate, int timeout)
+
+ Waits for \a timeout milliseconds or until the \a predicate returns true.
+
+ Returns \c true if the \a predicate returned true at any point, otherwise returns \c false.
+
+ Example:
+ \snippet code/src_qtestlib_qtestcase.cpp 30
+
+ The code above will wait for the object to become ready, for a
+ maximum of three seconds.
+
+ \since 5.10
+*/
+
/*! \fn bool QTest::qWaitForWindowExposed(QWindow *window, int timeout)
\since 5.0
@@ -1071,6 +1150,10 @@
This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
time after being asked to show itself on the screen.
+ Note that a window that is mapped to screen may still not be considered exposed if the window client
+ area is completely covered by other windows, or if the window is otherwise not visible. This function
+ will then time out when waiting for such a window.
+
\sa QTest::qWaitForWindowActive(), QWindow::isExposed()
*/
@@ -1093,6 +1176,13 @@
This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
time after being asked to show itself on the screen.
+ Note that a window that is mapped to screen may still not be considered exposed if the window client
+ area is completely covered by other windows, or if the window is otherwise not visible. This function
+ will then time out when waiting for such a window.
+
+ A specific configuration where this happens is when using QGLWidget as a viewport widget on macOS:
+ The viewport widget gets the expose event, not the parent widget.
+
\sa QTest::qWaitForWindowActive()
*/
@@ -1288,10 +1378,6 @@
// Internals of qtestmouse.h:
-/*! \fn void QTest::waitForEvents()
- \internal
-*/
-
/*! \fn void QTest::mouseEvent(MouseAction action, QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers stateKey, QPoint pos, int delay=-1)
\internal
*/
diff --git a/src/testlib/qtesteventloop.h b/src/testlib/qtesteventloop.h
index bcf4a4be2d..81c0b9126c 100644
--- a/src/testlib/qtesteventloop.h
+++ b/src/testlib/qtesteventloop.h
@@ -56,8 +56,8 @@ class Q_TESTLIB_EXPORT QTestEventLoop : public QObject
Q_OBJECT
public:
- inline QTestEventLoop(QObject *aParent = Q_NULLPTR)
- : QObject(aParent), inLoop(false), _timeout(false), timerId(-1), loop(Q_NULLPTR) {}
+ inline QTestEventLoop(QObject *aParent = nullptr)
+ : QObject(aParent), inLoop(false), _timeout(false), timerId(-1), loop(nullptr) {}
inline void enterLoopMSecs(int ms);
inline void enterLoop(int secs) { enterLoopMSecs(secs * 1000); }
@@ -103,7 +103,7 @@ inline void QTestEventLoop::enterLoopMSecs(int ms)
loop = &l;
l.exec();
- loop = Q_NULLPTR;
+ loop = nullptr;
}
inline void QTestEventLoop::exitLoop()
diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h
index e750fdb5a9..a7cf78f25a 100644
--- a/src/testlib/qtestkeyboard.h
+++ b/src/testlib/qtestkeyboard.h
@@ -54,6 +54,7 @@
#include <QtGui/qguiapplication.h>
#include <QtGui/qwindow.h>
#include <QtGui/qevent.h>
+#include <QtGui/qkeysequence.h>
#ifdef QT_WIDGETS_LIB
#include <QtWidgets/qwidget.h>
@@ -165,6 +166,15 @@ namespace QTest
Q_DECL_UNUSED inline static void keyPress(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
{ keyEvent(Press, window, key, modifier, delay); }
+ Q_DECL_UNUSED inline static void keySequence(QWindow *window, const QKeySequence &keySequence)
+ {
+ for (int i = 0; i < keySequence.count(); ++i) {
+ const Qt::Key key = Qt::Key(keySequence[i] & ~Qt::KeyboardModifierMask);
+ const Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers(keySequence[i] & Qt::KeyboardModifierMask);
+ keyClick(window, key, modifiers);
+ }
+ }
+
#ifdef QT_WIDGETS_LIB
static void simulateEvent(QWidget *widget, bool press, int code,
Qt::KeyboardModifiers modifier, QString text, bool repeat, int delay=-1)
@@ -294,6 +304,16 @@ namespace QTest
{ keyEvent(Release, widget, key, modifier, delay); }
inline static void keyClick(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
{ keyEvent(Click, widget, key, modifier, delay); }
+
+ inline static void keySequence(QWidget *widget, const QKeySequence &keySequence)
+ {
+ for (int i = 0; i < keySequence.count(); ++i) {
+ const Qt::Key key = Qt::Key(keySequence[i] & ~Qt::KeyboardModifierMask);
+ const Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers(keySequence[i] & Qt::KeyboardModifierMask);
+ keyClick(widget, key, modifiers);
+ }
+ }
+
#endif // QT_WIDGETS_LIB
}
diff --git a/src/testlib/qtestmouse.h b/src/testlib/qtestmouse.h
index 8f55c1801f..fa524fd8ca 100644
--- a/src/testlib/qtestmouse.h
+++ b/src/testlib/qtestmouse.h
@@ -64,7 +64,9 @@
QT_BEGIN_NAMESPACE
-Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp);
+Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *window, const QPointF &local, const QPointF &global,
+ Qt::MouseButtons state, Qt::MouseButton button,
+ QEvent::Type type, Qt::KeyboardModifiers mods, int timestamp);
namespace QTest
{
@@ -78,15 +80,13 @@ namespace QTest
// to depend on platform themes.
static const int mouseDoubleClickInterval = 500;
- static void waitForEvents()
- {
-#ifdef Q_OS_MAC
- QTest::qWait(20);
-#else
- qApp->processEvents();
-#endif
- }
+/*! \internal
+ This function mocks all mouse events by bypassing the windowing system. The
+ result is that the mouse events do not come from the system via Qt platform
+ plugins, but are created on the spot and immediately available for processing
+ by Qt.
+*/
static void mouseEvent(MouseAction action, QWindow *window, Qt::MouseButton button,
Qt::KeyboardModifiers stateKey, QPoint pos, int delay=-1)
{
@@ -120,30 +120,33 @@ namespace QTest
switch (action)
{
case MouseDClick:
- qt_handleMouseEvent(w, pos, global, button, stateKey, ++lastMouseTimestamp);
- qt_handleMouseEvent(w, pos, global, Qt::NoButton, stateKey, ++lastMouseTimestamp);
+ qt_handleMouseEvent(w, pos, global, button, button, QEvent::MouseButtonPress,
+ stateKey, ++lastMouseTimestamp);
+ qt_handleMouseEvent(w, pos, global, Qt::NoButton, button, QEvent::MouseButtonRelease,
+ stateKey, ++lastMouseTimestamp);
Q_FALLTHROUGH();
case MousePress:
case MouseClick:
- qt_handleMouseEvent(w, pos, global, button, stateKey, ++lastMouseTimestamp);
+ qt_handleMouseEvent(w, pos, global, button, button, QEvent::MouseButtonPress,
+ stateKey, ++lastMouseTimestamp);
lastMouseButton = button;
if (action == MousePress)
break;
Q_FALLTHROUGH();
case MouseRelease:
- qt_handleMouseEvent(w, pos, global, Qt::NoButton, stateKey, ++lastMouseTimestamp);
+ qt_handleMouseEvent(w, pos, global, Qt::NoButton, button, QEvent::MouseButtonRelease,
+ stateKey, ++lastMouseTimestamp);
lastMouseTimestamp += mouseDoubleClickInterval; // avoid double clicks being generated
lastMouseButton = Qt::NoButton;
break;
case MouseMove:
- qt_handleMouseEvent(w, pos, global, lastMouseButton, stateKey, ++lastMouseTimestamp);
- // No QCursor::setPos() call here. That could potentially result in mouse events sent by the windowing system
- // which is highly undesired here. Tests must avoid relying on QCursor.
+ qt_handleMouseEvent(w, pos, global, lastMouseButton, Qt::NoButton, QEvent::MouseMove,
+ stateKey, ++lastMouseTimestamp);
break;
default:
QTEST_ASSERT(false);
}
- waitForEvents();
+ qApp->processEvents();
}
inline void mousePress(QWindow *window, Qt::MouseButton button,
diff --git a/src/testlib/qtestsystem.h b/src/testlib/qtestsystem.h
index f38a156936..79fe68004e 100644
--- a/src/testlib/qtestsystem.h
+++ b/src/testlib/qtestsystem.h
@@ -54,8 +54,46 @@ QT_BEGIN_NAMESPACE
namespace QTest
{
+ template <typename Functor>
+ Q_REQUIRED_RESULT static bool qWaitFor(Functor predicate, int timeout = 5000)
+ {
+ // We should not spin the event loop in case the predicate is already true,
+ // otherwise we might send new events that invalidate the predicate.
+ if (predicate())
+ return true;
+
+ // qWait() is expected to spin the event loop, even when called with a small
+ // timeout like 1ms, so we we can't use a simple while-loop here based on
+ // the deadline timer not having timed out. Use do-while instead.
+
+ int remaining = timeout;
+ QDeadlineTimer deadline(remaining, Qt::PreciseTimer);
+
+ do {
+ QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+
+ remaining = deadline.remainingTime();
+ if (remaining > 0) {
+ QTest::qSleep(qMin(10, remaining));
+ remaining = deadline.remainingTime();
+ }
+
+ if (predicate())
+ return true;
+
+ remaining = deadline.remainingTime();
+ } while (remaining > 0);
+
+ return predicate(); // Last chance
+ }
+
Q_DECL_UNUSED inline static void qWait(int ms)
{
+ // Ideally this method would be implemented in terms of qWaitFor, with
+ // a predicate that always returns false, but due to a compiler bug in
+ // GCC 6 we can't do that.
+
Q_ASSERT(QCoreApplication::instance());
QDeadlineTimer timer(ms, Qt::PreciseTimer);
@@ -72,23 +110,17 @@ namespace QTest
}
#ifdef QT_GUI_LIB
- inline static bool qWaitForWindowActive(QWindow *window, int timeout = 5000)
+ Q_REQUIRED_RESULT inline static bool qWaitForWindowActive(QWindow *window, int timeout = 5000)
{
- QDeadlineTimer timer(timeout, Qt::PreciseTimer);
- int remaining = timeout;
- while (!window->isActive() && remaining > 0) {
- QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
- QCoreApplication::sendPostedEvents(Q_NULLPTR, QEvent::DeferredDelete);
- QTest::qSleep(10);
- remaining = timer.remainingTime();
- }
+ bool becameActive = qWaitFor([&]() { return window->isActive(); }, timeout);
+
// Try ensuring the platform window receives the real position.
// (i.e. that window->pos() reflects reality)
// isActive() ( == FocusIn in case of X) does not guarantee this. It seems some WMs randomly
// send the final ConfigureNotify (the one with the non-bogus 0,0 position) after the FocusIn.
// If we just let things go, every mapTo/FromGlobal call the tests perform directly after
// qWaitForWindowShown() will generate bogus results.
- if (window->isActive()) {
+ if (becameActive) {
int waitNo = 0; // 0, 0 might be a valid position after all, so do not wait for ever
while (window->position().isNull()) {
if (waitNo++ > timeout / 10)
@@ -99,29 +131,21 @@ namespace QTest
return window->isActive();
}
- inline static bool qWaitForWindowExposed(QWindow *window, int timeout = 5000)
+ Q_REQUIRED_RESULT inline static bool qWaitForWindowExposed(QWindow *window, int timeout = 5000)
{
- QDeadlineTimer timer(timeout, Qt::PreciseTimer);
- int remaining = timeout;
- while (!window->isExposed() && remaining > 0) {
- QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
- QCoreApplication::sendPostedEvents(Q_NULLPTR, QEvent::DeferredDelete);
- QTest::qSleep(10);
- remaining = timer.remainingTime();
- }
- return window->isExposed();
+ return qWaitFor([&]() { return window->isExposed(); }, timeout);
}
#endif
#ifdef QT_WIDGETS_LIB
- inline static bool qWaitForWindowActive(QWidget *widget, int timeout = 5000)
+ Q_REQUIRED_RESULT inline static bool qWaitForWindowActive(QWidget *widget, int timeout = 5000)
{
if (QWindow *window = widget->window()->windowHandle())
return qWaitForWindowActive(window, timeout);
return false;
}
- inline static bool qWaitForWindowExposed(QWidget *widget, int timeout = 5000)
+ Q_REQUIRED_RESULT inline static bool qWaitForWindowExposed(QWidget *widget, int timeout = 5000)
{
if (QWindow *window = widget->window()->windowHandle())
return qWaitForWindowExposed(window, timeout);
@@ -131,7 +155,8 @@ namespace QTest
#if QT_DEPRECATED_SINCE(5, 0)
# ifdef QT_WIDGETS_LIB
- QT_DEPRECATED inline static bool qWaitForWindowShown(QWidget *widget, int timeout = 5000)
+
+ QT_DEPRECATED Q_REQUIRED_RESULT inline static bool qWaitForWindowShown(QWidget *widget, int timeout = 5000)
{
return qWaitForWindowExposed(widget, timeout);
}
diff --git a/src/testlib/qtesttable.cpp b/src/testlib/qtesttable.cpp
index 1afe2f7af5..953495a18a 100644
--- a/src/testlib/qtesttable.cpp
+++ b/src/testlib/qtesttable.cpp
@@ -58,7 +58,7 @@ public:
}
struct Element {
- Element() : name(Q_NULLPTR), type(0) {}
+ Element() : name(nullptr), type(0) {}
Element(const char *n, int t) : name(n), type(t) {}
const char *name;
@@ -130,12 +130,12 @@ int QTestTable::elementTypeId(int index) const
const char *QTestTable::dataTag(int index) const
{
- return size_t(index) < d->elementList.size() ? d->elementList[index].name : Q_NULLPTR;
+ return size_t(index) < d->elementList.size() ? d->elementList[index].name : nullptr;
}
QTestData *QTestTable::testData(int index) const
{
- return size_t(index) < d->dataList.size() ? d->dataList[index] : Q_NULLPTR;
+ return size_t(index) < d->dataList.size() ? d->dataList[index] : nullptr;
}
class NamePredicate : public std::unary_function<QTestTablePrivate::Element, bool>
diff --git a/src/testlib/qtesttouch.h b/src/testlib/qtesttouch.h
index bda185bfee..83ca83602e 100644
--- a/src/testlib/qtesttouch.h
+++ b/src/testlib/qtesttouch.h
@@ -75,21 +75,21 @@ namespace QTest
if (commitWhenDestroyed)
commit();
}
- QTouchEventSequence& press(int touchId, const QPoint &pt, QWindow *window = Q_NULLPTR)
+ QTouchEventSequence& press(int touchId, const QPoint &pt, QWindow *window = nullptr)
{
QTouchEvent::TouchPoint &p = point(touchId);
p.setScreenPos(mapToScreen(window, pt));
p.setState(Qt::TouchPointPressed);
return *this;
}
- QTouchEventSequence& move(int touchId, const QPoint &pt, QWindow *window = Q_NULLPTR)
+ QTouchEventSequence& move(int touchId, const QPoint &pt, QWindow *window = nullptr)
{
QTouchEvent::TouchPoint &p = point(touchId);
p.setScreenPos(mapToScreen(window, pt));
p.setState(Qt::TouchPointMoved);
return *this;
}
- QTouchEventSequence& release(int touchId, const QPoint &pt, QWindow *window = Q_NULLPTR)
+ QTouchEventSequence& release(int touchId, const QPoint &pt, QWindow *window = nullptr)
{
QTouchEvent::TouchPoint &p = point(touchId);
p.setScreenPos(mapToScreen(window, pt));
@@ -104,21 +104,21 @@ namespace QTest
}
#ifdef QT_WIDGETS_LIB
- QTouchEventSequence& press(int touchId, const QPoint &pt, QWidget *widget = Q_NULLPTR)
+ QTouchEventSequence& press(int touchId, const QPoint &pt, QWidget *widget = nullptr)
{
QTouchEvent::TouchPoint &p = point(touchId);
p.setScreenPos(mapToScreen(widget, pt));
p.setState(Qt::TouchPointPressed);
return *this;
}
- QTouchEventSequence& move(int touchId, const QPoint &pt, QWidget *widget = Q_NULLPTR)
+ QTouchEventSequence& move(int touchId, const QPoint &pt, QWidget *widget = nullptr)
{
QTouchEvent::TouchPoint &p = point(touchId);
p.setScreenPos(mapToScreen(widget, pt));
p.setState(Qt::TouchPointMoved);
return *this;
}
- QTouchEventSequence& release(int touchId, const QPoint &pt, QWidget *widget = Q_NULLPTR)
+ QTouchEventSequence& release(int touchId, const QPoint &pt, QWidget *widget = nullptr)
{
QTouchEvent::TouchPoint &p = point(touchId);
p.setScreenPos(mapToScreen(widget, pt));
@@ -151,14 +151,14 @@ namespace QTest
private:
#ifdef QT_WIDGETS_LIB
QTouchEventSequence(QWidget *widget, QTouchDevice *aDevice, bool autoCommit)
- : targetWidget(widget), targetWindow(Q_NULLPTR), device(aDevice), commitWhenDestroyed(autoCommit)
+ : targetWidget(widget), targetWindow(nullptr), device(aDevice), commitWhenDestroyed(autoCommit)
{
}
#endif
QTouchEventSequence(QWindow *window, QTouchDevice *aDevice, bool autoCommit)
:
#ifdef QT_WIDGETS_LIB
- targetWidget(Q_NULLPTR),
+ targetWidget(nullptr),
#endif
targetWindow(window), device(aDevice), commitWhenDestroyed(autoCommit)
{
@@ -205,13 +205,13 @@ private:
QWindow *targetWindow;
QTouchDevice *device;
bool commitWhenDestroyed;
-#ifdef QT_WIDGETS_LIB
- friend QTouchEventSequence touchEvent(QWidget *, QTouchDevice*, bool);
+#if defined(QT_WIDGETS_LIB) || defined(Q_CLANG_QDOC)
+ friend QTouchEventSequence touchEvent(QWidget *widget, QTouchDevice *device, bool autoCommit);
#endif
- friend QTouchEventSequence touchEvent(QWindow *, QTouchDevice*, bool);
+ friend QTouchEventSequence touchEvent(QWindow *window, QTouchDevice *device, bool autoCommit);
};
-#ifdef QT_WIDGETS_LIB
+#if defined(QT_WIDGETS_LIB) || defined(Q_CLANG_QDOC)
inline
QTouchEventSequence touchEvent(QWidget *widget,
QTouchDevice *device,
diff --git a/src/testlib/qtestutil_macos.mm b/src/testlib/qtestutil_macos.mm
index 70a7fb9f85..7579c3b164 100644
--- a/src/testlib/qtestutil_macos.mm
+++ b/src/testlib/qtestutil_macos.mm
@@ -54,6 +54,33 @@ namespace QTestPrivate {
void disableWindowRestore() {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"ApplePersistenceIgnoreState"];
}
+
+ /*! \internal
+ \class AppNapDisabler
+ \brief Disables App Nap by registereing a bacground activity.
+
+ App Nap remains disabled as long as the AppNapDisabler instance
+ exists.
+ */
+
+ /*! \internal
+ Creates an AppNapDisabler instance and starts a NSActivityBackground activity.
+ */
+ AppNapDisabler::AppNapDisabler()
+ {
+ m_activity = [[NSProcessInfo processInfo] beginActivityWithOptions:NSActivityBackground
+ reason:@"Qt Auto Test"];
+ [m_activity retain];
+ }
+
+ /*! \internal
+ Destroys the AppNapDisabler instance and ends the NSActivityBackground activity.
+ */
+ AppNapDisabler::~AppNapDisabler()
+ {
+ [[NSProcessInfo processInfo] endActivity:m_activity];
+ [m_activity release];
+ }
}
QT_END_NAMESPACE
diff --git a/src/testlib/qtestutil_macos_p.h b/src/testlib/qtestutil_macos_p.h
index d7cc5bc251..36f27167c0 100644
--- a/src/testlib/qtestutil_macos_p.h
+++ b/src/testlib/qtestutil_macos_p.h
@@ -58,6 +58,17 @@ QT_BEGIN_NAMESPACE
namespace QTestPrivate {
void disableWindowRestore();
+
+ class AppNapDisabler
+ {
+ public:
+ AppNapDisabler();
+ ~AppNapDisabler();
+ AppNapDisabler(const AppNapDisabler&) = delete;
+ AppNapDisabler& operator=(const AppNapDisabler&) = delete;
+ private:
+ id m_activity;
+ };
}
QT_END_NAMESPACE
diff --git a/src/testlib/qxctestlogger_p.h b/src/testlib/qxctestlogger_p.h
index 2bbd5ad296..1b641f18af 100644
--- a/src/testlib/qxctestlogger_p.h
+++ b/src/testlib/qxctestlogger_p.h
@@ -65,21 +65,21 @@ class QXcodeTestLogger : public QAbstractTestLogger
{
public:
QXcodeTestLogger();
- ~QXcodeTestLogger() Q_DECL_OVERRIDE;
+ ~QXcodeTestLogger() override;
- void startLogging() Q_DECL_OVERRIDE;
- void stopLogging() Q_DECL_OVERRIDE;
+ void startLogging() override;
+ void stopLogging() override;
- void enterTestFunction(const char *function) Q_DECL_OVERRIDE;
- void leaveTestFunction() Q_DECL_OVERRIDE;
+ void enterTestFunction(const char *function) override;
+ void leaveTestFunction() override;
void addIncident(IncidentTypes type, const char *description,
- const char *file = 0, int line = 0) Q_DECL_OVERRIDE;
+ const char *file = 0, int line = 0) override;
void addMessage(MessageTypes type, const QString &message,
- const char *file = 0, int line = 0) Q_DECL_OVERRIDE;
+ const char *file = 0, int line = 0) override;
- void addBenchmarkResult(const QBenchmarkResult &result) Q_DECL_OVERRIDE;
+ void addBenchmarkResult(const QBenchmarkResult &result) override;
static bool canLogTestProgress();
static int parseCommandLineArgument(const char *argument);
diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro
index f99f28ca84..109feee630 100644
--- a/src/testlib/testlib.pro
+++ b/src/testlib/testlib.pro
@@ -11,7 +11,9 @@ unix:!embedded:QMAKE_PKGCONFIG_DESCRIPTION = Qt \
QMAKE_DOCS = $$PWD/doc/qttestlib.qdocconf
-HEADERS = qbenchmark.h \
+HEADERS = \
+ qabstractitemmodeltester.h \
+ qbenchmark.h \
qbenchmark_p.h \
qbenchmarkmeasurement_p.h \
qbenchmarktimemeasurers_p.h \
@@ -40,7 +42,9 @@ HEADERS = qbenchmark.h \
qtestblacklist_p.h \
qtesthelpers_p.h
-SOURCES = qtestcase.cpp \
+SOURCES = \
+ qabstractitemmodeltester.cpp \
+ qtestcase.cpp \
qtestlog.cpp \
qtesttable.cpp \
qtestdata.cpp \