diff options
Diffstat (limited to 'src/testlib/qtest.h')
-rw-r--r-- | src/testlib/qtest.h | 246 |
1 files changed, 120 insertions, 126 deletions
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index f9cf7aa941..99eae8553f 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -1,46 +1,14 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Copyright (C) 2020 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtTest module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2020 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTEST_H #define QTEST_H +#if 0 +#pragma qt_class(QTest) +#endif + #include <QtTest/qttestglobal.h> #include <QtTest/qtestcase.h> #include <QtTest/qtestdata.h> @@ -90,14 +58,14 @@ template<> inline char *toString(const QString &str) return toString(QStringView(str)); } -template<> inline char *toString(const QLatin1String &str) +template<> inline char *toString(const QLatin1StringView &str) { return toString(QString(str)); } template<> inline char *toString(const QByteArray &ba) { - return QTest::toPrettyCString(ba.constData(), ba.length()); + return QTest::toPrettyCString(ba.constData(), ba.size()); } template<> inline char *toString(const QBitArray &ba) @@ -105,7 +73,7 @@ template<> inline char *toString(const QBitArray &ba) qsizetype size = ba.size(); char *str = new char[size + 1]; for (qsizetype i = 0; i < size; ++i) - str[i] = "01"[ba.testBit(int(i))]; + str[i] = "01"[ba.testBit(i)]; str[size] = '\0'; return str; } @@ -206,7 +174,7 @@ template<> inline char *toString(const QRectF &s) template<> inline char *toString(const QUrl &uri) { if (!uri.isValid()) - return qstrdup(qPrintable(QLatin1String("Invalid URL: ") + uri.errorString())); + return qstrdup(qPrintable(QLatin1StringView("Invalid URL: ") + uri.errorString())); return qstrdup(uri.toEncoded().constData()); } @@ -239,6 +207,19 @@ template<> inline char *toString(const QVariant &v) return qstrdup(vstring.constData()); } +template<> inline char *toString(const QPartialOrdering &o) +{ + if (o == QPartialOrdering::Less) + return qstrdup("Less"); + if (o == QPartialOrdering::Equivalent) + return qstrdup("Equivalent"); + if (o == QPartialOrdering::Greater) + return qstrdup("Greater"); + if (o == QPartialOrdering::Unordered) + return qstrdup("Unordered"); + return qstrdup("<invalid>"); +} + namespace Internal { struct QCborValueFormatter { @@ -326,7 +307,7 @@ struct QCborValueFormatter { QByteArray out(1, '['); const char *comma = ""; - for (const QCborValueRef v : a) { + for (QCborValueConstRef v : a) { QScopedArrayPointer<char> s(format(v)); out += comma; out += s.get(); @@ -375,16 +356,29 @@ template<> inline char *toString(const QCborMap &m) return Internal::QCborValueFormatter::format(m); } +template <typename Rep, typename Period> char *toString(std::chrono::duration<Rep, Period> dur) +{ + QString r; + QDebug d(&r); + d.nospace() << qSetRealNumberPrecision(9) << dur; + if constexpr (Period::num != 1 || Period::den != 1) { + // include the equivalent value in seconds, in parentheses + using namespace std::chrono; + d << " (" << duration_cast<duration<qreal>>(dur).count() << "s)"; + } + return qstrdup(std::move(r).toUtf8().constData()); +} + 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())); + return formatString("std::pair(", ")", 2, first.data(), second.data()); } -template <typename Tuple, int... I> -inline char *toString(const Tuple & tuple, QtPrivate::IndexesList<I...>) { +template <typename Tuple, std::size_t... I> +inline char *tupleToString(const Tuple &tuple, std::index_sequence<I...>) { using UP = std::unique_ptr<char[]>; // Generate a table of N + 1 elements where N is the number of // elements in the tuple. @@ -398,36 +392,33 @@ inline char *toString(const Tuple & tuple, QtPrivate::IndexesList<I...>) { template <class... Types> inline char *toString(const std::tuple<Types...> &tuple) { - static const std::size_t params_count = sizeof...(Types); - return toString(tuple, typename QtPrivate::Indexes<params_count>::Value()); + return tupleToString(tuple, std::make_index_sequence<sizeof...(Types)>{}); } inline char *toString(std::nullptr_t) { - return toString(QLatin1String("nullptr")); + return toString(QStringView(u"nullptr")); } template<> -inline bool qCompare(QString const &t1, QLatin1String const &t2, const char *actual, - const char *expected, const char *file, int line) +inline bool qCompare(QString const &t1, QLatin1StringView const &t2, const char *actual, + const char *expected, const char *file, int line) { return qCompare(t1, QString(t2), actual, expected, file, line); } template<> -inline bool qCompare(QLatin1String const &t1, QString const &t2, const char *actual, - const char *expected, const char *file, int line) +inline bool qCompare(QLatin1StringView const &t1, QString const &t2, const char *actual, + const char *expected, const char *file, int line) { return qCompare(QString(t1), t2, actual, expected, file, line); } -namespace Internal { - // Compare sequences of equal size template <typename ActualIterator, typename ExpectedIterator> -bool compareSequence(ActualIterator actualIt, ActualIterator actualEnd, - ExpectedIterator expectedBegin, ExpectedIterator expectedEnd, - const char *actual, const char *expected, - const char *file, int line) +bool _q_compareSequence(ActualIterator actualIt, ActualIterator actualEnd, + ExpectedIterator expectedBegin, ExpectedIterator expectedEnd, + const char *actual, const char *expected, + const char *file, int line) { char msg[1024]; msg[0] = '\0'; @@ -446,8 +437,8 @@ bool compareSequence(ActualIterator actualIt, ActualIterator actualEnd, for (auto expectedIt = expectedBegin; isOk && expectedIt < expectedEnd; ++actualIt, ++expectedIt) { if (!(*actualIt == *expectedIt)) { const qsizetype i = qsizetype(expectedIt - expectedBegin); - char *val1 = QTest::toString(*actualIt); - char *val2 = QTest::toString(*expectedIt); + char *val1 = toString(*actualIt); + char *val2 = toString(*expectedIt); qsnprintf(msg, sizeof(msg), "Compared lists differ at index %zd.\n" " Actual (%s): %s\n" @@ -459,9 +450,11 @@ bool compareSequence(ActualIterator actualIt, ActualIterator actualEnd, delete [] val2; } } - return compare_helper(isOk, msg, nullptr, nullptr, actual, expected, file, line); + return compare_helper(isOk, msg, actual, expected, file, line); } +namespace Internal { + #if defined(TESTCASE_LOWDPI) void disableHighDpi() { @@ -476,7 +469,7 @@ template <typename T> inline bool qCompare(QList<T> const &t1, QList<T> const &t2, const char *actual, const char *expected, const char *file, int line) { - return Internal::compareSequence(t1.cbegin(), t1.cend(), t2.cbegin(), t2.cend(), + return _q_compareSequence(t1.cbegin(), t1.cend(), t2.cbegin(), t2.cend(), actual, expected, file, line); } @@ -485,7 +478,7 @@ bool qCompare(QList<T> const &t1, std::initializer_list<T> t2, const char *actual, const char *expected, const char *file, int line) { - return Internal::compareSequence(t1.cbegin(), t1.cend(), t2.cbegin(), t2.cend(), + return _q_compareSequence(t1.cbegin(), t1.cend(), t2.cbegin(), t2.cend(), actual, expected, file, line); } @@ -495,7 +488,7 @@ bool qCompare(QList<T> const &t1, const T (& t2)[N], const char *actual, const char *expected, const char *file, int line) { - return Internal::compareSequence(t1.cbegin(), t1.cend(), t2, t2 + N, + return _q_compareSequence(t1.cbegin(), t1.cend(), t2, t2 + N, actual, expected, file, line); } @@ -503,14 +496,16 @@ template <typename T> inline bool qCompare(QFlags<T> const &t1, T const &t2, const char *actual, const char *expected, const char *file, int line) { - return qCompare(int(t1), int(t2), actual, expected, file, line); + using Int = typename QFlags<T>::Int; + return qCompare(Int(t1), Int(t2), actual, expected, file, line); } template <typename T> inline bool qCompare(QFlags<T> const &t1, int const &t2, const char *actual, const char *expected, const char *file, int line) { - return qCompare(int(t1), t2, actual, expected, file, line); + using Int = typename QFlags<T>::Int; + return qCompare(Int(t1), Int(t2), actual, expected, file, line); } template<> @@ -612,14 +607,47 @@ struct QtCoverageScanner #define TESTLIB_SELFCOVERAGE_START(name) #endif -#define QTEST_APPLESS_MAIN(TestObject) \ +#if !defined(QTEST_BATCH_TESTS) +// Internal (but used by some testlib selftests to hack argc and argv). +// Tests should normally implement initMain() if they have set-up to do before +// instantiating the test class. +#define QTEST_MAIN_WRAPPER(TestObject, ...) \ int main(int argc, char *argv[]) \ { \ - TESTLIB_SELFCOVERAGE_START(TestObject) \ + TESTLIB_SELFCOVERAGE_START(#TestObject) \ + QT_PREPEND_NAMESPACE(QTest::Internal::callInitMain)<TestObject>(); \ + __VA_ARGS__ \ TestObject tc; \ QTEST_SET_MAIN_SOURCE_PATH \ return QTest::qExec(&tc, argc, argv); \ } +#else +// BATCHED_TEST_NAME is defined for each test in a batch in cmake. Some odd +// targets, like snippets, don't define it though. Play safe by providing a +// default value. +#if !defined(BATCHED_TEST_NAME) +#define BATCHED_TEST_NAME "other" +#endif +#define QTEST_MAIN_WRAPPER(TestObject, ...) \ +\ +void qRegister##TestObject() \ +{ \ + auto runTest = [](int argc, char** argv) -> int { \ + TESTLIB_SELFCOVERAGE_START(TestObject) \ + QT_PREPEND_NAMESPACE(QTest::Internal::callInitMain)<TestObject>(); \ + __VA_ARGS__ \ + TestObject tc; \ + QTEST_SET_MAIN_SOURCE_PATH \ + return QTest::qExec(&tc, argc, argv); \ + }; \ + QTest::qRegisterTestCase(QStringLiteral(BATCHED_TEST_NAME), runTest); \ +} \ +\ +Q_CONSTRUCTOR_FUNCTION(qRegister##TestObject) +#endif + +// For when you don't even want a QApplication: +#define QTEST_APPLESS_MAIN(TestObject) QTEST_MAIN_WRAPPER(TestObject) #include <QtTest/qtestsystem.h> @@ -627,68 +655,34 @@ int main(int argc, char *argv[]) \ # include <QtTest/qtest_network.h> #endif -#if defined(QT_WIDGETS_LIB) - -#include <QtTest/qtest_widgets.h> - -#ifdef QT_KEYPAD_NAVIGATION -# define QTEST_DISABLE_KEYPAD_NAVIGATION QApplication::setNavigationMode(Qt::NavigationModeNone); -#else -# define QTEST_DISABLE_KEYPAD_NAVIGATION -#endif - -#define QTEST_MAIN_IMPL(TestObject) \ - TESTLIB_SELFCOVERAGE_START(#TestObject) \ - QT_PREPEND_NAMESPACE(QTest::Internal::callInitMain)<TestObject>(); \ - QApplication app(argc, argv); \ - app.setAttribute(Qt::AA_Use96Dpi, true); \ - QTEST_DISABLE_KEYPAD_NAVIGATION \ - TestObject tc; \ - QTEST_SET_MAIN_SOURCE_PATH \ - return QTest::qExec(&tc, argc, argv); +// Internal +#define QTEST_QAPP_SETUP(klaz) \ + klaz app(argc, argv); \ + app.setAttribute(Qt::AA_Use96Dpi, true); +#if defined(QT_WIDGETS_LIB) +# include <QtTest/qtest_widgets.h> +# ifdef QT_KEYPAD_NAVIGATION +# define QTEST_DISABLE_KEYPAD_NAVIGATION QApplication::setNavigationMode(Qt::NavigationModeNone); +# else +# define QTEST_DISABLE_KEYPAD_NAVIGATION +# endif +// Internal +# define QTEST_MAIN_SETUP() QTEST_QAPP_SETUP(QApplication) QTEST_DISABLE_KEYPAD_NAVIGATION #elif defined(QT_GUI_LIB) - -#include <QtTest/qtest_gui.h> - -#define QTEST_MAIN_IMPL(TestObject) \ - TESTLIB_SELFCOVERAGE_START(#TestObject) \ - QT_PREPEND_NAMESPACE(QTest::Internal::callInitMain)<TestObject>(); \ - QGuiApplication app(argc, argv); \ - app.setAttribute(Qt::AA_Use96Dpi, true); \ - TestObject tc; \ - QTEST_SET_MAIN_SOURCE_PATH \ - return QTest::qExec(&tc, argc, argv); - +# include <QtTest/qtest_gui.h> +// Internal +# define QTEST_MAIN_SETUP() QTEST_QAPP_SETUP(QGuiApplication) #else - -#define QTEST_MAIN_IMPL(TestObject) \ - TESTLIB_SELFCOVERAGE_START(#TestObject) \ - QT_PREPEND_NAMESPACE(QTest::Internal::callInitMain)<TestObject>(); \ - QCoreApplication app(argc, argv); \ - app.setAttribute(Qt::AA_Use96Dpi, true); \ - TestObject tc; \ - QTEST_SET_MAIN_SOURCE_PATH \ - return QTest::qExec(&tc, argc, argv); - +// Internal +# define QTEST_MAIN_SETUP() QTEST_QAPP_SETUP(QCoreApplication) #endif // QT_GUI_LIB -#define QTEST_MAIN(TestObject) \ -int main(int argc, char *argv[]) \ -{ \ - QTEST_MAIN_IMPL(TestObject) \ -} +// For most tests: +#define QTEST_MAIN(TestObject) QTEST_MAIN_WRAPPER(TestObject, QTEST_MAIN_SETUP()) +// For command-line tests #define QTEST_GUILESS_MAIN(TestObject) \ -int main(int argc, char *argv[]) \ -{ \ - TESTLIB_SELFCOVERAGE_START(#TestObject) \ - QT_PREPEND_NAMESPACE(QTest::Internal::callInitMain)<TestObject>(); \ - QCoreApplication app(argc, argv); \ - app.setAttribute(Qt::AA_Use96Dpi, true); \ - TestObject tc; \ - QTEST_SET_MAIN_SOURCE_PATH \ - return QTest::qExec(&tc, argc, argv); \ -} + QTEST_MAIN_WRAPPER(TestObject, QTEST_QAPP_SETUP(QCoreApplication)) #endif |