diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-07-10 11:41:33 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-07-21 22:01:20 +0200 |
commit | d25589e0529732996e405aaff8d6c46b012e1601 (patch) | |
tree | 29b596d0c2ca0e36aa9aea65f426ed393c660e78 /src/testlib | |
parent | b50daef9771d8829fc7f808898cbe051a5464b79 (diff) | |
download | qtbase-d25589e0529732996e405aaff8d6c46b012e1601.tar.gz |
QTestlib: Enable comparing QList against initializer lists/arrays
It is unnecessary to create a QList container just for comparison.
Split out helpers for comparing sequence sizes and sequences from
qCompare(QList) and add a template for an array with a non-type template
parameter for the size.
One can then write something like:
const int expected[] = {10, 12,...};
QCOMPARE(QFontDatabase.pointSizes(...), expected)
Unfortunately, any commas in such an array will be misread by macro expansion
as macro argument separators, so any expected array with more than one entry
needs an extra macro expanding __VA_ARGS__.
Change-Id: Ie7c8dc20bf669bbb25f6d7f8562455f8d03968c8
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/testlib')
-rw-r--r-- | src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp | 20 | ||||
-rw-r--r-- | src/testlib/qtest.h | 69 | ||||
-rw-r--r-- | src/testlib/qtestcase.qdoc | 19 |
3 files changed, 88 insertions, 20 deletions
diff --git a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp index cfa999a6f4..01f4e11eb4 100644 --- a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp +++ b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp @@ -49,6 +49,9 @@ ****************************************************************************/ #include <QTest> #include <QSqlDatabase> +#include <QtGui/qfontdatabase.h> + +#include <initializer_list> // dummy class TestBenchmark : public QObject @@ -246,3 +249,20 @@ QVERIFY2(file.open(QIODevice::WriteOnly), .arg(file.fileName()).arg(file.errorString()))); //! [33] } + +void compareListToArray() +{ +//! [34] + const int expected[] = {8, 10, 12, 16, 20, 24}; + QCOMPARE(QFontDatabase::standardSizes(), expected); +//! [34] +} + +void compareListToInitializerList() +{ +//! [35] + #define ARG(...) __VA_ARGS__ + QCOMPARE(QFontDatabase::standardSizes(), ARG({8, 10, 12, 16, 20, 24})); + #undef ARG +//! [35] +} diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index 9455a66fdd..0fbef0b7c2 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -64,6 +64,7 @@ #include <QtCore/qsize.h> #include <QtCore/qrect.h> +#include <initializer_list> #include <memory> QT_BEGIN_NAMESPACE @@ -276,27 +277,36 @@ inline bool qCompare(QLatin1String const &t1, QString const &t2, const char *act return qCompare(QString(t1), t2, actual, expected, file, line); } -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) +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) { char msg[1024]; msg[0] = '\0'; - bool isOk = true; - const int actualSize = t1.count(); - const int expectedSize = t2.count(); - if (actualSize != expectedSize) { + + const qsizetype actualSize = actualEnd - actualIt; + const qsizetype expectedSize = expectedEnd - expectedBegin; + bool isOk = actualSize == expectedSize; + + if (!isOk) { qsnprintf(msg, sizeof(msg), "Compared lists have different sizes.\n" - " Actual (%s) size: %d\n" - " Expected (%s) size: %d", actual, actualSize, expected, expectedSize); - isOk = false; + " Actual (%s) size: %zd\n" + " Expected (%s) size: %zd", actual, actualSize, + expected, expectedSize); } - for (int i = 0; isOk && i < actualSize; ++i) { - if (!(t1.at(i) == t2.at(i))) { - char *val1 = toString(t1.at(i)); - char *val2 = toString(t2.at(i)); - qsnprintf(msg, sizeof(msg), "Compared lists differ at index %d.\n" + 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); + + qsnprintf(msg, sizeof(msg), "Compared lists differ at index %zd.\n" " Actual (%s): %s\n" " Expected (%s): %s", i, actual, val1 ? val1 : "<null>", expected, val2 ? val2 : "<null>"); @@ -309,6 +319,35 @@ inline bool qCompare(QList<T> const &t1, QList<T> const &t2, const char *actual, return compare_helper(isOk, msg, nullptr, nullptr, actual, expected, file, line); } +} // namespace Internal + +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(), + actual, expected, file, line); +} + +template <typename T, int N> +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(), + actual, expected, file, line); +} + +// Compare QList against array +template <typename T, int N> +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, + actual, expected, file, line); +} + template <> inline bool qCompare(QStringList const &t1, QStringList 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 98112027a5..8c89b37baf 100644 --- a/src/testlib/qtestcase.qdoc +++ b/src/testlib/qtestcase.qdoc @@ -116,19 +116,28 @@ Expected. If the parameter order is swapped, debugging a failing test can be confusing and tests expecting zero may fail due to rounding errors. + 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. + + Example: + \snippet code/src_qtestlib_qtestcase.cpp 2 + When comparing floating-point types (\c float, \c double, and \c qfloat16), \l qFuzzyCompare() is used for finite values. If qFuzzyIsNull() is true for both values, they are also considered equal. Infinities match if they have the same sign, and any NaN as actual value matches with any NaN as expected value (even though NaN != NaN, even when they're identical). - 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. + When comparing QList, arrays and initializer lists of the value type + can be passed as expected value: + \snippet code/src_qtestlib_qtestcase.cpp 34 - Example: - \snippet code/src_qtestlib_qtestcase.cpp 2 + Note that using initializer lists requires a defining a helper macro + to prevent the preprocessor from interpreting the commas as macro argument + delimiters: + \snippet code/src_qtestlib_qtestcase.cpp 35 - \note This macro can only be used in a test function that is invoked + \note QCOMPARE() can only be used in a test function that is invoked by the test framework. For your own classes, you can use \l QTest::toString() to format values for |