diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2020-03-11 01:00:56 +0100 |
---|---|---|
committer | Sona Kurazyan <sona.kurazyan@qt.io> | 2020-03-11 15:34:21 +0100 |
commit | 865afac25036d58b18794384e37d42931b2164c5 (patch) | |
tree | e18d31138f1a8b9200764fd3648e58b9dd6b124f /tests/auto | |
parent | 01bacdf7abb071198d843acdfb22ce1701766be8 (diff) | |
parent | 52de905d0ec6159d3a1e7ad63fed018b5c6973d2 (diff) | |
download | qtbase-865afac25036d58b18794384e37d42931b2164c5.tar.gz |
Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: Ibee5acec72a1a1769d4bc5f23f56c7dc8d4cf3cb
Diffstat (limited to 'tests/auto')
38 files changed, 4303 insertions, 187 deletions
diff --git a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp index a10e706ed7..4c269822d6 100644 --- a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp +++ b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp @@ -158,10 +158,13 @@ private slots: QFETCH(QtMsgType, msgType); QFETCH(LoggingRuleState, result); - QLoggingRule rule(QStringRef(&pattern), true); + const auto categoryL1 = category.toLatin1(); + const auto categoryL1S = QLatin1String(categoryL1); + + QLoggingRule rule(pattern, true); LoggingRuleState state = Invalid; if (rule.flags != 0) { - switch (rule.pass(category, msgType)) { + switch (rule.pass(categoryL1S, msgType)) { case -1: QFAIL("Shoudn't happen, we set pattern to true"); break; case 0: state = NoMatch; break; case 1: state = Match; break; diff --git a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp index 5fc4343cd9..419a8138a1 100644 --- a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp +++ b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp @@ -28,12 +28,13 @@ #include <QtTest/QtTest> #include <QtGui/QBitmap> +#include <QtGui/QPainter> +#include <QtGui/QPainterPath> #include <QtGui/QPalette> -#include <QtGui/QPixmap> +#include <QtGui/QPen> #include <QtGui/QPicture> +#include <QtGui/QPixmap> #include <QtGui/QTextLength> -#include <QtGui/QPainter> -#include <QtGui/QPen> class tst_QDataStream : public QObject { diff --git a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp index bcf4e73108..35546c2968 100644 --- a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp +++ b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp @@ -73,6 +73,8 @@ QStringList toQStringList(const Iterable &i) { MAKE_ALL(QByteArray, QChar) MAKE_ALL(QByteArray, QLatin1String) +MAKE_ALL(QByteArray, char16_t) +MAKE_ALL(char16_t, QByteArray) MAKE_ALL(const char*, QChar) @@ -100,6 +102,11 @@ static QByteArray rowName(const QByteArray &data) return result; } +# define QVERIFY_NOEXCEPT(expr) do { \ + if (!has_nothrow_compare<LHS, RHS>::value) \ + QEXPECT_FAIL("", "Qt is missing a nothrow utf8-utf16 comparator", Continue); \ + QVERIFY(noexcept(expr)); } while (0) + class tst_QStringApiSymmetry : public QObject { Q_OBJECT @@ -113,9 +120,11 @@ class tst_QStringApiSymmetry : public QObject void compare_impl() const; private Q_SLOTS: - // test all combinations of {QChar, QStringRef, QString, QStringView, QLatin1String, QByteArray, const char*} + // test all combinations of {QChar, char16_t, QStringRef, QString, QStringView, QLatin1String, QByteArray, const char*} void compare_QChar_QChar_data() { compare_data(false); } void compare_QChar_QChar() { compare_impl<QChar, QChar>(); } + void compare_QChar_char16_t_data() { compare_data(false); } + void compare_QChar_char16_t() { compare_impl<QChar, char16_t>(); } void compare_QChar_QStringRef_data() { compare_data(false); } void compare_QChar_QStringRef() { compare_impl<QChar, QStringRef>(); } void compare_QChar_QString_data() { compare_data(false); } @@ -129,8 +138,27 @@ private Q_SLOTS: void compare_QChar_const_char_star_data() { compare_data(false); } void compare_QChar_const_char_star() { compare_impl<QChar, const char *>(); } + void compare_char16_t_QChar_data() { compare_data(false); } + void compare_char16_t_QChar() { compare_impl<char16_t, QChar>(); } + //void compare_char16_t_char16_t_data() { compare_data(false); } + //void compare_char16_t_char16_t() { compare_impl<char16_t, char16_t>(); } + void compare_char16_t_QStringRef_data() { compare_data(false); } + void compare_char16_t_QStringRef() { compare_impl<char16_t, QStringRef>(); } + void compare_char16_t_QString_data() { compare_data(false); } + void compare_char16_t_QString() { compare_impl<char16_t, QString>(); } + void compare_char16_t_QStringView_data() { compare_data(false); } + void compare_char16_t_QStringView() { compare_impl<char16_t, QStringView>(); } + void compare_char16_t_QLatin1String_data() { compare_data(false); } + void compare_char16_t_QLatin1String() { compare_impl<char16_t, QLatin1String>(); } + void compare_char16_t_QByteArray_data() { compare_data(false); } + void compare_char16_t_QByteArray() { compare_impl<char16_t, QByteArray>(); } + //void compare_char16_t_const_char_star_data() { compare_data(false); } + //void compare_char16_t_const_char_star() { compare_impl<char16_t, const char *>(); } + void compare_QStringRef_QChar_data() { compare_data(false); } void compare_QStringRef_QChar() { compare_impl<QStringRef, QChar>(); } + void compare_QStringRef_char16_t_data() { compare_data(false); } + void compare_QStringRef_char16_t() { compare_impl<QStringRef, char16_t>(); } void compare_QStringRef_QStringRef_data() { compare_data(); } void compare_QStringRef_QStringRef() { compare_impl<QStringRef, QStringRef>(); } void compare_QStringRef_QString_data() { compare_data(); } @@ -146,6 +174,8 @@ private Q_SLOTS: void compare_QString_QChar_data() { compare_data(false); } void compare_QString_QChar() { compare_impl<QString, QChar>(); } + void compare_QString_char16_t_data() { compare_data(false); } + void compare_QString_char16_t() { compare_impl<QString, char16_t>(); } void compare_QString_QStringRef_data() { compare_data(); } void compare_QString_QStringRef() { compare_impl<QString, QStringRef>(); } void compare_QString_QString_data() { compare_data(); } @@ -161,6 +191,8 @@ private Q_SLOTS: void compare_QStringView_QChar_data() { compare_data(false); } void compare_QStringView_QChar() { compare_impl<QStringView, QChar>(); } + void compare_QStringView_char16_t_data() { compare_data(false); } + void compare_QStringView_char16_t() { compare_impl<QStringView, char16_t>(); } void compare_QStringView_QStringRef_data() { compare_data(); } void compare_QStringView_QStringRef() { compare_impl<QStringView, QStringRef>(); } void compare_QStringView_QString_data() { compare_data(); } @@ -178,6 +210,8 @@ private Q_SLOTS: void compare_QLatin1String_QChar_data() { compare_data(false); } void compare_QLatin1String_QChar() { compare_impl<QLatin1String, QChar>(); } + void compare_QLatin1String_char16_t_data() { compare_data(false); } + void compare_QLatin1String_char16_t() { compare_impl<QLatin1String, char16_t>(); } void compare_QLatin1String_QStringRef_data() { compare_data(); } void compare_QLatin1String_QStringRef() { compare_impl<QLatin1String, QStringRef>(); } void compare_QLatin1String_QString_data() { compare_data(); } @@ -193,6 +227,8 @@ private Q_SLOTS: void compare_QByteArray_QChar_data() { compare_data(false); } void compare_QByteArray_QChar() { compare_impl<QByteArray, QChar>(); } + void compare_QByteArray_char16_t_data() { compare_data(false); } + void compare_QByteArray_char16_t() { compare_impl<QByteArray, char16_t>(); } void compare_QByteArray_QStringRef_data() { compare_data(); } void compare_QByteArray_QStringRef() { compare_impl<QByteArray, QStringRef>(); } void compare_QByteArray_QString_data() { compare_data(); } @@ -206,6 +242,8 @@ private Q_SLOTS: void compare_const_char_star_QChar_data() { compare_data(false); } void compare_const_char_star_QChar() { compare_impl<const char *, QChar>(); } + //void compare_const_char_star_char16_t_data() { compare_data(false); } + //void compare_const_char_star_char16_t() { compare_impl<const char *, char16_t>(); } void compare_const_char_star_QStringRef_data() { compare_data(); } void compare_const_char_star_QStringRef() { compare_impl<const char *, QStringRef>(); } void compare_const_char_star_QString_data() { compare_data(); } @@ -223,10 +261,12 @@ private: void member_compare_impl() const; private Q_SLOTS: - // test all combinations of {QChar, QStringRef, QString, QStringView, QLatin1String, QByteArray, const char*} + // test all combinations of {QChar, char16_t, QStringRef, QString, QStringView, QLatin1String, QByteArray, const char*} #ifdef NOT_YET_IMPLEMENTED // probably never will be - what's the point of QChar::compare(QStringView)? void member_compare_QChar_QChar_data() { member_compare_data(false); } void member_compare_QChar_QChar() { member_compare_impl<QChar, QChar>(); } + void member_compare_QChar_char16_t_data() { member_compare_data(false); } + void member_compare_QChar_char16_t() { member_compare_impl<QChar, char16_t>(); } void member_compare_QChar_QStringRef_data() { member_compare_data(false); } void member_compare_QChar_QStringRef() { member_compare_impl<QChar, QStringRef>(); } void member_compare_QChar_QString_data() { member_compare_data(false); } @@ -241,8 +281,12 @@ private Q_SLOTS: void member_compare_QChar_const_char_star() { member_compare_impl<QChar, const char *>(); } #endif + // void member_compare_char16_t_XXX() - not possible + void member_compare_QStringRef_QChar_data() { member_compare_data(false); } void member_compare_QStringRef_QChar() { member_compare_impl<QStringRef, QChar>(); } + void member_compare_QStringRef_char16_t_data() { member_compare_data(false); } + void member_compare_QStringRef_char16_t() { member_compare_impl<QStringRef, char16_t>(); } void member_compare_QStringRef_QStringRef_data() { member_compare_data(); } void member_compare_QStringRef_QStringRef() { member_compare_impl<QStringRef, QStringRef>(); } void member_compare_QStringRef_QString_data() { member_compare_data(); } @@ -262,6 +306,8 @@ private Q_SLOTS: void member_compare_QString_QChar_data() { member_compare_data(false); } void member_compare_QString_QChar() { member_compare_impl<QString, QChar>(); } + void member_compare_QString_char16_t_data() { member_compare_data(false); } + void member_compare_QString_char16_t() { member_compare_impl<QString, char16_t>(); } void member_compare_QString_QStringRef_data() { member_compare_data(); } void member_compare_QString_QStringRef() { member_compare_impl<QString, QStringRef>(); } void member_compare_QString_QString_data() { member_compare_data(); } @@ -275,26 +321,29 @@ private Q_SLOTS: void member_compare_QString_const_char_star_data() { member_compare_data(); } void member_compare_QString_const_char_star() { member_compare_impl<QString, const char *>(); } -#ifdef NOT_YET_IMPLEMENTED // QChar doesn't implicitly convert to QStringView void member_compare_QStringView_QChar_data() { member_compare_data(false); } void member_compare_QStringView_QChar() { member_compare_impl<QStringView, QChar>(); } -#endif + void member_compare_QStringView_char16_t_data() { member_compare_data(false); } + void member_compare_QStringView_char16_t() { member_compare_impl<QStringView, char16_t>(); } void member_compare_QStringView_QStringRef_data() { member_compare_data(); } void member_compare_QStringView_QStringRef() { member_compare_impl<QStringView, QStringRef>(); } void member_compare_QStringView_QString_data() { member_compare_data(); } void member_compare_QStringView_QString() { member_compare_impl<QStringView, QString>(); } void member_compare_QStringView_QStringView_data() { member_compare_data(); } void member_compare_QStringView_QStringView() { member_compare_impl<QStringView, QStringView>(); } -#ifdef NOT_YET_IMPLEMENTED void member_compare_QStringView_QLatin1String_data() { member_compare_data(); } void member_compare_QStringView_QLatin1String() { member_compare_impl<QStringView, QLatin1String>(); } +#ifdef NOT_YET_IMPLEMENTED void member_compare_QStringView_QByteArray_data() { member_compare_data(); } void member_compare_QStringView_QByteArray() { member_compare_impl<QStringView, QByteArray>(); } void member_compare_QStringView_const_char_star_data() { member_compare_data(); } void member_compare_QStringView_const_char_star() { member_compare_impl<QStringView, const char *>(); } +#endif void member_compare_QLatin1String_QChar_data() { member_compare_data(false); } void member_compare_QLatin1String_QChar() { member_compare_impl<QLatin1String, QChar>(); } + void member_compare_QLatin1String_char16_t_data() { member_compare_data(false); } + void member_compare_QLatin1String_char16_t() { member_compare_impl<QLatin1String, char16_t>(); } void member_compare_QLatin1String_QStringRef_data() { member_compare_data(); } void member_compare_QLatin1String_QStringRef() { member_compare_impl<QLatin1String, QStringRef>(); } void member_compare_QLatin1String_QString_data() { member_compare_data(); } @@ -303,6 +352,7 @@ private Q_SLOTS: void member_compare_QLatin1String_QStringView() { member_compare_impl<QLatin1String, QStringView>(); } void member_compare_QLatin1String_QLatin1String_data() { member_compare_data(); } void member_compare_QLatin1String_QLatin1String() { member_compare_impl<QLatin1String, QLatin1String>(); } +#ifdef NOT_YET_IMPLEMENTED void member_compare_QLatin1String_QByteArray_data() { member_compare_data(); } void member_compare_QLatin1String_QByteArray() { member_compare_impl<QLatin1String, QByteArray>(); } void member_compare_QLatin1String_const_char_star_data() { member_compare_data(); } @@ -310,6 +360,8 @@ private Q_SLOTS: void member_compare_QByteArray_QChar_data() { member_compare_data(false); } void member_compare_QByteArray_QChar() { member_compare_impl<QByteArray, QChar>(); } + void member_compare_QByteArray_char16_t_data() { member_compare_data(false); } + void member_compare_QByteArray_char16_t() { member_compare_impl<QByteArray, char16_t>(); } void member_compare_QByteArray_QStringRef_data() { member_compare_data(); } void member_compare_QByteArray_QStringRef() { member_compare_impl<QByteArray, QStringRef>(); } void member_compare_QByteArray_QString_data() { member_compare_data(); } @@ -330,7 +382,7 @@ private: template <typename Haystack, typename Needle> void endsWith_impl() const; private Q_SLOTS: - // test all combinations of {QString, QStringRef, QStringView, QLatin1String} x {QString, QStringRef, QStringView, QLatin1String, QChar}: + // test all combinations of {QString, QStringRef, QStringView, QLatin1String} x {QString, QStringRef, QStringView, QLatin1String, QChar, char16_t}: void startsWith_QString_QString_data() { startsWith_data(); } void startsWith_QString_QString() { startsWith_impl<QString, QString>(); } void startsWith_QString_QStringRef_data() { startsWith_data(); } @@ -341,6 +393,8 @@ private Q_SLOTS: void startsWith_QString_QLatin1String() { startsWith_impl<QString, QLatin1String>(); } void startsWith_QString_QChar_data() { startsWith_data(false); } void startsWith_QString_QChar() { startsWith_impl<QString, QChar>(); } + void startsWith_QString_char16_t_data() { startsWith_data(false); } + void startsWith_QString_char16_t() { startsWith_impl<QString, char16_t>(); } void startsWith_QStringRef_QString_data() { startsWith_data(); } void startsWith_QStringRef_QString() { startsWith_impl<QStringRef, QString>(); } @@ -352,6 +406,8 @@ private Q_SLOTS: void startsWith_QStringRef_QLatin1String() { startsWith_impl<QStringRef, QLatin1String>(); } void startsWith_QStringRef_QChar_data() { startsWith_data(false); } void startsWith_QStringRef_QChar() { startsWith_impl<QStringRef, QChar>(); } + void startsWith_QStringRef_char16_t_data() { startsWith_data(false); } + void startsWith_QStringRef_char16_t() { startsWith_impl<QStringRef, char16_t>(); } void startsWith_QStringView_QString_data() { startsWith_data(); } void startsWith_QStringView_QString() { startsWith_impl<QStringView, QString>(); } @@ -363,6 +419,8 @@ private Q_SLOTS: void startsWith_QStringView_QLatin1String() { startsWith_impl<QStringView, QLatin1String>(); } void startsWith_QStringView_QChar_data() { startsWith_data(false); } void startsWith_QStringView_QChar() { startsWith_impl<QStringView, QChar>(); } + void startsWith_QStringView_char16_t_data() { startsWith_data(false); } + void startsWith_QStringView_char16_t() { startsWith_impl<QStringView, char16_t>(); } void startsWith_QLatin1String_QString_data() { startsWith_data(); } void startsWith_QLatin1String_QString() { startsWith_impl<QLatin1String, QString>(); } @@ -374,6 +432,8 @@ private Q_SLOTS: void startsWith_QLatin1String_QLatin1String() { startsWith_impl<QLatin1String, QLatin1String>(); } void startsWith_QLatin1String_QChar_data() { startsWith_data(false); } void startsWith_QLatin1String_QChar() { startsWith_impl<QLatin1String, QChar>(); } + void startsWith_QLatin1String_char16_t_data() { startsWith_data(false); } + void startsWith_QLatin1String_char16_t() { startsWith_impl<QLatin1String, char16_t>(); } void endsWith_QString_QString_data() { endsWith_data(); } void endsWith_QString_QString() { endsWith_impl<QString, QString>(); } @@ -385,6 +445,8 @@ private Q_SLOTS: void endsWith_QString_QLatin1String() { endsWith_impl<QString, QLatin1String>(); } void endsWith_QString_QChar_data() { endsWith_data(false); } void endsWith_QString_QChar() { endsWith_impl<QString, QChar>(); } + void endsWith_QString_char16_t_data() { endsWith_data(false); } + void endsWith_QString_char16_t() { endsWith_impl<QString, char16_t>(); } void endsWith_QStringRef_QString_data() { endsWith_data(); } void endsWith_QStringRef_QString() { endsWith_impl<QStringRef, QString>(); } @@ -396,6 +458,8 @@ private Q_SLOTS: void endsWith_QStringRef_QLatin1String() { endsWith_impl<QStringRef, QLatin1String>(); } void endsWith_QStringRef_QChar_data() { endsWith_data(false); } void endsWith_QStringRef_QChar() { endsWith_impl<QStringRef, QChar>(); } + void endsWith_QStringRef_char16_t_data() { endsWith_data(false); } + void endsWith_QStringRef_char16_t() { endsWith_impl<QStringRef, char16_t>(); } void endsWith_QStringView_QString_data() { endsWith_data(); } void endsWith_QStringView_QString() { endsWith_impl<QStringView, QString>(); } @@ -407,6 +471,8 @@ private Q_SLOTS: void endsWith_QStringView_QLatin1String() { endsWith_impl<QStringView, QLatin1String>(); } void endsWith_QStringView_QChar_data() { endsWith_data(false); } void endsWith_QStringView_QChar() { endsWith_impl<QStringView, QChar>(); } + void endsWith_QStringView_char16_t_data() { endsWith_data(false); } + void endsWith_QStringView_char16_t() { endsWith_impl<QStringView, char16_t>(); } void endsWith_QLatin1String_QString_data() { endsWith_data(); } void endsWith_QLatin1String_QString() { endsWith_impl<QLatin1String, QString>(); } @@ -418,6 +484,8 @@ private Q_SLOTS: void endsWith_QLatin1String_QLatin1String() { endsWith_impl<QLatin1String, QLatin1String>(); } void endsWith_QLatin1String_QChar_data() { endsWith_data(false); } void endsWith_QLatin1String_QChar() { endsWith_impl<QLatin1String, QChar>(); } + void endsWith_QLatin1String_char16_t_data() { endsWith_data(false); } + void endsWith_QLatin1String_char16_t() { endsWith_impl<QLatin1String, char16_t>(); } private: void split_data(bool rhsHasVariableLength = true); @@ -566,9 +634,10 @@ private Q_SLOTS: private: template <typename Haystack, typename Needle> void indexOf_impl() const; - void indexOf_data(); + void indexOf_data(bool rhsHasVariableLength = true); private Q_SLOTS: + // test all combinations of {QString, QLatin1String, QStringRef, QStringView} x {QString, QLatin1String, QStringRef, QStringView, QChar, char16_t}: void indexOf_QString_QString_data() { indexOf_data(); } void indexOf_QString_QString() { indexOf_impl<QString, QString>(); } void indexOf_QString_QLatin1String_data() { indexOf_data(); } @@ -577,6 +646,10 @@ private Q_SLOTS: void indexOf_QString_QStringRef() { indexOf_impl<QString, QStringRef>(); } void indexOf_QString_QStringView_data() { indexOf_data(); } void indexOf_QString_QStringView() { indexOf_impl<QString, QStringView>(); } + void indexOf_QString_QChar_data() { indexOf_data(false); } + void indexOf_QString_QChar() { indexOf_impl<QString, QChar>(); } + void indexOf_QString_char16_t_data() { indexOf_data(false); } + void indexOf_QString_char16_t() { indexOf_impl<QString, char16_t>(); } void indexOf_QLatin1String_QString_data() { indexOf_data(); } void indexOf_QLatin1String_QString() { indexOf_impl<QLatin1String, QString>(); } @@ -586,6 +659,10 @@ private Q_SLOTS: void indexOf_QLatin1String_QStringRef() { indexOf_impl<QLatin1String, QStringRef>(); } void indexOf_QLatin1String_QStringView_data() { indexOf_data(); } void indexOf_QLatin1String_QStringView() { indexOf_impl<QLatin1String, QStringView>(); } + void indexOf_QLatin1String_QChar_data() { indexOf_data(false); } + void indexOf_QLatin1String_QChar() { indexOf_impl<QLatin1String, QChar>(); } + void indexOf_QLatin1String_char16_t_data() { indexOf_data(false); } + void indexOf_QLatin1String_char16_t() { indexOf_impl<QLatin1String, char16_t>(); } void indexOf_QStringRef_QString_data() { indexOf_data(); } void indexOf_QStringRef_QString() { indexOf_impl<QStringRef, QString>(); } @@ -595,6 +672,10 @@ private Q_SLOTS: void indexOf_QStringRef_QStringRef() { indexOf_impl<QStringRef, QStringRef>(); } void indexOf_QStringRef_QStringView_data() { indexOf_data(); } void indexOf_QStringRef_QStringView() { indexOf_impl<QStringRef, QStringView>(); } + void indexOf_QStringRef_QChar_data() { indexOf_data(false); } + void indexOf_QStringRef_QChar() { indexOf_impl<QStringRef, QChar>(); } + void indexOf_QStringRef_char16_t_data() { indexOf_data(false); } + void indexOf_QStringRef_char16_t() { indexOf_impl<QStringRef, char16_t>(); } void indexOf_QStringView_QString_data() { indexOf_data(); } void indexOf_QStringView_QString() { indexOf_impl<QStringView, QString>(); } @@ -604,12 +685,17 @@ private Q_SLOTS: void indexOf_QStringView_QStringRef() { indexOf_impl<QStringView, QStringRef>(); } void indexOf_QStringView_QStringView_data() { indexOf_data(); } void indexOf_QStringView_QStringView() { indexOf_impl<QStringView, QStringView>(); } + void indexOf_QStringView_QChar_data() { indexOf_data(false); } + void indexOf_QStringView_QChar() { indexOf_impl<QStringView, QChar>(); } + void indexOf_QStringView_char16_t_data() { indexOf_data(false); } + void indexOf_QStringView_char16_t() { indexOf_impl<QStringView, char16_t>(); } private: template <typename Haystack, typename Needle> void contains_impl() const; - void contains_data(); + void contains_data(bool rhsHasVariableLength = true); private Q_SLOTS: + // test all combinations of {QString, QLatin1String, QStringRef, QStringView} x {QString, QLatin1String, QStringRef, QStringView, QChar, char16_t}: void contains_QString_QString_data() { contains_data(); } void contains_QString_QString() { contains_impl<QString, QString>(); } void contains_QString_QLatin1String_data() { contains_data(); } @@ -618,6 +704,10 @@ private Q_SLOTS: void contains_QString_QStringRef() { contains_impl<QString, QStringRef>(); } void contains_QString_QStringView_data() { contains_data(); } void contains_QString_QStringView() { contains_impl<QString, QStringView>(); } + void contains_QString_QChar_data() { contains_data(false); } + void contains_QString_QChar() { contains_impl<QString, QChar>(); } + void contains_QString_char16_t_data() { contains_data(false); } + void contains_QString_char16_t() { contains_impl<QString, char16_t>(); } void contains_QLatin1String_QString_data() { contains_data(); } void contains_QLatin1String_QString() { contains_impl<QLatin1String, QString>(); } @@ -627,6 +717,10 @@ private Q_SLOTS: void contains_QLatin1String_QStringRef() { contains_impl<QLatin1String, QStringRef>(); } void contains_QLatin1String_QStringView_data() { contains_data(); } void contains_QLatin1String_QStringView() { contains_impl<QLatin1String, QStringView>(); } + void contains_QLatin1String_QChar_data() { contains_data(false); } + void contains_QLatin1String_QChar() { contains_impl<QLatin1String, QChar>(); } + void contains_QLatin1String_char16_t_data() { contains_data(false); } + void contains_QLatin1String_char16_t() { contains_impl<QLatin1String, char16_t>(); } void contains_QStringRef_QString_data() { contains_data(); } void contains_QStringRef_QString() { contains_impl<QStringRef, QString>(); } @@ -636,6 +730,10 @@ private Q_SLOTS: void contains_QStringRef_QStringRef() { contains_impl<QStringRef, QStringRef>(); } void contains_QStringRef_QStringView_data() { contains_data(); } void contains_QStringRef_QStringView() { contains_impl<QStringRef, QStringView>(); } + void contains_QStringRef_QChar_data() { contains_data(false); } + void contains_QStringRef_QChar() { contains_impl<QStringRef, QChar>(); } + void contains_QStringRef_char16_t_data() { contains_data(false); } + void contains_QStringRef_char16_t() { contains_impl<QStringRef, char16_t>(); } void contains_QStringView_QString_data() { contains_data(); } void contains_QStringView_QString() { contains_impl<QStringView, QString>(); } @@ -645,12 +743,17 @@ private Q_SLOTS: void contains_QStringView_QStringRef() { contains_impl<QStringView, QStringRef>(); } void contains_QStringView_QStringView_data() { contains_data(); } void contains_QStringView_QStringView() { contains_impl<QStringView, QStringView>(); } + void contains_QStringView_QChar_data() { contains_data(false); } + void contains_QStringView_QChar() { contains_impl<QStringView, QChar>(); } + void contains_QStringView_char16_t_data() { contains_data(false); } + void contains_QStringView_char16_t() { contains_impl<QStringView, char16_t>(); } private: template <typename Haystack, typename Needle> void lastIndexOf_impl() const; - void lastIndexOf_data(); + void lastIndexOf_data(bool rhsHasVariableLength = true); private Q_SLOTS: + // test all combinations of {QString, QLatin1String, QStringRef, QStringView} x {QString, QLatin1String, QStringRef, QStringView, QChar, char16_t}: void lastIndexOf_QString_QString_data() { lastIndexOf_data(); } void lastIndexOf_QString_QString() { lastIndexOf_impl<QString, QString>(); } void lastIndexOf_QString_QLatin1String_data() { lastIndexOf_data(); } @@ -659,6 +762,10 @@ private Q_SLOTS: void lastIndexOf_QString_QStringRef() { lastIndexOf_impl<QString, QStringRef>(); } void lastIndexOf_QString_QStringView_data() { lastIndexOf_data(); } void lastIndexOf_QString_QStringView() { lastIndexOf_impl<QString, QStringView>(); } + void lastIndexOf_QString_QChar_data() { lastIndexOf_data(false); } + void lastIndexOf_QString_QChar() { lastIndexOf_impl<QString, QChar>(); } + void lastIndexOf_QString_char16_t_data() { lastIndexOf_data(false); } + void lastIndexOf_QString_char16_t() { lastIndexOf_impl<QString, char16_t>(); } void lastIndexOf_QLatin1String_QString_data() { lastIndexOf_data(); } void lastIndexOf_QLatin1String_QString() { lastIndexOf_impl<QLatin1String, QString>(); } @@ -668,6 +775,10 @@ private Q_SLOTS: void lastIndexOf_QLatin1String_QStringRef() { lastIndexOf_impl<QLatin1String, QStringRef>(); } void lastIndexOf_QLatin1String_QStringView_data() { lastIndexOf_data(); } void lastIndexOf_QLatin1String_QStringView() { lastIndexOf_impl<QLatin1String, QStringView>(); } + void lastIndexOf_QLatin1String_QChar_data() { lastIndexOf_data(false); } + void lastIndexOf_QLatin1String_QChar() { lastIndexOf_impl<QLatin1String, QChar>(); } + void lastIndexOf_QLatin1String_char16_t_data() { lastIndexOf_data(false); } + void lastIndexOf_QLatin1String_char16_t() { lastIndexOf_impl<QLatin1String, char16_t>(); } void lastIndexOf_QStringRef_QString_data() { lastIndexOf_data(); } void lastIndexOf_QStringRef_QString() { lastIndexOf_impl<QStringRef, QString>(); } @@ -677,6 +788,10 @@ private Q_SLOTS: void lastIndexOf_QStringRef_QStringRef() { lastIndexOf_impl<QStringRef, QStringRef>(); } void lastIndexOf_QStringRef_QStringView_data() { lastIndexOf_data(); } void lastIndexOf_QStringRef_QStringView() { lastIndexOf_impl<QStringRef, QStringView>(); } + void lastIndexOf_QStringRef_QChar_data() { lastIndexOf_data(false); } + void lastIndexOf_QStringRef_QChar() { lastIndexOf_impl<QStringRef, QChar>(); } + void lastIndexOf_QStringRef_char16_t_data() { lastIndexOf_data(false); } + void lastIndexOf_QStringRef_char16_t() { lastIndexOf_impl<QStringRef, char16_t>(); } void lastIndexOf_QStringView_QString_data() { lastIndexOf_data(); } void lastIndexOf_QStringView_QString() { lastIndexOf_impl<QStringView, QString>(); } @@ -686,6 +801,10 @@ private Q_SLOTS: void lastIndexOf_QStringView_QStringRef() { lastIndexOf_impl<QStringView, QStringRef>(); } void lastIndexOf_QStringView_QStringView_data() { lastIndexOf_data(); } void lastIndexOf_QStringView_QStringView() { lastIndexOf_impl<QStringView, QStringView>(); } + void lastIndexOf_QStringView_QChar_data() { lastIndexOf_data(false); } + void lastIndexOf_QStringView_QChar() { lastIndexOf_impl<QStringView, QChar>(); } + void lastIndexOf_QStringView_char16_t_data() { lastIndexOf_data(false); } + void lastIndexOf_QStringView_char16_t() { lastIndexOf_impl<QStringView, char16_t>(); } }; void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty) @@ -725,6 +844,8 @@ void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty) ROW("0", ""); ROW("0", "1"); ROW("0", "0"); + ROW("10", "0"); + ROW("01", "1"); ROW("\xE4", "\xE4"); // ä <> ä ROW("\xE4", "\xC4"); // ä <> Ä #undef ROW @@ -741,6 +862,7 @@ template <typename String> String detached(String s) template <class Str> Str make(const QStringRef &sf, QLatin1String l1, const QByteArray &u8); template <> QChar make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf.isEmpty() ? QChar() : sf.at(0); } +template <> char16_t make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf.isEmpty() ? char16_t() : char16_t{sf.at(0).unicode()}; } template <> QStringRef make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf; } template <> QString make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf.toString(); } template <> QStringView make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf; } @@ -783,15 +905,6 @@ void tst_QStringApiSymmetry::compare_impl() const const auto lhs = make<LHS>(lhsUnicode, lhsLatin1, lhsU8); const auto rhs = make<RHS>(rhsUnicode, rhsLatin1, rhsU8); -#ifdef Q_COMPILER_NOEXCEPT -# define QVERIFY_NOEXCEPT(expr) do { \ - if (has_nothrow_compare<LHS, RHS>::value) {} else \ - QEXPECT_FAIL("", "Qt is missing a nothrow utf8-utf16 comparator", Continue); \ - QVERIFY(noexcept(expr)); } while (0) -#else -# define QVERIFY_NOEXCEPT(expr) -#endif - #define CHECK(op) \ QVERIFY_NOEXCEPT(lhs op rhs); \ do { if (caseSensitiveCompareResult op 0) { \ @@ -825,15 +938,6 @@ void tst_QStringApiSymmetry::member_compare_impl() const const auto lhs = make<LHS>(lhsUnicode, lhsLatin1, lhsU8); const auto rhs = make<RHS>(rhsUnicode, rhsLatin1, rhsU8); -#define QVERIFY_NOEXCEPT(expr) do { \ - if (has_nothrow_compare<LHS, RHS>::value) {} else \ - QEXPECT_FAIL("", "Qt is missing a nothrow utf8-utf16 comparator", Continue); \ - QVERIFY(noexcept(expr)); } while (0) - - if (std::is_same<LHS, QByteArray>::value || // needs to simply be marked as noexcept - ((std::is_same<LHS, QString>::value || std::is_same<LHS, QStringRef>::value) - && std::is_same<RHS, QChar>::value)) // implict QChar -> QString conversion kills noexcept - QEXPECT_FAIL("", "known issues, will be fixed before 5.14 release", Continue); QVERIFY_NOEXCEPT(lhs.compare(rhs, Qt::CaseSensitive)); QCOMPARE(sign(lhs.compare(rhs)), caseSensitiveCompareResult); @@ -1646,7 +1750,7 @@ void tst_QStringApiSymmetry::toUcs4_impl() QCOMPARE(unicode.isEmpty(), ucs4.isEmpty()); } -void tst_QStringApiSymmetry::indexOf_data() +void tst_QStringApiSymmetry::indexOf_data(bool rhsHasVariableLength) { QTest::addColumn<QString>("haystackU16"); QTest::addColumn<QLatin1String>("haystackL1"); @@ -1659,18 +1763,20 @@ void tst_QStringApiSymmetry::indexOf_data() constexpr qsizetype zeroPos = 0; constexpr qsizetype minus1Pos = -1; - QTest::addRow("haystack: null, needle: null") << null << QLatin1String() + if (rhsHasVariableLength) { + QTest::addRow("haystack: null, needle: null") << null << QLatin1String() << null << QLatin1String() << zeroPos << zeroPos << zeroPos; - QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("") + QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("") << null << QLatin1String() << zeroPos << zeroPos << zeroPos; - QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") + QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") << null << QLatin1String() << zeroPos << zeroPos << zeroPos; - QTest::addRow("haystack: null, needle: empty") << null << QLatin1String() + QTest::addRow("haystack: null, needle: empty") << null << QLatin1String() << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos; - QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") + QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos; - QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("") + QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("") << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos; + } QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("") << a << QLatin1String("a") << zeroPos << minus1Pos << minus1Pos; QTest::addRow("haystack: null, needle: a") << null << QLatin1String() @@ -1702,17 +1808,19 @@ void tst_QStringApiSymmetry::indexOf_data() ROW(ABC, b, 1, -1, 1); ROW(ABC, B, 2, -1, -1); - ROW(aBc, bc, 0, -1, 1); - ROW(aBc, Bc, 0, 1, 1); - ROW(aBc, bC, 0, -1, 1); - ROW(aBc, BC, 0, -1, 1); - - ROW(AbC, bc, 0, -1, 1); - ROW(AbC, Bc, 0, -1, 1); - ROW(AbC, bC, 0, 1, 1); - ROW(AbC, BC, 0, -1, 1); - ROW(AbC, BC, 1, -1, 1); - ROW(AbC, BC, 2, -1, -1); + if (rhsHasVariableLength) { + ROW(aBc, bc, 0, -1, 1); + ROW(aBc, Bc, 0, 1, 1); + ROW(aBc, bC, 0, -1, 1); + ROW(aBc, BC, 0, -1, 1); + + ROW(AbC, bc, 0, -1, 1); + ROW(AbC, Bc, 0, -1, 1); + ROW(AbC, bC, 0, 1, 1); + ROW(AbC, BC, 0, -1, 1); + ROW(AbC, BC, 1, -1, 1); + ROW(AbC, BC, 2, -1, -1); + } #undef ROW } @@ -1739,13 +1847,6 @@ void tst_QStringApiSymmetry::indexOf_impl() const QCOMPARE(haystack.indexOf(needle, startpos), size_type(resultCS)); QCOMPARE(haystack.indexOf(needle, startpos, Qt::CaseSensitive), size_type(resultCS)); QCOMPARE(haystack.indexOf(needle, startpos, Qt::CaseInsensitive), size_type(resultCIS)); - - if (needle.size() == 1) - { - QCOMPARE(haystack.indexOf(needle[0], startpos), size_type(resultCS)); - QCOMPARE(haystack.indexOf(needle[0], startpos, Qt::CaseSensitive), size_type(resultCS)); - QCOMPARE(haystack.indexOf(needle[0], startpos, Qt::CaseInsensitive), size_type(resultCIS)); - } } static QString ABCDEFGHIEfGEFG = QStringLiteral("ABCDEFGHIEfGEFG"); @@ -1755,7 +1856,7 @@ static QString asd = QStringLiteral("asd"); static QString asdf = QStringLiteral("asdf"); static QString Z = QStringLiteral("Z"); -void tst_QStringApiSymmetry::contains_data() +void tst_QStringApiSymmetry::contains_data(bool rhsHasVariableLength) { QTest::addColumn<QString>("haystackU16"); QTest::addColumn<QLatin1String>("haystackL1"); @@ -1764,18 +1865,20 @@ void tst_QStringApiSymmetry::contains_data() QTest::addColumn<bool>("resultCS"); QTest::addColumn<bool>("resultCIS"); - QTest::addRow("haystack: null, needle: null") << null << QLatin1String() + if (rhsHasVariableLength) { + QTest::addRow("haystack: null, needle: null") << null << QLatin1String() << null << QLatin1String() << true << true; - QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("") + QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("") << null << QLatin1String() << true << true; - QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") + QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") << null << QLatin1String() << true << true; - QTest::addRow("haystack: null, needle: empty") << null << QLatin1String() + QTest::addRow("haystack: null, needle: empty") << null << QLatin1String() << empty << QLatin1String("") << true << true; - QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") + QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") << empty << QLatin1String("") << true << true;; - QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("") + QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("") << empty << QLatin1String("") << true << true; + } QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("") << a << QLatin1String("a") << false << false; QTest::addRow("haystack: null, needle: a") << null << QLatin1String() @@ -1789,8 +1892,10 @@ void tst_QStringApiSymmetry::contains_data() ROW(ABCDEFGHIEfGEFG, A, true, true); ROW(ABCDEFGHIEfGEFG, a, false, true); ROW(ABCDEFGHIEfGEFG, Z, false, false); - ROW(ABCDEFGHIEfGEFG, EFG, true, true); - ROW(ABCDEFGHIEfGEFG, efg, false, true); + if (rhsHasVariableLength) { + ROW(ABCDEFGHIEfGEFG, EFG, true, true); + ROW(ABCDEFGHIEfGEFG, efg, false, true); + } ROW(ABCDEFGHIEfGEFG, E, true, true); ROW(ABCDEFGHIEfGEFG, e, false, true); #undef ROW @@ -1815,16 +1920,9 @@ void tst_QStringApiSymmetry::contains_impl() const QCOMPARE(haystack.contains(needle), resultCS); QCOMPARE(haystack.contains(needle, Qt::CaseSensitive), resultCS); QCOMPARE(haystack.contains(needle, Qt::CaseInsensitive), resultCIS); - - if (needle.size() == 1) - { - QCOMPARE(haystack.contains(needle[0]), resultCS); - QCOMPARE(haystack.contains(needle[0], Qt::CaseSensitive), resultCS); - QCOMPARE(haystack.contains(needle[0], Qt::CaseInsensitive), resultCIS); - } } -void tst_QStringApiSymmetry::lastIndexOf_data() +void tst_QStringApiSymmetry::lastIndexOf_data(bool rhsHasVariableLength) { QTest::addColumn<QString>("haystackU16"); QTest::addColumn<QLatin1String>("haystackL1"); @@ -1837,38 +1935,43 @@ void tst_QStringApiSymmetry::lastIndexOf_data() constexpr qsizetype zeroPos = 0; constexpr qsizetype minus1Pos = -1; - QTest::addRow("haystack: null, needle: null") << null << QLatin1String() + if (rhsHasVariableLength) { + QTest::addRow("haystack: null, needle: null") << null << QLatin1String() << null << QLatin1String() << minus1Pos << minus1Pos << minus1Pos; - QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("") + QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("") << null << QLatin1String() << minus1Pos << minus1Pos << minus1Pos; - QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") + QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") << null << QLatin1String() << minus1Pos << zeroPos << zeroPos; - QTest::addRow("haystack: null, needle: empty") << null << QLatin1String() + QTest::addRow("haystack: null, needle: empty") << null << QLatin1String() << empty << QLatin1String("") << minus1Pos << minus1Pos << minus1Pos; - QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") + QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") << empty << QLatin1String("") << minus1Pos << zeroPos << zeroPos; - QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("") + QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("") << empty << QLatin1String("") << minus1Pos << minus1Pos << minus1Pos; + } QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("") << a << QLatin1String("a") << minus1Pos << minus1Pos << minus1Pos; QTest::addRow("haystack: null, needle: a") << null << QLatin1String() << a << QLatin1String("a") << minus1Pos << minus1Pos << minus1Pos; - QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") + if (rhsHasVariableLength) { + QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") << null << QLatin1String() << qsizetype(1) << qsizetype(1) << qsizetype(1); - QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") + QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") << empty << QLatin1String("") << qsizetype(1) << qsizetype(1) << qsizetype(1); - QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") + QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") << null << QLatin1String() << qsizetype(2) << minus1Pos << minus1Pos; - QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") + QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") << empty << QLatin1String("") << qsizetype(2) << minus1Pos << minus1Pos; + } #define ROW(h, n, st, cs, cis) \ QTest::addRow("haystack: %s, needle: %s", #h, #n) << h << QLatin1String(#h) \ << n << QLatin1String(#n) \ << qsizetype(st) << qsizetype(cs) << qsizetype(cis) - ROW(asd, asdf, -1, -1, -1); + if (rhsHasVariableLength) + ROW(asd, asdf, -1, -1, -1); ROW(ABCDEFGHIEfGEFG, G, -1, 14, 14); ROW(ABCDEFGHIEfGEFG, g, -1, -1, 14); @@ -1895,13 +1998,15 @@ void tst_QStringApiSymmetry::lastIndexOf_data() ROW(ABCDEFGHIEfGEFG, A, -15, 0, 0); ROW(ABCDEFGHIEfGEFG, a, -15, -1, 0); - ROW(ABCDEFGHIEfGEFG, efg, 0, -1, -1); - ROW(ABCDEFGHIEfGEFG, efg, 15, -1, -1); - ROW(ABCDEFGHIEfGEFG, efg, -15, -1, -1); - ROW(ABCDEFGHIEfGEFG, efg, 14, -1, 12); - ROW(ABCDEFGHIEfGEFG, efg, 12, -1, 12); - ROW(ABCDEFGHIEfGEFG, efg, -12, -1, -1); - ROW(ABCDEFGHIEfGEFG, efg, 11, -1, 9); + if (rhsHasVariableLength) { + ROW(ABCDEFGHIEfGEFG, efg, 0, -1, -1); + ROW(ABCDEFGHIEfGEFG, efg, 15, -1, -1); + ROW(ABCDEFGHIEfGEFG, efg, -15, -1, -1); + ROW(ABCDEFGHIEfGEFG, efg, 14, -1, 12); + ROW(ABCDEFGHIEfGEFG, efg, 12, -1, 12); + ROW(ABCDEFGHIEfGEFG, efg, -12, -1, -1); + ROW(ABCDEFGHIEfGEFG, efg, 11, -1, 9); + } #undef ROW } @@ -1928,12 +2033,6 @@ void tst_QStringApiSymmetry::lastIndexOf_impl() const QCOMPARE(haystack.lastIndexOf(needle, startpos, Qt::CaseSensitive), size_type(resultCS)); QCOMPARE(haystack.lastIndexOf(needle, startpos, Qt::CaseInsensitive), size_type(resultCIS)); - if (needle.size() == 1) - { - QCOMPARE(haystack.lastIndexOf(needle[0], startpos), size_type(resultCS)); - QCOMPARE(haystack.lastIndexOf(needle[0], startpos, Qt::CaseSensitive), size_type(resultCS)); - QCOMPARE(haystack.lastIndexOf(needle[0], startpos, Qt::CaseInsensitive), size_type(resultCIS)); - } } QTEST_APPLESS_MAIN(tst_QStringApiSymmetry) diff --git a/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp b/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp new file mode 100644 index 0000000000..b681676d09 --- /dev/null +++ b/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp @@ -0,0 +1,1148 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <QLinkedList> + +#if QT_DEPRECATED_SINCE(5, 15) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED + +struct Movable +{ + Movable(char input = 'j') : i(input), state(Constructed) + { + ++liveCount; + } + Movable(const Movable &other) + : i(other.i) + , state(Constructed) + { + check(other.state, Constructed); + ++liveCount; + } + + ~Movable() + { + check(state, Constructed); + i = 0; + --liveCount; + state = Destructed; + } + + bool operator ==(const Movable &other) const + { + check(state, Constructed); + check(other.state, Constructed); + return i == other.i; + } + + Movable &operator=(const Movable &other) + { + check(state, Constructed); + check(other.state, Constructed); + i = other.i; + return *this; + } + char i; + + static int getLiveCount() { return liveCount; } +private: + static int liveCount; + + enum State { Constructed = 106, Destructed = 110 }; + State state; + + static void check(const State state1, const State state2) + { + QCOMPARE(int(state1), int(state2)); + } +}; + +int Movable::liveCount = 0; + +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE); +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(Movable); + +Q_DECLARE_METATYPE(QLinkedList<int>); + + +int qHash(const Movable& movable) +{ + return qHash(movable.i); +} + +struct Complex +{ + Complex(int val = 0) + : value(val) + , checkSum(this) + { + ++liveCount; + } + + Complex(Complex const &other) + : value(other.value) + , checkSum(this) + { + ++liveCount; + } + + Complex &operator=(Complex const &other) + { + check(); other.check(); + + value = other.value; + return *this; + } + + ~Complex() + { + --liveCount; + check(); + } + + operator int() const { return value; } + + bool operator==(Complex const &other) const + { + check(); other.check(); + return value == other.value; + } + + void check() const + { + QVERIFY(this == checkSum); + } + + static int getLiveCount() { return liveCount; } +private: + static int liveCount; + + int value; + void *checkSum; +}; + +int Complex::liveCount = 0; + +Q_DECLARE_METATYPE(Complex); + +// Tests depend on the fact that: +Q_STATIC_ASSERT(!QTypeInfo<int>::isStatic); +Q_STATIC_ASSERT(!QTypeInfo<int>::isComplex); +Q_STATIC_ASSERT(!QTypeInfo<Movable>::isStatic); +Q_STATIC_ASSERT(QTypeInfo<Movable>::isComplex); +Q_STATIC_ASSERT(QTypeInfo<Complex>::isStatic); +Q_STATIC_ASSERT(QTypeInfo<Complex>::isComplex); + +class tst_QLinkedList : public QObject +{ + Q_OBJECT +private slots: + void eraseValidIteratorsOnSharedList() const; + void insertWithIteratorsOnSharedList() const; + void lengthInt() const; + void lengthMovable() const; + void lengthComplex() const; + void lengthSignature() const; + void firstInt() const; + void firstMovable() const; + void firstComplex() const; + void lastInt() const; + void lastMovable() const; + void lastComplex() const; + void beginInt() const; + void beginMovable() const; + void beginComplex() const; + void endInt() const; + void endMovable() const; + void endComplex() const; + void containsInt() const; + void containsMovable() const; + void containsComplex() const; + void countInt() const; + void countMovable() const; + void countComplex() const; + void cpp17ctad() const; + void emptyInt() const; + void emptyMovable() const; + void emptyComplex() const; + void endsWithInt() const; + void endsWithMovable() const; + void endsWithComplex() const; + void removeAllInt() const; + void removeAllMovable() const; + void removeAllComplex() const; + void removeOneInt() const; + void removeOneMovable() const; + void removeOneComplex() const; + void reverseIterators() const; + void startsWithInt() const; + void startsWithMovable() const; + void startsWithComplex() const; + void takeFirstInt() const; + void takeFirstMovable() const; + void takeFirstComplex() const; + void takeLastInt() const; + void takeLastMovable() const; + void takeLastComplex() const; + void toStdListInt() const; + void toStdListMovable() const; + void toStdListComplex() const; + void testOperatorsInt() const; + void testOperatorsMovable() const; + void testOperatorsComplex() const; + void testSTLIteratorsInt() const; + void testSTLIteratorsMovable() const; + void testSTLIteratorsComplex() const; + + void initializeList() const; + + void constSharedNullInt() const; + void constSharedNullMovable() const; + void constSharedNullComplex() const; + + void setSharableInt() const; +private: + template<typename T> void length() const; + template<typename T> void first() const; + template<typename T> void last() const; + template<typename T> void begin() const; + template<typename T> void end() const; + template<typename T> void contains() const; + template<typename T> void count() const; + template<typename T> void empty() const; + template<typename T> void endsWith() const; + template<typename T> void move() const; + template<typename T> void removeAll() const; + template<typename T> void removeOne() const; + template<typename T> void startsWith() const; + template<typename T> void swap() const; + template<typename T> void takeFirst() const; + template<typename T> void takeLast() const; + template<typename T> void toStdList() const; + template<typename T> void value() const; + + template<typename T> void testOperators() const; + template<typename T> void testSTLIterators() const; + + template<typename T> void constSharedNull() const; + + int dummyForGuard; +}; + +template<typename T> struct SimpleValue +{ + static T at(int index) + { + return values[index % maxSize]; + } + static const uint maxSize = 7; + static const T values[maxSize]; +}; + +template<> +const int SimpleValue<int>::values[] = { 10, 20, 30, 40, 100, 101, 102 }; +template<> +const Movable SimpleValue<Movable>::values[] = { 10, 20, 30, 40, 100, 101, 102 }; +template<> +const Complex SimpleValue<Complex>::values[] = { 10, 20, 30, 40, 100, 101, 102 }; + +// Make some macros for the tests to use in order to be slightly more readable... +#define T_FOO SimpleValue<T>::at(0) +#define T_BAR SimpleValue<T>::at(1) +#define T_BAZ SimpleValue<T>::at(2) +#define T_CAT SimpleValue<T>::at(3) +#define T_DOG SimpleValue<T>::at(4) +#define T_BLAH SimpleValue<T>::at(5) +#define T_WEEE SimpleValue<T>::at(6) + +template<typename T> +void tst_QLinkedList::length() const +{ + /* Empty list. */ + { + const QLinkedList<T> list; + QCOMPARE(list.size(), 0); + } + + /* One entry. */ + { + QLinkedList<T> list; + list.append(T_FOO); + QCOMPARE(list.size(), 1); + } + + /* Two entries. */ + { + QLinkedList<T> list; + list.append(T_FOO); + list.append(T_BAR); + QCOMPARE(list.size(), 2); + } + + /* Three entries. */ + { + QLinkedList<T> list; + list.append(T_FOO); + list.append(T_BAR); + list.append(T_BAZ); + QCOMPARE(list.size(), 3); + } +} + +void tst_QLinkedList::eraseValidIteratorsOnSharedList() const +{ + QLinkedList<int> a, b; + a.append(5); + a.append(10); + a.append(20); + a.append(20); + a.append(20); + a.append(20); + a.append(30); + + QLinkedList<int>::iterator i = a.begin(); + ++i; + ++i; + ++i; + b = a; + QLinkedList<int>::iterator r = a.erase(i); + QCOMPARE(b.size(), 7); + QCOMPARE(a.size(), 6); + --r; + --r; + QCOMPARE(*r, 10); // Ensure that number 2 instance was removed; +} + +void tst_QLinkedList::insertWithIteratorsOnSharedList() const +{ + QLinkedList<int> a, b; + a.append(5); + a.append(10); + a.append(20); + QLinkedList<int>::iterator i = a.begin(); + ++i; + ++i; + b = a; + + QLinkedList<int>::iterator i2 = a.insert(i, 15); + QCOMPARE(b.size(), 3); + QCOMPARE(a.size(), 4); + --i2; + QCOMPARE(*i2, 10); +} + +void tst_QLinkedList::lengthInt() const +{ + length<int>(); +} + +void tst_QLinkedList::lengthMovable() const +{ + const int liveCount = Movable::getLiveCount(); + length<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::lengthComplex() const +{ + const int liveCount = Complex::getLiveCount(); + length<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +void tst_QLinkedList::lengthSignature() const +{ + /* Constness. */ + { + const QLinkedList<int> list; + /* The function should be const. */ + list.size(); + } +} + +template<typename T> +void tst_QLinkedList::first() const +{ + QLinkedList<T> list; + list << T_FOO << T_BAR; + + QCOMPARE(list.first(), T_FOO); + + // remove an item, make sure it still works + list.pop_front(); + QVERIFY(list.size() == 1); + QCOMPARE(list.first(), T_BAR); +} + +void tst_QLinkedList::firstInt() const +{ + first<int>(); +} + +void tst_QLinkedList::firstMovable() const +{ + const int liveCount = Movable::getLiveCount(); + first<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::firstComplex() const +{ + const int liveCount = Complex::getLiveCount(); + first<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> +void tst_QLinkedList::last() const +{ + QLinkedList<T> list; + list << T_FOO << T_BAR; + + QCOMPARE(list.last(), T_BAR); + + // remove an item, make sure it still works + list.pop_back(); + QVERIFY(list.size() == 1); + QCOMPARE(list.last(), T_FOO); +} + +void tst_QLinkedList::lastInt() const +{ + last<int>(); +} + +void tst_QLinkedList::lastMovable() const +{ + const int liveCount = Movable::getLiveCount(); + last<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::lastComplex() const +{ + const int liveCount = Complex::getLiveCount(); + last<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> +void tst_QLinkedList::begin() const +{ + QLinkedList<T> list; + list << T_FOO << T_BAR; + + QCOMPARE(*list.begin(), T_FOO); + + // remove an item, make sure it still works + list.pop_front(); + QVERIFY(list.size() == 1); + QCOMPARE(*list.begin(), T_BAR); +} + +void tst_QLinkedList::beginInt() const +{ + begin<int>(); +} + +void tst_QLinkedList::beginMovable() const +{ + const int liveCount = Movable::getLiveCount(); + begin<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::beginComplex() const +{ + const int liveCount = Complex::getLiveCount(); + begin<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> +void tst_QLinkedList::end() const +{ + QLinkedList<T> list; + list << T_FOO << T_BAR; + + QCOMPARE(*--list.end(), T_BAR); + + // remove an item, make sure it still works + list.pop_back(); + QVERIFY(list.size() == 1); + QCOMPARE(*--list.end(), T_FOO); +} + +void tst_QLinkedList::endInt() const +{ + end<int>(); +} + +void tst_QLinkedList::endMovable() const +{ + const int liveCount = Movable::getLiveCount(); + end<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::endComplex() const +{ + const int liveCount = Complex::getLiveCount(); + end<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> +void tst_QLinkedList::contains() const +{ + QLinkedList<T> list; + list << T_FOO << T_BAR << T_BAZ; + + QVERIFY(list.contains(T_FOO)); + QVERIFY(list.contains(T_BLAH) != true); + + // add it and make sure it matches + list.append(T_BLAH); + QVERIFY(list.contains(T_BLAH)); +} + +void tst_QLinkedList::containsInt() const +{ + contains<int>(); +} + +void tst_QLinkedList::containsMovable() const +{ + const int liveCount = Movable::getLiveCount(); + contains<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::containsComplex() const +{ + const int liveCount = Complex::getLiveCount(); + contains<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> +void tst_QLinkedList::count() const +{ + QLinkedList<T> list; + + // starts empty + QVERIFY(list.count() == 0); + + // goes up + list.append(T_FOO); + QVERIFY(list.count() == 1); + + // and up + list.append(T_BAR); + QVERIFY(list.count() == 2); + + // and down + list.pop_back(); + QVERIFY(list.count() == 1); + + // and empty. :) + list.pop_back(); + QVERIFY(list.count() == 0); +} + +void tst_QLinkedList::countInt() const +{ + count<int>(); +} + +void tst_QLinkedList::countMovable() const +{ + const int liveCount = Movable::getLiveCount(); + count<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::countComplex() const +{ + const int liveCount = Complex::getLiveCount(); + count<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +void tst_QLinkedList::cpp17ctad() const +{ +#ifdef __cpp_deduction_guides +#define QVERIFY_IS_LIST_OF(obj, Type) \ + QVERIFY2((std::is_same<decltype(obj), QLinkedList<Type>>::value), \ + QMetaType::typeName(qMetaTypeId<decltype(obj)::value_type>())) +#define CHECK(Type, One, Two, Three) \ + do { \ + const Type v[] = {One, Two, Three}; \ + QLinkedList v1 = {One, Two, Three}; \ + QVERIFY_IS_LIST_OF(v1, Type); \ + QLinkedList v2(v1.begin(), v1.end()); \ + QVERIFY_IS_LIST_OF(v2, Type); \ + QLinkedList v3(std::begin(v), std::end(v)); \ + QVERIFY_IS_LIST_OF(v3, Type); \ + } while (false) \ + /*end*/ + CHECK(int, 1, 2, 3); + CHECK(double, 1.0, 2.0, 3.0); + CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three")); +#undef QVERIFY_IS_LIST_OF +#undef CHECK +#else + QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler."); +#endif +} + +template<typename T> +void tst_QLinkedList::empty() const +{ + QLinkedList<T> list; + + // make sure it starts empty + QVERIFY(list.empty()); + + // and doesn't stay empty + list.append(T_FOO); + QVERIFY(!list.empty()); + + // and goes back to being empty + list.pop_back(); + QVERIFY(list.empty()); +} + +void tst_QLinkedList::emptyInt() const +{ + empty<int>(); +} + +void tst_QLinkedList::emptyMovable() const +{ + const int liveCount = Movable::getLiveCount(); + empty<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::emptyComplex() const +{ + const int liveCount = Complex::getLiveCount(); + empty<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> +void tst_QLinkedList::endsWith() const +{ + QLinkedList<T> list; + list << T_FOO << T_BAR << T_BAZ; + + // test it returns correctly in both cases + QVERIFY(list.endsWith(T_BAZ)); + QVERIFY(!list.endsWith(T_BAR)); + + // remove an item and make sure the end item changes + list.pop_back(); + QVERIFY(list.endsWith(T_BAR)); +} + +void tst_QLinkedList::endsWithInt() const +{ + endsWith<int>(); +} + +void tst_QLinkedList::endsWithMovable() const +{ + const int liveCount = Movable::getLiveCount(); + endsWith<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::endsWithComplex() const +{ + const int liveCount = Complex::getLiveCount(); + endsWith<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> +void tst_QLinkedList::removeAll() const +{ + QLinkedList<T> list; + list << T_FOO << T_BAR << T_BAZ; + + // remove one instance + list.removeAll(T_BAR); + QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAZ); + + // many instances + list << T_FOO << T_BAR << T_BAZ << T_FOO << T_BAR << T_BAZ << T_FOO << T_BAR << T_BAZ; + list.removeAll(T_BAR); + QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ); + + // try remove something that doesn't exist + list.removeAll(T_WEEE); + QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ); +} + +void tst_QLinkedList::removeAllInt() const +{ + removeAll<int>(); +} + +void tst_QLinkedList::removeAllMovable() const +{ + const int liveCount = Movable::getLiveCount(); + removeAll<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::removeAllComplex() const +{ + const int liveCount = Complex::getLiveCount(); + removeAll<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> +void tst_QLinkedList::removeOne() const +{ + QLinkedList<T> list; + list << T_FOO << T_BAR << T_BAZ; + + // middle + list.removeOne(T_BAR); + QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAZ); + + // start + list.removeOne(T_FOO); + QCOMPARE(list, QLinkedList<T>() << T_BAZ); + + // last + list.removeOne(T_BAZ); + QCOMPARE(list, QLinkedList<T>()); + + // make sure it really only removes one :) + list << T_FOO << T_FOO; + list.removeOne(T_FOO); + QCOMPARE(list, QLinkedList<T>() << T_FOO); + + // try remove something that doesn't exist + list.removeOne(T_WEEE); + QCOMPARE(list, QLinkedList<T>() << T_FOO); +} + +void tst_QLinkedList::removeOneInt() const +{ + removeOne<int>(); +} + +void tst_QLinkedList::removeOneMovable() const +{ + const int liveCount = Movable::getLiveCount(); + removeOne<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::removeOneComplex() const +{ + const int liveCount = Complex::getLiveCount(); + removeOne<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +void tst_QLinkedList::reverseIterators() const +{ + QLinkedList<int> l; + l << 1 << 2 << 3 << 4; + QLinkedList<int> lr = l; + std::reverse(lr.begin(), lr.end()); + const QLinkedList<int> &clr = lr; + QVERIFY(std::equal(l.begin(), l.end(), lr.rbegin())); + QVERIFY(std::equal(l.begin(), l.end(), lr.crbegin())); + QVERIFY(std::equal(l.begin(), l.end(), clr.rbegin())); + QVERIFY(std::equal(lr.rbegin(), lr.rend(), l.begin())); + QVERIFY(std::equal(lr.crbegin(), lr.crend(), l.begin())); + QVERIFY(std::equal(clr.rbegin(), clr.rend(), l.begin())); +} + +template<typename T> +void tst_QLinkedList::startsWith() const +{ + QLinkedList<T> list; + list << T_FOO << T_BAR << T_BAZ; + + // make sure it starts ok + QVERIFY(list.startsWith(T_FOO)); + + // remove an item + list.removeFirst(); + QVERIFY(list.startsWith(T_BAR)); +} + +void tst_QLinkedList::startsWithInt() const +{ + startsWith<int>(); +} + +void tst_QLinkedList::startsWithMovable() const +{ + const int liveCount = Movable::getLiveCount(); + startsWith<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::startsWithComplex() const +{ + const int liveCount = Complex::getLiveCount(); + startsWith<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> +void tst_QLinkedList::takeFirst() const +{ + QLinkedList<T> list; + list << T_FOO << T_BAR << T_BAZ; + + QCOMPARE(list.takeFirst(), T_FOO); + QVERIFY(list.size() == 2); + QCOMPARE(list.takeFirst(), T_BAR); + QVERIFY(list.size() == 1); + QCOMPARE(list.takeFirst(), T_BAZ); + QVERIFY(list.size() == 0); +} + +void tst_QLinkedList::takeFirstInt() const +{ + takeFirst<int>(); +} + +void tst_QLinkedList::takeFirstMovable() const +{ + const int liveCount = Movable::getLiveCount(); + takeFirst<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::takeFirstComplex() const +{ + const int liveCount = Complex::getLiveCount(); + takeFirst<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> +void tst_QLinkedList::takeLast() const +{ + QLinkedList<T> list; + list << T_FOO << T_BAR << T_BAZ; + + QCOMPARE(list.takeLast(), T_BAZ); + QCOMPARE(list.takeLast(), T_BAR); + QCOMPARE(list.takeLast(), T_FOO); +} + +void tst_QLinkedList::takeLastInt() const +{ + takeLast<int>(); +} + +void tst_QLinkedList::takeLastMovable() const +{ + const int liveCount = Movable::getLiveCount(); + takeLast<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::takeLastComplex() const +{ + const int liveCount = Complex::getLiveCount(); + takeLast<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> +void tst_QLinkedList::toStdList() const +{ + QLinkedList<T> list; + list << T_FOO << T_BAR << T_BAZ; + + // yuck. + std::list<T> slist; + slist.push_back(T_FOO); + slist.push_back(T_BAR); + slist.push_back(T_BAZ); + + QCOMPARE(list.toStdList(), slist); + QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAR << T_BAZ); +} + +void tst_QLinkedList::toStdListInt() const +{ + toStdList<int>(); +} + +void tst_QLinkedList::toStdListMovable() const +{ + const int liveCount = Movable::getLiveCount(); + toStdList<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::toStdListComplex() const +{ + const int liveCount = Complex::getLiveCount(); + toStdList<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> +void tst_QLinkedList::testOperators() const +{ + QLinkedList<T> list; + list << T_FOO << T_BAR << T_BAZ; + + QLinkedList<T> listtwo; + listtwo << T_FOO << T_BAR << T_BAZ; + + // test equal + QVERIFY(list == listtwo); + + // not equal + listtwo.append(T_CAT); + QVERIFY(list != listtwo); + + // += + list += listtwo; + QVERIFY(list.size() == 7); + QVERIFY(listtwo.size() == 4); + QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAR << T_BAZ + << T_FOO << T_BAR << T_BAZ << T_CAT); + + // = + list = listtwo; + QCOMPARE(list, listtwo); + QCOMPARE(list, QLinkedList<T>() << T_FOO << T_BAR << T_BAZ << T_CAT); +} + +void tst_QLinkedList::testOperatorsInt() const +{ + testOperators<int>(); +} + +void tst_QLinkedList::testOperatorsMovable() const +{ + const int liveCount = Movable::getLiveCount(); + testOperators<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::testOperatorsComplex() const +{ + const int liveCount = Complex::getLiveCount(); + testOperators<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> +void tst_QLinkedList::testSTLIterators() const +{ + QLinkedList<T> list; + + // create a list + list << T_FOO << T_BAR << T_BAZ; + typename QLinkedList<T>::iterator it = list.begin(); + QCOMPARE(*it, T_FOO); it++; + QCOMPARE(*it, T_BAR); it++; + QCOMPARE(*it, T_BAZ); it++; + QCOMPARE(it, list.end()); it--; + + // walk backwards + QCOMPARE(*it, T_BAZ); it--; + QCOMPARE(*it, T_BAR); it--; + QCOMPARE(*it, T_FOO); + + // test erase + it = list.erase(it); + QVERIFY(list.size() == 2); + QCOMPARE(*it, T_BAR); + + // test multiple erase + it = list.erase(it, it + 2); + QVERIFY(list.size() == 0); + QCOMPARE(it, list.end()); + + // insert again + it = list.insert(it, T_FOO); + QVERIFY(list.size() == 1); + QCOMPARE(*it, T_FOO); + + // insert again + it = list.insert(it, T_BAR); + QVERIFY(list.size() == 2); + QCOMPARE(*it++, T_BAR); + QCOMPARE(*it, T_FOO); +} + +void tst_QLinkedList::testSTLIteratorsInt() const +{ + testSTLIterators<int>(); +} + +void tst_QLinkedList::testSTLIteratorsMovable() const +{ + const int liveCount = Movable::getLiveCount(); + testSTLIterators<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::testSTLIteratorsComplex() const +{ + const int liveCount = Complex::getLiveCount(); + testSTLIterators<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +void tst_QLinkedList::initializeList() const +{ + QLinkedList<int> v1 { 2, 3, 4 }; + QCOMPARE(v1, QLinkedList<int>() << 2 << 3 << 4); + QCOMPARE(v1, (QLinkedList<int> { 2, 3, 4})); + + QLinkedList<QLinkedList<int>> v2{ v1, { 1 }, QLinkedList<int>(), { 2, 3, 4 } }; + QLinkedList<QLinkedList<int>> v3; + v3 << v1 << (QLinkedList<int>() << 1) << QLinkedList<int>() << v1; + QCOMPARE(v3, v2); +} + + +template<typename T> +void tst_QLinkedList::constSharedNull() const +{ + QLinkedList<T> list2; +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) + QLinkedList<T> list1; + list1.setSharable(false); + QVERIFY(list1.isDetached()); + + list2.setSharable(true); +#endif + QVERIFY(!list2.isDetached()); +} + +void tst_QLinkedList::constSharedNullInt() const +{ + constSharedNull<int>(); +} + +void tst_QLinkedList::constSharedNullMovable() const +{ + const int liveCount = Movable::getLiveCount(); + constSharedNull<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QLinkedList::constSharedNullComplex() const +{ + const int liveCount = Complex::getLiveCount(); + constSharedNull<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + + +void tst_QLinkedList::setSharableInt() const +{ +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) + QLinkedList<int> orglist; + orglist << 0 << 1 << 2 << 3 << 4 << 5; + int size = 6; + + QLinkedList<int> list; + list = orglist; + + QVERIFY(!list.isDetached()); + list.setSharable(true); + + QCOMPARE(list.size(), size); + + { + QLinkedList<int> copy(list); + QVERIFY(!copy.isDetached()); + QVERIFY(copy.isSharedWith(list)); + } + + list.setSharable(false); + QVERIFY(list.isDetached() || list.isSharedWith(QLinkedList<int>())); + + { + QLinkedList<int> copy(list); + + QVERIFY(copy.isDetached() || copy.isSharedWith(QLinkedList<int>())); + QCOMPARE(copy.size(), size); + QCOMPARE(copy, list); + } + + list.setSharable(true); + + { + QLinkedList<int> copy(list); + + QVERIFY(!copy.isDetached()); + QVERIFY(copy.isSharedWith(list)); + } + + QLinkedList<int>::const_iterator it = list.constBegin(); + for (int i = 0; i < list.size(); ++i) { + QCOMPARE(int(*it), i); + ++it; + } + + QCOMPARE(list.size(), size); +#endif +} + +QT_WARNING_POP +#else +class tst_QLinkedList : public QObject +{ + Q_OBJECT +private slots: + void initTestCase() { QSKIP("Deprecated APIs are disabled, skipping this test."); } +}; + +#endif // QT_DEPRECATED_SINCE(5, 15) + +QTEST_APPLESS_MAIN(tst_QLinkedList) +#include "tst_qlinkedlist.moc" diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index 7418f447e6..ce88c6a7a4 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -46,6 +46,7 @@ #include <private/qdrawhelper_p.h> #include <qpainter.h> +#include <qpainterpath.h> #include <qqueue.h> #include <qscreen.h> diff --git a/tests/auto/gui/painting/qregion/tst_qregion.cpp b/tests/auto/gui/painting/qregion/tst_qregion.cpp index d1ea7706b9..aa9a84ba8e 100644 --- a/tests/auto/gui/painting/qregion/tst_qregion.cpp +++ b/tests/auto/gui/painting/qregion/tst_qregion.cpp @@ -32,6 +32,7 @@ #include <qbitmap.h> #include <qpainter.h> +#include <qpainterpath.h> #include <qpolygon.h> class tst_QRegion : public QObject diff --git a/tests/auto/gui/painting/qtransform/tst_qtransform.cpp b/tests/auto/gui/painting/qtransform/tst_qtransform.cpp index 97c6ad60b8..2dcb564e2b 100644 --- a/tests/auto/gui/painting/qtransform/tst_qtransform.cpp +++ b/tests/auto/gui/painting/qtransform/tst_qtransform.cpp @@ -28,11 +28,11 @@ #include <QtTest/QtTest> -#include "qtransform.h" +#include <qpainterpath.h> #include <qpolygon.h> +#include <qtransform.h> #include <qdebug.h> - class tst_QTransform : public QObject { Q_OBJECT diff --git a/tests/auto/gui/qopengl/tst_qopengl.cpp b/tests/auto/gui/qopengl/tst_qopengl.cpp index 8dd8b95daf..ad0dfb5c08 100644 --- a/tests/auto/gui/qopengl/tst_qopengl.cpp +++ b/tests/auto/gui/qopengl/tst_qopengl.cpp @@ -36,6 +36,7 @@ #include <QtGui/QOpenGLFunctions> #include <QtGui/QOpenGLFunctions_4_2_Core> #include <QtGui/QPainter> +#include <QtGui/QPainterPath> #include <QtGui/QScreen> #include <QtGui/QWindow> #include <QtGui/QOffscreenSurface> diff --git a/tests/auto/gui/rhi/qrhi/data/buildshaders.bat b/tests/auto/gui/rhi/qrhi/data/buildshaders.bat index 5b8a77b833..0cfeaaaff3 100644 --- a/tests/auto/gui/rhi/qrhi/data/buildshaders.bat +++ b/tests/auto/gui/rhi/qrhi/data/buildshaders.bat @@ -44,5 +44,6 @@ qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o simple.vert.qsb simple.vert qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o simple.frag.qsb simple.frag qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o simpletextured.vert.qsb simpletextured.vert qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o simpletextured.frag.qsb simpletextured.frag +qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 20 -o simpletextured_array.frag.qsb simpletextured_array.frag qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o textured.vert.qsb textured.vert qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o textured.frag.qsb textured.frag diff --git a/tests/auto/gui/rhi/qrhi/data/simple.frag.qsb b/tests/auto/gui/rhi/qrhi/data/simple.frag.qsb Binary files differindex c235108d39..43edbdffd9 100644 --- a/tests/auto/gui/rhi/qrhi/data/simple.frag.qsb +++ b/tests/auto/gui/rhi/qrhi/data/simple.frag.qsb diff --git a/tests/auto/gui/rhi/qrhi/data/simple.vert.qsb b/tests/auto/gui/rhi/qrhi/data/simple.vert.qsb Binary files differindex 68cfeb8f1d..06af5df492 100644 --- a/tests/auto/gui/rhi/qrhi/data/simple.vert.qsb +++ b/tests/auto/gui/rhi/qrhi/data/simple.vert.qsb diff --git a/tests/auto/gui/rhi/qrhi/data/simpletextured.frag.qsb b/tests/auto/gui/rhi/qrhi/data/simpletextured.frag.qsb Binary files differindex 397961c238..7749f3caad 100644 --- a/tests/auto/gui/rhi/qrhi/data/simpletextured.frag.qsb +++ b/tests/auto/gui/rhi/qrhi/data/simpletextured.frag.qsb diff --git a/tests/auto/gui/rhi/qrhi/data/simpletextured.vert.qsb b/tests/auto/gui/rhi/qrhi/data/simpletextured.vert.qsb Binary files differindex a9067949a5..c87d4b2fc1 100644 --- a/tests/auto/gui/rhi/qrhi/data/simpletextured.vert.qsb +++ b/tests/auto/gui/rhi/qrhi/data/simpletextured.vert.qsb diff --git a/tests/auto/gui/rhi/qrhi/data/simpletextured_array.frag b/tests/auto/gui/rhi/qrhi/data/simpletextured_array.frag new file mode 100644 index 0000000000..c5ee2057d8 --- /dev/null +++ b/tests/auto/gui/rhi/qrhi/data/simpletextured_array.frag @@ -0,0 +1,17 @@ +#version 440 + +layout(location = 0) in vec2 uv; +layout(location = 0) out vec4 fragColor; + +layout(binding = 0) uniform sampler2D tex[3]; + +void main() +{ + vec4 c0 = texture(tex[0], uv); + vec4 c1 = texture(tex[1], uv); + vec4 c2 = texture(tex[2], uv); + vec4 cc = c0 + c1 + c2; + vec4 c = vec4(clamp(cc.r, 0.0, 1.0), clamp(cc.g, 0.0, 1.0), clamp(cc.b, 0.0, 1.0), clamp(cc.a, 0.0, 1.0)); + c.rgb *= c.a; + fragColor = c; +} diff --git a/tests/auto/gui/rhi/qrhi/data/simpletextured_array.frag.qsb b/tests/auto/gui/rhi/qrhi/data/simpletextured_array.frag.qsb Binary files differnew file mode 100644 index 0000000000..362e220d25 --- /dev/null +++ b/tests/auto/gui/rhi/qrhi/data/simpletextured_array.frag.qsb diff --git a/tests/auto/gui/rhi/qrhi/data/textured.frag.qsb b/tests/auto/gui/rhi/qrhi/data/textured.frag.qsb Binary files differindex 018d732e2f..f669152c9c 100644 --- a/tests/auto/gui/rhi/qrhi/data/textured.frag.qsb +++ b/tests/auto/gui/rhi/qrhi/data/textured.frag.qsb diff --git a/tests/auto/gui/rhi/qrhi/data/textured.vert.qsb b/tests/auto/gui/rhi/qrhi/data/textured.vert.qsb Binary files differindex 44454d226e..d4ba474777 100644 --- a/tests/auto/gui/rhi/qrhi/data/textured.vert.qsb +++ b/tests/auto/gui/rhi/qrhi/data/textured.vert.qsb diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp index 549481aa21..c1793d7d4a 100644 --- a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp +++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp @@ -91,6 +91,8 @@ private slots: void renderToTextureSimple(); void renderToTextureTexturedQuad_data(); void renderToTextureTexturedQuad(); + void renderToTextureArrayOfTexturedQuad_data(); + void renderToTextureArrayOfTexturedQuad(); void renderToTextureTexturedQuadAndUniformBuffer_data(); void renderToTextureTexturedQuadAndUniformBuffer(); void renderToWindowSimple_data(); @@ -1468,6 +1470,147 @@ void tst_QRhi::renderToTextureTexturedQuad() QVERIFY(qGreen(result.pixel(214, 191)) > 2 * qBlue(result.pixel(214, 191))); } +void tst_QRhi::renderToTextureArrayOfTexturedQuad_data() +{ + rhiTestData(); +} + +void tst_QRhi::renderToTextureArrayOfTexturedQuad() +{ + QFETCH(QRhi::Implementation, impl); + QFETCH(QRhiInitParams *, initParams); + + QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr)); + if (!rhi) + QSKIP("QRhi could not be created, skipping testing rendering"); + + QImage inputImage; + inputImage.load(QLatin1String(":/data/qt256.png")); + QVERIFY(!inputImage.isNull()); + + QScopedPointer<QRhiTexture> texture(rhi->newTexture(QRhiTexture::RGBA8, inputImage.size(), 1, + QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource)); + QVERIFY(texture->build()); + + QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ texture.data() })); + QScopedPointer<QRhiRenderPassDescriptor> rpDesc(rt->newCompatibleRenderPassDescriptor()); + rt->setRenderPassDescriptor(rpDesc.data()); + QVERIFY(rt->build()); + + QRhiCommandBuffer *cb = nullptr; + QVERIFY(rhi->beginOffscreenFrame(&cb) == QRhi::FrameOpSuccess); + QVERIFY(cb); + + QRhiResourceUpdateBatch *updates = rhi->nextResourceUpdateBatch(); + + static const float verticesUvs[] = { + -1.0f, -1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f + }; + QScopedPointer<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(verticesUvs))); + QVERIFY(vbuf->build()); + updates->uploadStaticBuffer(vbuf.data(), verticesUvs); + + // In this test we pass 3 textures (and samplers) to the fragment shader in + // form of an array of combined image samplers. + + QScopedPointer<QRhiTexture> inputTexture(rhi->newTexture(QRhiTexture::RGBA8, inputImage.size())); + QVERIFY(inputTexture->build()); + updates->uploadTexture(inputTexture.data(), inputImage); + + QImage redImage(inputImage.size(), QImage::Format_RGBA8888); + redImage.fill(Qt::red); + + QScopedPointer<QRhiTexture> redTexture(rhi->newTexture(QRhiTexture::RGBA8, inputImage.size())); + QVERIFY(redTexture->build()); + updates->uploadTexture(redTexture.data(), redImage); + + QImage greenImage(inputImage.size(), QImage::Format_RGBA8888); + greenImage.fill(Qt::green); + + QScopedPointer<QRhiTexture> greenTexture(rhi->newTexture(QRhiTexture::RGBA8, inputImage.size())); + QVERIFY(greenTexture->build()); + updates->uploadTexture(greenTexture.data(), greenImage); + + QScopedPointer<QRhiSampler> sampler(rhi->newSampler(QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None, + QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge)); + QVERIFY(sampler->build()); + + QScopedPointer<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings()); + QRhiShaderResourceBinding::TextureAndSampler texSamplers[3] = { + { inputTexture.data(), sampler.data() }, + { redTexture.data(), sampler.data() }, + { greenTexture.data(), sampler.data() } + }; + srb->setBindings({ + QRhiShaderResourceBinding::sampledTextures(0, QRhiShaderResourceBinding::FragmentStage, 3, texSamplers) + }); + QVERIFY(srb->build()); + + QScopedPointer<QRhiGraphicsPipeline> pipeline(rhi->newGraphicsPipeline()); + pipeline->setTopology(QRhiGraphicsPipeline::TriangleStrip); + QShader vs = loadShader(":/data/simpletextured.vert.qsb"); + QVERIFY(vs.isValid()); + QShader fs = loadShader(":/data/simpletextured_array.frag.qsb"); + QVERIFY(fs.isValid()); + pipeline->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } }); + QRhiVertexInputLayout inputLayout; + inputLayout.setBindings({ { 4 * sizeof(float) } }); + inputLayout.setAttributes({ + { 0, 0, QRhiVertexInputAttribute::Float2, 0 }, + { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) } + }); + pipeline->setVertexInputLayout(inputLayout); + pipeline->setShaderResourceBindings(srb.data()); + pipeline->setRenderPassDescriptor(rpDesc.data()); + + QVERIFY(pipeline->build()); + + cb->beginPass(rt.data(), Qt::black, { 1.0f, 0 }, updates); + cb->setGraphicsPipeline(pipeline.data()); + cb->setShaderResources(); + cb->setViewport({ 0, 0, float(texture->pixelSize().width()), float(texture->pixelSize().height()) }); + QRhiCommandBuffer::VertexInput vbindings(vbuf.data(), 0); + cb->setVertexInput(0, 1, &vbindings); + cb->draw(4); + + QRhiReadbackResult readResult; + QImage result; + readResult.completed = [&readResult, &result] { + result = QImage(reinterpret_cast<const uchar *>(readResult.data.constData()), + readResult.pixelSize.width(), readResult.pixelSize.height(), + QImage::Format_RGBA8888_Premultiplied); + }; + QRhiResourceUpdateBatch *readbackBatch = rhi->nextResourceUpdateBatch(); + readbackBatch->readBackTexture({ texture.data() }, &readResult); + cb->endPass(readbackBatch); + + rhi->endOffscreenFrame(); + + QVERIFY(!result.isNull()); + + if (impl == QRhi::Null) + return; + + // Flip with D3D and Metal because these have Y down in images. Vulkan does + // not need this because there Y is down both in images and in NDC, which + // just happens to give correct results with our OpenGL-targeted vertex and + // UV data. + if (rhi->isYUpInFramebuffer() != rhi->isYUpInNDC()) + result = std::move(result).mirrored(); + + // we added the input image + red + green together, so red and green must be all 1 + for (int y = 0; y < result.height(); ++y) { + for (int x = 0; x < result.width(); ++x) { + const QRgb pixel = result.pixel(x, y); + QCOMPARE(qRed(pixel), 255); + QCOMPARE(qGreen(pixel), 255); + } + } +} + void tst_QRhi::renderToTextureTexturedQuadAndUniformBuffer_data() { rhiTestData(); diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp index a7a81e9f0b..6cd730bd38 100644 --- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp +++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp @@ -436,7 +436,7 @@ void tst_QSslCertificate::subjectAlternativeNames() void tst_QSslCertificate::utf8SubjectNames() { QSslCertificate cert = QSslCertificate::fromPath(testDataDir + "certificates/cert-ss-san-utf8.pem", QSsl::Pem, - QSslCertificate::FixedString).first(); + QSslCertificate::PatternSyntax::FixedString).first(); QVERIFY(!cert.isNull()); // O is "Heavy Metal Records" with heavy use of "decorations" like accents, umlauts etc., @@ -634,66 +634,66 @@ void tst_QSslCertificate::fromPath_qregularexpression_data() QTest::addColumn<bool>("pemencoding"); QTest::addColumn<int>("numCerts"); - QTest::newRow("empty fixed pem") << QString() << int(QSslCertificate::FixedString) << true << 0; - QTest::newRow("empty fixed der") << QString() << int(QSslCertificate::FixedString) << false << 0; - QTest::newRow("empty regexp pem") << QString() << int(QSslCertificate::RegExp) << true << 0; - QTest::newRow("empty regexp der") << QString() << int(QSslCertificate::RegExp) << false << 0; - QTest::newRow("empty wildcard pem") << QString() << int(QSslCertificate::Wildcard) << true << 0; - QTest::newRow("empty wildcard der") << QString() << int(QSslCertificate::Wildcard) << false << 0; - QTest::newRow("\"certificates\" fixed pem") << (testDataDir + "certificates") << int(QSslCertificate::FixedString) << true << 0; - QTest::newRow("\"certificates\" fixed der") << (testDataDir + "certificates") << int(QSslCertificate::FixedString) << false << 0; - QTest::newRow("\"certificates\" regexp pem") << (testDataDir + "certificates") << int(QSslCertificate::RegExp) << true << 0; - QTest::newRow("\"certificates\" regexp der") << (testDataDir + "certificates") << int(QSslCertificate::RegExp) << false << 0; - QTest::newRow("\"certificates\" wildcard pem") << (testDataDir + "certificates") << int(QSslCertificate::Wildcard) << true << 0; - QTest::newRow("\"certificates\" wildcard der") << (testDataDir + "certificates") << int(QSslCertificate::Wildcard) << false << 0; - QTest::newRow("\"certificates/cert.pem\" fixed pem") << (testDataDir + "certificates/cert.pem") << int(QSslCertificate::FixedString) << true << 1; - QTest::newRow("\"certificates/cert.pem\" fixed der") << (testDataDir + "certificates/cert.pem") << int(QSslCertificate::FixedString) << false << 0; - QTest::newRow("\"certificates/cert.pem\" regexp pem") << (testDataDir + "certificates/cert.pem") << int(QSslCertificate::RegExp) << true << 1; - QTest::newRow("\"certificates/cert.pem\" regexp der") << (testDataDir + "certificates/cert.pem") << int(QSslCertificate::RegExp) << false << 0; - QTest::newRow("\"certificates/cert.pem\" wildcard pem") << (testDataDir + "certificates/cert.pem") << int(QSslCertificate::Wildcard) << true << 1; - QTest::newRow("\"certificates/cert.pem\" wildcard der") << (testDataDir + "certificates/cert.pem") << int(QSslCertificate::Wildcard) << false << 0; - QTest::newRow("\"certificates/*\" fixed pem") << (testDataDir + "certificates/*") << int(QSslCertificate::FixedString) << true << 0; - QTest::newRow("\"certificates/*\" fixed der") << (testDataDir + "certificates/*") << int(QSslCertificate::FixedString) << false << 0; - QTest::newRow("\"certificates/*\" regexp pem") << (testDataDir + "certificates/*") << int(QSslCertificate::RegExp) << true << 0; - QTest::newRow("\"certificates/*\" regexp der") << (testDataDir + "certificates/*") << int(QSslCertificate::RegExp) << false << 0; - QTest::newRow("\"certificates/*\" wildcard pem") << (testDataDir + "certificates/*") << int(QSslCertificate::Wildcard) << true << 7; - QTest::newRow("\"certificates/ca*\" wildcard pem") << (testDataDir + "certificates/ca*") << int(QSslCertificate::Wildcard) << true << 1; - QTest::newRow("\"certificates/cert*\" wildcard pem") << (testDataDir + "certificates/cert*") << int(QSslCertificate::Wildcard) << true << 4; - QTest::newRow("\"certificates/cert-[sure]*\" wildcard pem") << (testDataDir + "certificates/cert-[sure]*") << int(QSslCertificate::Wildcard) << true << 3; - QTest::newRow("\"certificates/cert-[not]*\" wildcard pem") << (testDataDir + "certificates/cert-[not]*") << int(QSslCertificate::Wildcard) << true << 0; - QTest::newRow("\"certificates/*\" wildcard der") << (testDataDir + "certificates/*") << int(QSslCertificate::Wildcard) << false << 2; - QTest::newRow("\"c*/c*.pem\" fixed pem") << (testDataDir + "c*/c*.pem") << int(QSslCertificate::FixedString) << true << 0; - QTest::newRow("\"c*/c*.pem\" fixed der") << (testDataDir + "c*/c*.pem") << int(QSslCertificate::FixedString) << false << 0; - QTest::newRow("\"c*/c*.pem\" regexp pem") << (testDataDir + "c*/c*.pem") << int(QSslCertificate::RegExp) << true << 0; - QTest::newRow("\"c*/c*.pem\" regexp der") << (testDataDir + "c*/c*.pem") << int(QSslCertificate::RegExp) << false << 0; - QTest::newRow("\"c*/c*.pem\" wildcard pem") << (testDataDir + "c*/c*.pem") << int(QSslCertificate::Wildcard) << true << 5; - QTest::newRow("\"c*/c*.pem\" wildcard der") << (testDataDir + "c*/c*.pem") << int(QSslCertificate::Wildcard) << false << 0; - QTest::newRow("\"d*/c*.pem\" fixed pem") << (testDataDir + "d*/c*.pem") << int(QSslCertificate::FixedString) << true << 0; - QTest::newRow("\"d*/c*.pem\" fixed der") << (testDataDir + "d*/c*.pem") << int(QSslCertificate::FixedString) << false << 0; - QTest::newRow("\"d*/c*.pem\" regexp pem") << (testDataDir + "d*/c*.pem") << int(QSslCertificate::RegExp) << true << 0; - QTest::newRow("\"d*/c*.pem\" regexp der") << (testDataDir + "d*/c*.pem") << int(QSslCertificate::RegExp) << false << 0; - QTest::newRow("\"d*/c*.pem\" wildcard pem") << (testDataDir + "d*/c*.pem") << int(QSslCertificate::Wildcard) << true << 0; - QTest::newRow("\"d*/c*.pem\" wildcard der") << (testDataDir + "d*/c*.pem") << int(QSslCertificate::Wildcard) << false << 0; - QTest::newRow("\"c.*/c.*.pem\" fixed pem") << (testDataDir + "c.*/c.*.pem") << int(QSslCertificate::FixedString) << true << 0; - QTest::newRow("\"c.*/c.*.pem\" fixed der") << (testDataDir + "c.*/c.*.pem") << int(QSslCertificate::FixedString) << false << 0; - QTest::newRow("\"c.*/c.*.pem\" regexp pem") << (testDataDir + "c.*/c.*.pem") << int(QSslCertificate::RegExp) << true << 5; - QTest::newRow("\"c.*/c.*.pem\" regexp der") << (testDataDir + "c.*/c.*.pem") << int(QSslCertificate::RegExp) << false << 0; - QTest::newRow("\"c.*/c.*.pem\" wildcard pem") << (testDataDir + "c.*/c.*.pem") << int(QSslCertificate::Wildcard) << true << 0; - QTest::newRow("\"c.*/c.*.pem\" wildcard der") << (testDataDir + "c.*/c.*.pem") << int(QSslCertificate::Wildcard) << false << 0; - QTest::newRow("\"d.*/c.*.pem\" fixed pem") << (testDataDir + "d.*/c.*.pem") << int(QSslCertificate::FixedString) << true << 0; - QTest::newRow("\"d.*/c.*.pem\" fixed der") << (testDataDir + "d.*/c.*.pem") << int(QSslCertificate::FixedString) << false << 0; - QTest::newRow("\"d.*/c.*.pem\" regexp pem") << (testDataDir + "d.*/c.*.pem") << int(QSslCertificate::RegExp) << true << 0; - QTest::newRow("\"d.*/c.*.pem\" regexp der") << (testDataDir + "d.*/c.*.pem") << int(QSslCertificate::RegExp) << false << 0; - QTest::newRow("\"d.*/c.*.pem\" wildcard pem") << (testDataDir + "d.*/c.*.pem") << int(QSslCertificate::Wildcard) << true << 0; - QTest::newRow("\"d.*/c.*.pem\" wildcard der") << (testDataDir + "d.*/c.*.pem") << int(QSslCertificate::Wildcard) << false << 0; + QTest::newRow("empty fixed pem") << QString() << int(QSslCertificate::PatternSyntax::FixedString) << true << 0; + QTest::newRow("empty fixed der") << QString() << int(QSslCertificate::PatternSyntax::FixedString) << false << 0; + QTest::newRow("empty regexp pem") << QString() << int(QSslCertificate::PatternSyntax::RegularExpression) << true << 0; + QTest::newRow("empty regexp der") << QString() << int(QSslCertificate::PatternSyntax::RegularExpression) << false << 0; + QTest::newRow("empty wildcard pem") << QString() << int(QSslCertificate::PatternSyntax::Wildcard) << true << 0; + QTest::newRow("empty wildcard der") << QString() << int(QSslCertificate::PatternSyntax::Wildcard) << false << 0; + QTest::newRow("\"certificates\" fixed pem") << (testDataDir + "certificates") << int(QSslCertificate::PatternSyntax::FixedString) << true << 0; + QTest::newRow("\"certificates\" fixed der") << (testDataDir + "certificates") << int(QSslCertificate::PatternSyntax::FixedString) << false << 0; + QTest::newRow("\"certificates\" regexp pem") << (testDataDir + "certificates") << int(QSslCertificate::PatternSyntax::RegularExpression) << true << 0; + QTest::newRow("\"certificates\" regexp der") << (testDataDir + "certificates") << int(QSslCertificate::PatternSyntax::RegularExpression) << false << 0; + QTest::newRow("\"certificates\" wildcard pem") << (testDataDir + "certificates") << int(QSslCertificate::PatternSyntax::Wildcard) << true << 0; + QTest::newRow("\"certificates\" wildcard der") << (testDataDir + "certificates") << int(QSslCertificate::PatternSyntax::Wildcard) << false << 0; + QTest::newRow("\"certificates/cert.pem\" fixed pem") << (testDataDir + "certificates/cert.pem") << int(QSslCertificate::PatternSyntax::FixedString) << true << 1; + QTest::newRow("\"certificates/cert.pem\" fixed der") << (testDataDir + "certificates/cert.pem") << int(QSslCertificate::PatternSyntax::FixedString) << false << 0; + QTest::newRow("\"certificates/cert.pem\" regexp pem") << (testDataDir + "certificates/cert.pem") << int(QSslCertificate::PatternSyntax::RegularExpression) << true << 1; + QTest::newRow("\"certificates/cert.pem\" regexp der") << (testDataDir + "certificates/cert.pem") << int(QSslCertificate::PatternSyntax::RegularExpression) << false << 0; + QTest::newRow("\"certificates/cert.pem\" wildcard pem") << (testDataDir + "certificates/cert.pem") << int(QSslCertificate::PatternSyntax::Wildcard) << true << 1; + QTest::newRow("\"certificates/cert.pem\" wildcard der") << (testDataDir + "certificates/cert.pem") << int(QSslCertificate::PatternSyntax::Wildcard) << false << 0; + QTest::newRow("\"certificates/*\" fixed pem") << (testDataDir + "certificates/*") << int(QSslCertificate::PatternSyntax::FixedString) << true << 0; + QTest::newRow("\"certificates/*\" fixed der") << (testDataDir + "certificates/*") << int(QSslCertificate::PatternSyntax::FixedString) << false << 0; + QTest::newRow("\"certificates/*\" regexp pem") << (testDataDir + "certificates/*") << int(QSslCertificate::PatternSyntax::RegularExpression) << true << 0; + QTest::newRow("\"certificates/*\" regexp der") << (testDataDir + "certificates/*") << int(QSslCertificate::PatternSyntax::RegularExpression) << false << 0; + QTest::newRow("\"certificates/*\" wildcard pem") << (testDataDir + "certificates/*") << int(QSslCertificate::PatternSyntax::Wildcard) << true << 7; + QTest::newRow("\"certificates/ca*\" wildcard pem") << (testDataDir + "certificates/ca*") << int(QSslCertificate::PatternSyntax::Wildcard) << true << 1; + QTest::newRow("\"certificates/cert*\" wildcard pem") << (testDataDir + "certificates/cert*") << int(QSslCertificate::PatternSyntax::Wildcard) << true << 4; + QTest::newRow("\"certificates/cert-[sure]*\" wildcard pem") << (testDataDir + "certificates/cert-[sure]*") << int(QSslCertificate::PatternSyntax::Wildcard) << true << 3; + QTest::newRow("\"certificates/cert-[not]*\" wildcard pem") << (testDataDir + "certificates/cert-[not]*") << int(QSslCertificate::PatternSyntax::Wildcard) << true << 0; + QTest::newRow("\"certificates/*\" wildcard der") << (testDataDir + "certificates/*") << int(QSslCertificate::PatternSyntax::Wildcard) << false << 2; + QTest::newRow("\"c*/c*.pem\" fixed pem") << (testDataDir + "c*/c*.pem") << int(QSslCertificate::PatternSyntax::FixedString) << true << 0; + QTest::newRow("\"c*/c*.pem\" fixed der") << (testDataDir + "c*/c*.pem") << int(QSslCertificate::PatternSyntax::FixedString) << false << 0; + QTest::newRow("\"c*/c*.pem\" regexp pem") << (testDataDir + "c*/c*.pem") << int(QSslCertificate::PatternSyntax::RegularExpression) << true << 0; + QTest::newRow("\"c*/c*.pem\" regexp der") << (testDataDir + "c*/c*.pem") << int(QSslCertificate::PatternSyntax::RegularExpression) << false << 0; + QTest::newRow("\"c*/c*.pem\" wildcard pem") << (testDataDir + "c*/c*.pem") << int(QSslCertificate::PatternSyntax::Wildcard) << true << 5; + QTest::newRow("\"c*/c*.pem\" wildcard der") << (testDataDir + "c*/c*.pem") << int(QSslCertificate::PatternSyntax::Wildcard) << false << 0; + QTest::newRow("\"d*/c*.pem\" fixed pem") << (testDataDir + "d*/c*.pem") << int(QSslCertificate::PatternSyntax::FixedString) << true << 0; + QTest::newRow("\"d*/c*.pem\" fixed der") << (testDataDir + "d*/c*.pem") << int(QSslCertificate::PatternSyntax::FixedString) << false << 0; + QTest::newRow("\"d*/c*.pem\" regexp pem") << (testDataDir + "d*/c*.pem") << int(QSslCertificate::PatternSyntax::RegularExpression) << true << 0; + QTest::newRow("\"d*/c*.pem\" regexp der") << (testDataDir + "d*/c*.pem") << int(QSslCertificate::PatternSyntax::RegularExpression) << false << 0; + QTest::newRow("\"d*/c*.pem\" wildcard pem") << (testDataDir + "d*/c*.pem") << int(QSslCertificate::PatternSyntax::Wildcard) << true << 0; + QTest::newRow("\"d*/c*.pem\" wildcard der") << (testDataDir + "d*/c*.pem") << int(QSslCertificate::PatternSyntax::Wildcard) << false << 0; + QTest::newRow("\"c.*/c.*.pem\" fixed pem") << (testDataDir + "c.*/c.*.pem") << int(QSslCertificate::PatternSyntax::FixedString) << true << 0; + QTest::newRow("\"c.*/c.*.pem\" fixed der") << (testDataDir + "c.*/c.*.pem") << int(QSslCertificate::PatternSyntax::FixedString) << false << 0; + QTest::newRow("\"c.*/c.*.pem\" regexp pem") << (testDataDir + "c.*/c.*.pem") << int(QSslCertificate::PatternSyntax::RegularExpression) << true << 5; + QTest::newRow("\"c.*/c.*.pem\" regexp der") << (testDataDir + "c.*/c.*.pem") << int(QSslCertificate::PatternSyntax::RegularExpression) << false << 0; + QTest::newRow("\"c.*/c.*.pem\" wildcard pem") << (testDataDir + "c.*/c.*.pem") << int(QSslCertificate::PatternSyntax::Wildcard) << true << 0; + QTest::newRow("\"c.*/c.*.pem\" wildcard der") << (testDataDir + "c.*/c.*.pem") << int(QSslCertificate::PatternSyntax::Wildcard) << false << 0; + QTest::newRow("\"d.*/c.*.pem\" fixed pem") << (testDataDir + "d.*/c.*.pem") << int(QSslCertificate::PatternSyntax::FixedString) << true << 0; + QTest::newRow("\"d.*/c.*.pem\" fixed der") << (testDataDir + "d.*/c.*.pem") << int(QSslCertificate::PatternSyntax::FixedString) << false << 0; + QTest::newRow("\"d.*/c.*.pem\" regexp pem") << (testDataDir + "d.*/c.*.pem") << int(QSslCertificate::PatternSyntax::RegularExpression) << true << 0; + QTest::newRow("\"d.*/c.*.pem\" regexp der") << (testDataDir + "d.*/c.*.pem") << int(QSslCertificate::PatternSyntax::RegularExpression) << false << 0; + QTest::newRow("\"d.*/c.*.pem\" wildcard pem") << (testDataDir + "d.*/c.*.pem") << int(QSslCertificate::PatternSyntax::Wildcard) << true << 0; + QTest::newRow("\"d.*/c.*.pem\" wildcard der") << (testDataDir + "d.*/c.*.pem") << int(QSslCertificate::PatternSyntax::Wildcard) << false << 0; #ifdef Q_OS_LINUX - QTest::newRow("absolute path wildcard pem") << (testDataDir + "certificates/*.pem") << int(QSslCertificate::Wildcard) << true << 7; + QTest::newRow("absolute path wildcard pem") << (testDataDir + "certificates/*.pem") << int(QSslCertificate::PatternSyntax::Wildcard) << true << 7; #endif - QTest::newRow("trailing-whitespace") << (testDataDir + "more-certificates/trailing-whitespace.pem") << int(QSslCertificate::FixedString) << true << 1; - QTest::newRow("no-ending-newline") << (testDataDir + "more-certificates/no-ending-newline.pem") << int(QSslCertificate::FixedString) << true << 1; - QTest::newRow("malformed-just-begin") << (testDataDir + "more-certificates/malformed-just-begin.pem") << int(QSslCertificate::FixedString) << true << 0; - QTest::newRow("malformed-just-begin-no-newline") << (testDataDir + "more-certificates/malformed-just-begin-no-newline.pem") << int(QSslCertificate::FixedString) << true << 0; + QTest::newRow("trailing-whitespace") << (testDataDir + "more-certificates/trailing-whitespace.pem") << int(QSslCertificate::PatternSyntax::FixedString) << true << 1; + QTest::newRow("no-ending-newline") << (testDataDir + "more-certificates/no-ending-newline.pem") << int(QSslCertificate::PatternSyntax::FixedString) << true << 1; + QTest::newRow("malformed-just-begin") << (testDataDir + "more-certificates/malformed-just-begin.pem") << int(QSslCertificate::PatternSyntax::FixedString) << true << 0; + QTest::newRow("malformed-just-begin-no-newline") << (testDataDir + "more-certificates/malformed-just-begin-no-newline.pem") << int(QSslCertificate::PatternSyntax::FixedString) << true << 0; } void tst_QSslCertificate::fromPath_qregularexpression() @@ -795,7 +795,7 @@ void tst_QSslCertificate::certInfo() "55:ba:e7:fb:95:5d:91"; QSslCertificate cert = QSslCertificate::fromPath(testDataDir + "certificates/cert.pem", QSsl::Pem, - QSslCertificate::FixedString).first(); + QSslCertificate::PatternSyntax::FixedString).first(); QVERIFY(!cert.isNull()); QCOMPARE(cert.issuerInfo(QSslCertificate::Organization)[0], QString("CryptSoft Pty Ltd")); @@ -852,7 +852,7 @@ void tst_QSslCertificate::certInfo() void tst_QSslCertificate::certInfoQByteArray() { QSslCertificate cert = QSslCertificate::fromPath(testDataDir + "certificates/cert.pem", QSsl::Pem, - QSslCertificate::FixedString).first(); + QSslCertificate::PatternSyntax::FixedString).first(); QVERIFY(!cert.isNull()); // in this test, check the bytearray variants before the enum variants to see if @@ -904,7 +904,7 @@ void tst_QSslCertificate::nulInCN() QSKIP("Generic QSslCertificatePrivate fails this test"); #endif QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "more-certificates/badguy-nul-cn.crt", QSsl::Pem, QSslCertificate::FixedString); + QSslCertificate::fromPath(testDataDir + "more-certificates/badguy-nul-cn.crt", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QCOMPARE(certList.size(), 1); const QSslCertificate &cert = certList.at(0); @@ -923,7 +923,7 @@ void tst_QSslCertificate::nulInSan() QSKIP("Generic QSslCertificatePrivate fails this test"); #endif QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "more-certificates/badguy-nul-san.crt", QSsl::Pem, QSslCertificate::FixedString); + QSslCertificate::fromPath(testDataDir + "more-certificates/badguy-nul-san.crt", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QCOMPARE(certList.size(), 1); const QSslCertificate &cert = certList.at(0); @@ -943,7 +943,7 @@ void tst_QSslCertificate::nulInSan() void tst_QSslCertificate::largeSerialNumber() { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "more-certificates/cert-large-serial-number.pem", QSsl::Pem, QSslCertificate::FixedString); + QSslCertificate::fromPath(testDataDir + "more-certificates/cert-large-serial-number.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QCOMPARE(certList.size(), 1); @@ -955,7 +955,7 @@ void tst_QSslCertificate::largeSerialNumber() void tst_QSslCertificate::largeExpirationDate() // QTBUG-12489 { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "more-certificates/cert-large-expiration-date.pem", QSsl::Pem, QSslCertificate::FixedString); + QSslCertificate::fromPath(testDataDir + "more-certificates/cert-large-expiration-date.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QCOMPARE(certList.size(), 1); @@ -968,7 +968,7 @@ void tst_QSslCertificate::largeExpirationDate() // QTBUG-12489 void tst_QSslCertificate::blacklistedCertificates() { - QList<QSslCertificate> blacklistedCerts = QSslCertificate::fromPath(testDataDir + "more-certificates/blacklisted*.pem", QSsl::Pem, QSslCertificate::Wildcard); + QList<QSslCertificate> blacklistedCerts = QSslCertificate::fromPath(testDataDir + "more-certificates/blacklisted*.pem", QSsl::Pem, QSslCertificate::PatternSyntax::Wildcard); QVERIFY(blacklistedCerts.count() > 0); for (int a = 0; a < blacklistedCerts.count(); a++) { QVERIFY(blacklistedCerts.at(a).isBlacklisted()); @@ -977,15 +977,15 @@ void tst_QSslCertificate::blacklistedCertificates() void tst_QSslCertificate::selfsignedCertificates() { - QVERIFY(QSslCertificate::fromPath(testDataDir + "certificates/cert-ss.pem", QSsl::Pem, QSslCertificate::FixedString).first().isSelfSigned()); - QVERIFY(!QSslCertificate::fromPath(testDataDir + "certificates/cert.pem", QSsl::Pem, QSslCertificate::FixedString).first().isSelfSigned()); + QVERIFY(QSslCertificate::fromPath(testDataDir + "certificates/cert-ss.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString).first().isSelfSigned()); + QVERIFY(!QSslCertificate::fromPath(testDataDir + "certificates/cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString).first().isSelfSigned()); QVERIFY(!QSslCertificate().isSelfSigned()); } void tst_QSslCertificate::toText() { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "more-certificates/cert-large-expiration-date.pem", QSsl::Pem, QSslCertificate::FixedString); + QSslCertificate::fromPath(testDataDir + "more-certificates/cert-large-expiration-date.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QCOMPARE(certList.size(), 1); const QSslCertificate &cert = certList.at(0); @@ -1027,7 +1027,7 @@ void tst_QSslCertificate::toText() void tst_QSslCertificate::multipleCommonNames() { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "more-certificates/test-cn-two-cns-cert.pem", QSsl::Pem, QSslCertificate::FixedString); + QSslCertificate::fromPath(testDataDir + "more-certificates/test-cn-two-cns-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QVERIFY(certList.count() > 0); QStringList commonNames = certList[0].subjectInfo(QSslCertificate::CommonName); @@ -1038,14 +1038,14 @@ void tst_QSslCertificate::multipleCommonNames() void tst_QSslCertificate::subjectAndIssuerAttributes() { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "more-certificates/test-cn-with-drink-cert.pem", QSsl::Pem, QSslCertificate::FixedString); + QSslCertificate::fromPath(testDataDir + "more-certificates/test-cn-with-drink-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QVERIFY(certList.count() > 0); QList<QByteArray> attributes = certList[0].subjectInfoAttributes(); QVERIFY(attributes.contains(QByteArray("favouriteDrink"))); attributes.clear(); - certList = QSslCertificate::fromPath(testDataDir + "more-certificates/natwest-banking.pem", QSsl::Pem, QSslCertificate::FixedString); + certList = QSslCertificate::fromPath(testDataDir + "more-certificates/natwest-banking.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QVERIFY(certList.count() > 0); QByteArray shortName("1.3.6.1.4.1.311.60.2.1.3"); @@ -1080,17 +1080,17 @@ void tst_QSslCertificate::verify() errors.clear(); // Verify a valid cert signed by a CA - QList<QSslCertificate> caCerts = QSslCertificate::fromPath(testDataDir + "verify-certs/cacert.pem", QSsl::Pem, QSslCertificate::FixedString); + QList<QSslCertificate> caCerts = QSslCertificate::fromPath(testDataDir + "verify-certs/cacert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QSslSocket::addDefaultCaCertificate(caCerts.first()); - toVerify = QSslCertificate::fromPath(testDataDir + "verify-certs/test-ocsp-good-cert.pem", QSsl::Pem, QSslCertificate::FixedString); + toVerify = QSslCertificate::fromPath(testDataDir + "verify-certs/test-ocsp-good-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); errors = QSslCertificate::verify(toVerify); VERIFY_VERBOSE(errors.count() == 0); errors.clear(); // Test a blacklisted certificate - toVerify = QSslCertificate::fromPath(testDataDir + "verify-certs/test-addons-mozilla-org-cert.pem", QSsl::Pem, QSslCertificate::FixedString); + toVerify = QSslCertificate::fromPath(testDataDir + "verify-certs/test-addons-mozilla-org-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); errors = QSslCertificate::verify(toVerify); bool foundBlack = false; foreach (const QSslError &error, errors) { @@ -1103,7 +1103,7 @@ void tst_QSslCertificate::verify() errors.clear(); // This one is expired and untrusted - toVerify = QSslCertificate::fromPath(testDataDir + "more-certificates/cert-large-serial-number.pem", QSsl::Pem, QSslCertificate::FixedString); + toVerify = QSslCertificate::fromPath(testDataDir + "more-certificates/cert-large-serial-number.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); errors = QSslCertificate::verify(toVerify); VERIFY_VERBOSE(errors.contains(QSslError(QSslError::SelfSignedCertificate, toVerify[0]))); VERIFY_VERBOSE(errors.contains(QSslError(QSslError::CertificateExpired, toVerify[0]))); @@ -1111,15 +1111,15 @@ void tst_QSslCertificate::verify() toVerify.clear(); // This one is signed by a valid cert, but the signer is not a valid CA - toVerify << QSslCertificate::fromPath(testDataDir + "verify-certs/test-intermediate-not-ca-cert.pem", QSsl::Pem, QSslCertificate::FixedString).first(); - toVerify << QSslCertificate::fromPath(testDataDir + "verify-certs/test-ocsp-good-cert.pem", QSsl::Pem, QSslCertificate::FixedString).first(); + toVerify << QSslCertificate::fromPath(testDataDir + "verify-certs/test-intermediate-not-ca-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString).first(); + toVerify << QSslCertificate::fromPath(testDataDir + "verify-certs/test-ocsp-good-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString).first(); errors = QSslCertificate::verify(toVerify); VERIFY_VERBOSE(errors.contains(QSslError(QSslError::InvalidCaCertificate, toVerify[1]))); toVerify.clear(); // This one is signed by a valid cert, and the signer is a valid CA - toVerify << QSslCertificate::fromPath(testDataDir + "verify-certs/test-intermediate-is-ca-cert.pem", QSsl::Pem, QSslCertificate::FixedString).first(); - toVerify << QSslCertificate::fromPath(testDataDir + "verify-certs/test-intermediate-ca-cert.pem", QSsl::Pem, QSslCertificate::FixedString).first(); + toVerify << QSslCertificate::fromPath(testDataDir + "verify-certs/test-intermediate-is-ca-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString).first(); + toVerify << QSslCertificate::fromPath(testDataDir + "verify-certs/test-intermediate-ca-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString).first(); errors = QSslCertificate::verify(toVerify); VERIFY_VERBOSE(errors.count() == 0); @@ -1149,7 +1149,7 @@ QString tst_QSslCertificate::toString(const QList<QSslError>& errors) void tst_QSslCertificate::extensions() { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "more-certificates/natwest-banking.pem", QSsl::Pem, QSslCertificate::FixedString); + QSslCertificate::fromPath(testDataDir + "more-certificates/natwest-banking.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QVERIFY(certList.count() > 0); QSslCertificate cert = certList[0]; @@ -1247,7 +1247,7 @@ void tst_QSslCertificate::extensions() void tst_QSslCertificate::extensionsCritical() { QList<QSslCertificate> certList = - QSslCertificate::fromPath(testDataDir + "verify-certs/test-addons-mozilla-org-cert.pem", QSsl::Pem, QSslCertificate::FixedString); + QSslCertificate::fromPath(testDataDir + "verify-certs/test-addons-mozilla-org-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QVERIFY(certList.count() > 0); QSslCertificate cert = certList[0]; @@ -1368,12 +1368,12 @@ void tst_QSslCertificate::version_data() QTest::newRow("null certificate") << QSslCertificate() << QByteArray(); QList<QSslCertificate> certs; - certs << QSslCertificate::fromPath(testDataDir + "verify-certs/test-ocsp-good-cert.pem", QSsl::Pem, QSslCertificate::FixedString); + certs << QSslCertificate::fromPath(testDataDir + "verify-certs/test-ocsp-good-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QTest::newRow("v3 certificate") << certs.first() << QByteArrayLiteral("3"); certs.clear(); - certs << QSslCertificate::fromPath(testDataDir + "certificates/cert.pem", QSsl::Pem, QSslCertificate::FixedString); + certs << QSslCertificate::fromPath(testDataDir + "certificates/cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QTest::newRow("v1 certificate") << certs.first() << QByteArrayLiteral("1"); } @@ -1410,7 +1410,7 @@ void tst_QSslCertificate::pkcs12() QVERIFY(ok); f.close(); - QList<QSslCertificate> leafCert = QSslCertificate::fromPath(testDataDir + QLatin1String("pkcs12/leaf.crt"), QSsl::Pem, QSslCertificate::FixedString); + QList<QSslCertificate> leafCert = QSslCertificate::fromPath(testDataDir + QLatin1String("pkcs12/leaf.crt"), QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QVERIFY(!leafCert.isEmpty()); QCOMPARE(cert, leafCert.first()); @@ -1425,7 +1425,7 @@ void tst_QSslCertificate::pkcs12() QVERIFY(!leafKey.isNull()); QCOMPARE(key, leafKey); - QList<QSslCertificate> caCert = QSslCertificate::fromPath(testDataDir + QLatin1String("pkcs12/inter.crt"), QSsl::Pem, QSslCertificate::FixedString); + QList<QSslCertificate> caCert = QSslCertificate::fromPath(testDataDir + QLatin1String("pkcs12/inter.crt"), QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); QVERIFY(!caCert.isEmpty()); QVERIFY(!caCerts.isEmpty()); diff --git a/tests/auto/opengl/qgl/tst_qgl.cpp b/tests/auto/opengl/qgl/tst_qgl.cpp new file mode 100644 index 0000000000..d860caaa37 --- /dev/null +++ b/tests/auto/opengl/qgl/tst_qgl.cpp @@ -0,0 +1,2525 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include <qcoreapplication.h> +#include <qdebug.h> +#include <qgl.h> +#include <qglpixelbuffer.h> +#include <qglframebufferobject.h> +#include <qglcolormap.h> +#include <qpaintengine.h> +#include <qpainterpath.h> +#include <qopenglfunctions.h> +#include <qopenglframebufferobject.h> +#include <qopenglpaintdevice.h> + +#include <QGraphicsView> +#include <QGraphicsProxyWidget> +#include <QVBoxLayout> + +#ifdef QT_BUILD_INTERNAL +#include <qpa/qplatformpixmap.h> +#include <QtOpenGL/private/qgl_p.h> +#include <QtGui/private/qimage_p.h> +#include <QtGui/private/qimagepixmapcleanuphooks_p.h> +#include <QtGui/private/qopenglextensions_p.h> +#endif + +class tst_QGL : public QObject +{ +Q_OBJECT + +public: + tst_QGL(); + virtual ~tst_QGL(); + + static void initMain(); + +private slots: + void initTestCase(); + void getSetCheck(); +#ifdef QT_BUILD_INTERNAL + void qglContextDefaultBindTexture(); + void openGLVersionCheck(); + void shareRegister(); + void textureCleanup(); +#endif + void partialGLWidgetUpdates_data(); + void partialGLWidgetUpdates(); + void glWidgetWithAlpha(); + void glWidgetRendering(); + void glFBOSimpleRendering(); + void glFBORendering(); + void currentFboSync(); + void multipleFBOInterleavedRendering(); + void glFBOUseInGLWidget(); + void glPBufferRendering(); + void glWidgetReparent(); + void glWidgetRenderPixmap(); + void colormap(); + void fboFormat(); + void testDontCrashOnDanglingResources(); + void replaceClipping(); + void clipTest(); + void destroyFBOAfterContext(); + void threadImages(); + void nullRectCrash(); + void graphicsViewClipping(); + void extensions(); +}; + +tst_QGL::tst_QGL() +{ +} + +tst_QGL::~tst_QGL() +{ +} + +void tst_QGL::initMain() +{ + QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); +} + +void tst_QGL::initTestCase() +{ + QGLWidget glWidget; + if (!glWidget.isValid()) + QSKIP("QGL is not supported on the test system"); +} + +class MyGLContext : public QGLContext +{ +public: + MyGLContext(const QGLFormat& format) : QGLContext(format) {} + bool windowCreated() const { return QGLContext::windowCreated(); } + void setWindowCreated(bool on) { QGLContext::setWindowCreated(on); } + bool initialized() const { return QGLContext::initialized(); } + void setInitialized(bool on) { QGLContext::setInitialized(on); } +}; + +class MyGLWidget : public QGLWidget +{ +public: + MyGLWidget() : QGLWidget() {} + bool autoBufferSwap() const { return QGLWidget::autoBufferSwap(); } + void setAutoBufferSwap(bool on) { QGLWidget::setAutoBufferSwap(on); } +}; + +static int appDefaultDepth() +{ + static int depth = 0; + if (depth == 0) { + QPixmap pm(1, 1); + depth = pm.depth(); + } + return depth; +} + +// Using INT_MIN and INT_MAX will cause failures on systems +// where "int" is 64-bit, so use the explicit values instead. +#define TEST_INT_MIN (-2147483647 - 1) +#define TEST_INT_MAX 2147483647 + +// Testing get/set functions +void tst_QGL::getSetCheck() +{ + QGLFormat obj1; + // int QGLFormat::depthBufferSize() + // void QGLFormat::setDepthBufferSize(int) + QCOMPARE(-1, obj1.depthBufferSize()); + obj1.setDepthBufferSize(0); + QCOMPARE(0, obj1.depthBufferSize()); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setDepthBufferSize: Cannot set negative depth buffer size -2147483648"); + obj1.setDepthBufferSize(TEST_INT_MIN); + QCOMPARE(0, obj1.depthBufferSize()); // Makes no sense with a negative buffer size + obj1.setDepthBufferSize(3); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setDepthBufferSize: Cannot set negative depth buffer size -1"); + obj1.setDepthBufferSize(-1); + QCOMPARE(3, obj1.depthBufferSize()); + obj1.setDepthBufferSize(TEST_INT_MAX); + QCOMPARE(TEST_INT_MAX, obj1.depthBufferSize()); + + // int QGLFormat::accumBufferSize() + // void QGLFormat::setAccumBufferSize(int) + QCOMPARE(-1, obj1.accumBufferSize()); + obj1.setAccumBufferSize(0); + QCOMPARE(0, obj1.accumBufferSize()); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setAccumBufferSize: Cannot set negative accumulate buffer size -2147483648"); + obj1.setAccumBufferSize(TEST_INT_MIN); + QCOMPARE(0, obj1.accumBufferSize()); // Makes no sense with a negative buffer size + obj1.setAccumBufferSize(3); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setAccumBufferSize: Cannot set negative accumulate buffer size -1"); + obj1.setAccumBufferSize(-1); + QCOMPARE(3, obj1.accumBufferSize()); + obj1.setAccumBufferSize(TEST_INT_MAX); + QCOMPARE(TEST_INT_MAX, obj1.accumBufferSize()); + + // int QGLFormat::redBufferSize() + // void QGLFormat::setRedBufferSize(int) + QCOMPARE(-1, obj1.redBufferSize()); + obj1.setRedBufferSize(0); + QCOMPARE(0, obj1.redBufferSize()); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setRedBufferSize: Cannot set negative red buffer size -2147483648"); + obj1.setRedBufferSize(TEST_INT_MIN); + QCOMPARE(0, obj1.redBufferSize()); // Makes no sense with a negative buffer size + obj1.setRedBufferSize(3); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setRedBufferSize: Cannot set negative red buffer size -1"); + obj1.setRedBufferSize(-1); + QCOMPARE(3, obj1.redBufferSize()); + obj1.setRedBufferSize(TEST_INT_MAX); + QCOMPARE(TEST_INT_MAX, obj1.redBufferSize()); + + // int QGLFormat::greenBufferSize() + // void QGLFormat::setGreenBufferSize(int) + QCOMPARE(-1, obj1.greenBufferSize()); + obj1.setGreenBufferSize(0); + QCOMPARE(0, obj1.greenBufferSize()); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setGreenBufferSize: Cannot set negative green buffer size -2147483648"); + obj1.setGreenBufferSize(TEST_INT_MIN); + QCOMPARE(0, obj1.greenBufferSize()); // Makes no sense with a negative buffer size + obj1.setGreenBufferSize(3); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setGreenBufferSize: Cannot set negative green buffer size -1"); + obj1.setGreenBufferSize(-1); + QCOMPARE(3, obj1.greenBufferSize()); + obj1.setGreenBufferSize(TEST_INT_MAX); + QCOMPARE(TEST_INT_MAX, obj1.greenBufferSize()); + + // int QGLFormat::blueBufferSize() + // void QGLFormat::setBlueBufferSize(int) + QCOMPARE(-1, obj1.blueBufferSize()); + obj1.setBlueBufferSize(0); + QCOMPARE(0, obj1.blueBufferSize()); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setBlueBufferSize: Cannot set negative blue buffer size -2147483648"); + obj1.setBlueBufferSize(TEST_INT_MIN); + QCOMPARE(0, obj1.blueBufferSize()); // Makes no sense with a negative buffer size + obj1.setBlueBufferSize(3); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setBlueBufferSize: Cannot set negative blue buffer size -1"); + obj1.setBlueBufferSize(-1); + QCOMPARE(3, obj1.blueBufferSize()); + obj1.setBlueBufferSize(TEST_INT_MAX); + QCOMPARE(TEST_INT_MAX, obj1.blueBufferSize()); + + // int QGLFormat::alphaBufferSize() + // void QGLFormat::setAlphaBufferSize(int) + QCOMPARE(-1, obj1.alphaBufferSize()); + QCOMPARE(false, obj1.alpha()); + QVERIFY(!obj1.testOption(QGL::AlphaChannel)); + QVERIFY(obj1.testOption(QGL::NoAlphaChannel)); + obj1.setAlphaBufferSize(1); + QCOMPARE(true, obj1.alpha()); // setAlphaBufferSize() enables alpha. + QCOMPARE(1, obj1.alphaBufferSize()); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setAlphaBufferSize: Cannot set negative alpha buffer size -2147483648"); + obj1.setAlphaBufferSize(TEST_INT_MIN); + QCOMPARE(1, obj1.alphaBufferSize()); // Makes no sense with a negative buffer size + obj1.setAlphaBufferSize(3); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setAlphaBufferSize: Cannot set negative alpha buffer size -1"); + obj1.setAlphaBufferSize(-1); + QCOMPARE(3, obj1.alphaBufferSize()); + obj1.setAlphaBufferSize(TEST_INT_MAX); + QCOMPARE(TEST_INT_MAX, obj1.alphaBufferSize()); + + // int QGLFormat::stencilBufferSize() + // void QGLFormat::setStencilBufferSize(int) + QCOMPARE(-1, obj1.stencilBufferSize()); + obj1.setStencilBufferSize(1); + QCOMPARE(1, obj1.stencilBufferSize()); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setStencilBufferSize: Cannot set negative stencil buffer size -2147483648"); + obj1.setStencilBufferSize(TEST_INT_MIN); + QCOMPARE(1, obj1.stencilBufferSize()); // Makes no sense with a negative buffer size + obj1.setStencilBufferSize(3); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setStencilBufferSize: Cannot set negative stencil buffer size -1"); + obj1.setStencilBufferSize(-1); + QCOMPARE(3, obj1.stencilBufferSize()); + obj1.setStencilBufferSize(TEST_INT_MAX); + QCOMPARE(TEST_INT_MAX, obj1.stencilBufferSize()); + + // bool QGLFormat::sampleBuffers() + // void QGLFormat::setSampleBuffers(bool) + QCOMPARE(false, obj1.sampleBuffers()); + QVERIFY(!obj1.testOption(QGL::SampleBuffers)); + QVERIFY(obj1.testOption(QGL::NoSampleBuffers)); + + obj1.setSampleBuffers(false); + QCOMPARE(false, obj1.sampleBuffers()); + QVERIFY(obj1.testOption(QGL::NoSampleBuffers)); + obj1.setSampleBuffers(true); + QCOMPARE(true, obj1.sampleBuffers()); + QVERIFY(obj1.testOption(QGL::SampleBuffers)); + + // int QGLFormat::samples() + // void QGLFormat::setSamples(int) + QCOMPARE(-1, obj1.samples()); + obj1.setSamples(0); + QCOMPARE(0, obj1.samples()); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setSamples: Cannot have negative number of samples per pixel -2147483648"); + obj1.setSamples(TEST_INT_MIN); + QCOMPARE(0, obj1.samples()); // Makes no sense with a negative sample size + obj1.setSamples(3); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setSamples: Cannot have negative number of samples per pixel -1"); + obj1.setSamples(-1); + QCOMPARE(3, obj1.samples()); + obj1.setSamples(TEST_INT_MAX); + QCOMPARE(TEST_INT_MAX, obj1.samples()); + + // int QGLFormat::swapInterval() + // void QGLFormat::setSwapInterval(int) + QCOMPARE(-1, obj1.swapInterval()); + obj1.setSwapInterval(0); + QCOMPARE(0, obj1.swapInterval()); + obj1.setSwapInterval(TEST_INT_MIN); + QCOMPARE(TEST_INT_MIN, obj1.swapInterval()); + obj1.setSwapInterval(-1); + QCOMPARE(-1, obj1.swapInterval()); + obj1.setSwapInterval(TEST_INT_MAX); + QCOMPARE(TEST_INT_MAX, obj1.swapInterval()); + + // bool QGLFormat::doubleBuffer() + // void QGLFormat::setDoubleBuffer(bool) + QCOMPARE(true, obj1.doubleBuffer()); + QVERIFY(obj1.testOption(QGL::DoubleBuffer)); + QVERIFY(!obj1.testOption(QGL::SingleBuffer)); + obj1.setDoubleBuffer(false); + QCOMPARE(false, obj1.doubleBuffer()); + QVERIFY(!obj1.testOption(QGL::DoubleBuffer)); + QVERIFY(obj1.testOption(QGL::SingleBuffer)); + obj1.setDoubleBuffer(true); + QCOMPARE(true, obj1.doubleBuffer()); + QVERIFY(obj1.testOption(QGL::DoubleBuffer)); + QVERIFY(!obj1.testOption(QGL::SingleBuffer)); + + // bool QGLFormat::depth() + // void QGLFormat::setDepth(bool) + QCOMPARE(true, obj1.depth()); + QVERIFY(obj1.testOption(QGL::DepthBuffer)); + QVERIFY(!obj1.testOption(QGL::NoDepthBuffer)); + obj1.setDepth(false); + QCOMPARE(false, obj1.depth()); + QVERIFY(!obj1.testOption(QGL::DepthBuffer)); + QVERIFY(obj1.testOption(QGL::NoDepthBuffer)); + obj1.setDepth(true); + QCOMPARE(true, obj1.depth()); + QVERIFY(obj1.testOption(QGL::DepthBuffer)); + QVERIFY(!obj1.testOption(QGL::NoDepthBuffer)); + + // bool QGLFormat::rgba() + // void QGLFormat::setRgba(bool) + QCOMPARE(true, obj1.rgba()); + QVERIFY(obj1.testOption(QGL::Rgba)); + QVERIFY(!obj1.testOption(QGL::ColorIndex)); + obj1.setRgba(false); + QCOMPARE(false, obj1.rgba()); + QVERIFY(!obj1.testOption(QGL::Rgba)); + QVERIFY(obj1.testOption(QGL::ColorIndex)); + obj1.setRgba(true); + QCOMPARE(true, obj1.rgba()); + QVERIFY(obj1.testOption(QGL::Rgba)); + QVERIFY(!obj1.testOption(QGL::ColorIndex)); + + // bool QGLFormat::alpha() + // void QGLFormat::setAlpha(bool) + QVERIFY(obj1.testOption(QGL::AlphaChannel)); + QVERIFY(!obj1.testOption(QGL::NoAlphaChannel)); + obj1.setAlpha(false); + QCOMPARE(false, obj1.alpha()); + QVERIFY(!obj1.testOption(QGL::AlphaChannel)); + QVERIFY(obj1.testOption(QGL::NoAlphaChannel)); + obj1.setAlpha(true); + QCOMPARE(true, obj1.alpha()); + QVERIFY(obj1.testOption(QGL::AlphaChannel)); + QVERIFY(!obj1.testOption(QGL::NoAlphaChannel)); + + // bool QGLFormat::accum() + // void QGLFormat::setAccum(bool) + obj1.setAccumBufferSize(0); + QCOMPARE(false, obj1.accum()); + QVERIFY(!obj1.testOption(QGL::AccumBuffer)); + QVERIFY(obj1.testOption(QGL::NoAccumBuffer)); + obj1.setAccum(false); + QCOMPARE(false, obj1.accum()); + QVERIFY(!obj1.testOption(QGL::AccumBuffer)); + QVERIFY(obj1.testOption(QGL::NoAccumBuffer)); + obj1.setAccum(true); + QCOMPARE(true, obj1.accum()); + QVERIFY(obj1.testOption(QGL::AccumBuffer)); + QVERIFY(!obj1.testOption(QGL::NoAccumBuffer)); + + // bool QGLFormat::stencil() + // void QGLFormat::setStencil(bool) + QCOMPARE(true, obj1.stencil()); + QVERIFY(obj1.testOption(QGL::StencilBuffer)); + QVERIFY(!obj1.testOption(QGL::NoStencilBuffer)); + obj1.setStencil(false); + QCOMPARE(false, obj1.stencil()); + QVERIFY(!obj1.testOption(QGL::StencilBuffer)); + QVERIFY(obj1.testOption(QGL::NoStencilBuffer)); + obj1.setStencil(true); + QCOMPARE(true, obj1.stencil()); + QVERIFY(obj1.testOption(QGL::StencilBuffer)); + QVERIFY(!obj1.testOption(QGL::NoStencilBuffer)); + + // bool QGLFormat::stereo() + // void QGLFormat::setStereo(bool) + QCOMPARE(false, obj1.stereo()); + QVERIFY(!obj1.testOption(QGL::StereoBuffers)); + QVERIFY(obj1.testOption(QGL::NoStereoBuffers)); + obj1.setStereo(false); + QCOMPARE(false, obj1.stereo()); + QVERIFY(!obj1.testOption(QGL::StereoBuffers)); + QVERIFY(obj1.testOption(QGL::NoStereoBuffers)); + obj1.setStereo(true); + QCOMPARE(true, obj1.stereo()); + QVERIFY(obj1.testOption(QGL::StereoBuffers)); + QVERIFY(!obj1.testOption(QGL::NoStereoBuffers)); + + // bool QGLFormat::directRendering() + // void QGLFormat::setDirectRendering(bool) + QCOMPARE(true, obj1.directRendering()); + QVERIFY(obj1.testOption(QGL::DirectRendering)); + QVERIFY(!obj1.testOption(QGL::IndirectRendering)); + obj1.setDirectRendering(false); + QCOMPARE(false, obj1.directRendering()); + QVERIFY(!obj1.testOption(QGL::DirectRendering)); + QVERIFY(obj1.testOption(QGL::IndirectRendering)); + obj1.setDirectRendering(true); + QCOMPARE(true, obj1.directRendering()); + QVERIFY(obj1.testOption(QGL::DirectRendering)); + QVERIFY(!obj1.testOption(QGL::IndirectRendering)); + + // bool QGLFormat::overlay() + // void QGLFormat::setOverlay(bool) + QCOMPARE(false, obj1.hasOverlay()); + QVERIFY(!obj1.testOption(QGL::HasOverlay)); + QVERIFY(obj1.testOption(QGL::NoOverlay)); + obj1.setOverlay(false); + QCOMPARE(false, obj1.hasOverlay()); + QVERIFY(!obj1.testOption(QGL::HasOverlay)); + QVERIFY(obj1.testOption(QGL::NoOverlay)); + obj1.setOverlay(true); + QCOMPARE(true, obj1.hasOverlay()); + QVERIFY(obj1.testOption(QGL::HasOverlay)); + QVERIFY(!obj1.testOption(QGL::NoOverlay)); + + // int QGLFormat::plane() + // void QGLFormat::setPlane(int) + QCOMPARE(0, obj1.plane()); + obj1.setPlane(0); + QCOMPARE(0, obj1.plane()); + obj1.setPlane(TEST_INT_MIN); + QCOMPARE(TEST_INT_MIN, obj1.plane()); + obj1.setPlane(TEST_INT_MAX); + QCOMPARE(TEST_INT_MAX, obj1.plane()); + + // int QGLFormat::major/minorVersion() + // void QGLFormat::setVersion(int, int) + QCOMPARE(obj1.majorVersion(), 2); + QCOMPARE(obj1.minorVersion(), 0); + obj1.setVersion(3, 2); + QCOMPARE(obj1.majorVersion(), 3); + QCOMPARE(obj1.minorVersion(), 2); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setVersion: Cannot set zero or negative version number 0.1"); + obj1.setVersion(0, 1); + QCOMPARE(obj1.majorVersion(), 3); + QCOMPARE(obj1.minorVersion(), 2); + QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setVersion: Cannot set zero or negative version number 3.-1"); + obj1.setVersion(3, -1); + QCOMPARE(obj1.majorVersion(), 3); + QCOMPARE(obj1.minorVersion(), 2); + obj1.setVersion(TEST_INT_MAX, TEST_INT_MAX - 1); + QCOMPARE(obj1.majorVersion(), TEST_INT_MAX); + QCOMPARE(obj1.minorVersion(), TEST_INT_MAX - 1); + + + // operator== and operator!= for QGLFormat + QGLFormat format1; + QGLFormat format2; + + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + format1.setDoubleBuffer(false); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setDoubleBuffer(false); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + format1.setDepthBufferSize(8); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setDepthBufferSize(8); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + format1.setAccumBufferSize(8); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setAccumBufferSize(8); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + format1.setRedBufferSize(8); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setRedBufferSize(8); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + format1.setGreenBufferSize(8); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setGreenBufferSize(8); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + format1.setBlueBufferSize(8); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setBlueBufferSize(8); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + format1.setAlphaBufferSize(8); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setAlphaBufferSize(8); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + format1.setStencilBufferSize(8); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setStencilBufferSize(8); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + format1.setSamples(8); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setSamples(8); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + format1.setSwapInterval(8); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setSwapInterval(8); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + format1.setPlane(8); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setPlane(8); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + format1.setVersion(3, 2); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setVersion(3, 2); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + format1.setProfile(QGLFormat::CoreProfile); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setProfile(QGLFormat::CoreProfile); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + format1.setOption(QGL::NoDeprecatedFunctions); + QVERIFY(!(format1 == format2)); + QVERIFY(format1 != format2); + format2.setOption(QGL::NoDeprecatedFunctions); + QCOMPARE(format1, format2); + QVERIFY(!(format1 != format2)); + + // Copy constructor and assignment for QGLFormat. + QGLFormat format3(format1); + QGLFormat format4; + QCOMPARE(format1, format3); + QVERIFY(format1 != format4); + format4 = format1; + QCOMPARE(format1, format4); + + // Check that modifying a copy doesn't affect the original. + format3.setRedBufferSize(16); + format4.setPlane(16); + QCOMPARE(format1.redBufferSize(), 8); + QCOMPARE(format1.plane(), 8); + + // Check the QGLFormat constructor that takes an option list. + QGLFormat format5 + (QGL::DepthBuffer | QGL::StereoBuffers | QGL::ColorIndex, 3); + QVERIFY(format5.depth()); + QVERIFY(format5.stereo()); + QVERIFY(format5.doubleBuffer()); // From defaultFormat() + QVERIFY(!format5.hasOverlay()); // From defaultFormat() + QVERIFY(!format5.rgba()); + QCOMPARE(format5.plane(), 3); + + // The default format should be the same as QGLFormat(). + QCOMPARE(QGLFormat::defaultFormat(), QGLFormat()); + + // Modify the default format and check that it was changed. + QGLFormat::setDefaultFormat(format1); + QCOMPARE(QGLFormat::defaultFormat(), format1); + + // Restore the default format. + QGLFormat::setDefaultFormat(QGLFormat()); + QCOMPARE(QGLFormat::defaultFormat(), QGLFormat()); + + // Check the default overlay format's expected values. + QGLFormat overlay(QGLFormat::defaultOverlayFormat()); + QCOMPARE(overlay.depthBufferSize(), -1); + QCOMPARE(overlay.accumBufferSize(), -1); + QCOMPARE(overlay.redBufferSize(), -1); + QCOMPARE(overlay.greenBufferSize(), -1); + QCOMPARE(overlay.blueBufferSize(), -1); + QCOMPARE(overlay.alphaBufferSize(), -1); + QCOMPARE(overlay.samples(), -1); + QCOMPARE(overlay.swapInterval(), -1); + QCOMPARE(overlay.plane(), 1); + QVERIFY(!overlay.sampleBuffers()); + QVERIFY(!overlay.doubleBuffer()); + QVERIFY(!overlay.depth()); + QVERIFY(!overlay.rgba()); + QVERIFY(!overlay.alpha()); + QVERIFY(!overlay.accum()); + QVERIFY(!overlay.stencil()); + QVERIFY(!overlay.stereo()); + QVERIFY(overlay.directRendering()); // Only option that should be on. + QVERIFY(!overlay.hasOverlay()); // Overlay doesn't need an overlay! + + // Modify the default overlay format and check that it was changed. + QGLFormat::setDefaultOverlayFormat(format1); + QCOMPARE(QGLFormat::defaultOverlayFormat(), format1); + + // Restore the default overlay format. + QGLFormat::setDefaultOverlayFormat(overlay); + QCOMPARE(QGLFormat::defaultOverlayFormat(), overlay); + + MyGLContext obj2(obj1); + // bool QGLContext::windowCreated() + // void QGLContext::setWindowCreated(bool) + obj2.setWindowCreated(false); + QCOMPARE(false, obj2.windowCreated()); + obj2.setWindowCreated(true); + QCOMPARE(true, obj2.windowCreated()); + + // bool QGLContext::initialized() + // void QGLContext::setInitialized(bool) + obj2.setInitialized(false); + QCOMPARE(false, obj2.initialized()); + obj2.setInitialized(true); + QCOMPARE(true, obj2.initialized()); + + MyGLWidget obj3; + // bool QGLWidget::autoBufferSwap() + // void QGLWidget::setAutoBufferSwap(bool) + obj3.setAutoBufferSwap(false); + QCOMPARE(false, obj3.autoBufferSwap()); + obj3.setAutoBufferSwap(true); + QCOMPARE(true, obj3.autoBufferSwap()); +} + +#ifdef QT_BUILD_INTERNAL +QT_BEGIN_NAMESPACE +extern QGLFormat::OpenGLVersionFlags qOpenGLVersionFlagsFromString(const QString &versionString); +QT_END_NAMESPACE +#endif + +#ifdef QT_BUILD_INTERNAL +void tst_QGL::openGLVersionCheck() +{ + QString versionString; + QGLFormat::OpenGLVersionFlags expectedFlag; + QGLFormat::OpenGLVersionFlags versionFlag; + + versionString = "1.1 Irix 6.5"; + expectedFlag = QGLFormat::OpenGL_Version_1_1; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "1.2 Microsoft"; + expectedFlag = QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "1.2.1"; + expectedFlag = QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "1.3 NVIDIA"; + expectedFlag = QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "1.4"; + expectedFlag = QGLFormat::OpenGL_Version_1_4 | QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "1.5 NVIDIA"; + expectedFlag = QGLFormat::OpenGL_Version_1_5 | QGLFormat::OpenGL_Version_1_4 | QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "2.0.2 NVIDIA 87.62"; + expectedFlag = QGLFormat::OpenGL_Version_2_0 | QGLFormat::OpenGL_Version_1_5 | QGLFormat::OpenGL_Version_1_4 | QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "2.1 NVIDIA"; + expectedFlag = QGLFormat::OpenGL_Version_2_1 | QGLFormat::OpenGL_Version_2_0 | QGLFormat::OpenGL_Version_1_5 | QGLFormat::OpenGL_Version_1_4 | QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "2.1"; + expectedFlag = QGLFormat::OpenGL_Version_2_1 | QGLFormat::OpenGL_Version_2_0 | QGLFormat::OpenGL_Version_1_5 | QGLFormat::OpenGL_Version_1_4 | QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "OpenGL ES-CM 1.0 ATI"; + expectedFlag = QGLFormat::OpenGL_ES_Common_Version_1_0 | QGLFormat::OpenGL_ES_CommonLite_Version_1_0; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "OpenGL ES-CL 1.0 ATI"; + expectedFlag = QGLFormat::OpenGL_ES_CommonLite_Version_1_0; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "OpenGL ES-CM 1.1 ATI"; + expectedFlag = QGLFormat::OpenGL_ES_Common_Version_1_1 | QGLFormat::OpenGL_ES_CommonLite_Version_1_1 | QGLFormat::OpenGL_ES_Common_Version_1_0 | QGLFormat::OpenGL_ES_CommonLite_Version_1_0; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "OpenGL ES-CL 1.1 ATI"; + expectedFlag = QGLFormat::OpenGL_ES_CommonLite_Version_1_1 | QGLFormat::OpenGL_ES_CommonLite_Version_1_0; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "OpenGL ES 2.0 ATI"; + expectedFlag = QGLFormat::OpenGL_ES_Version_2_0; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + versionString = "3.0"; + expectedFlag = QGLFormat::OpenGL_Version_3_0 | QGLFormat::OpenGL_Version_2_1 | QGLFormat::OpenGL_Version_2_0 | QGLFormat::OpenGL_Version_1_5 | QGLFormat::OpenGL_Version_1_4 | QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; + versionFlag = qOpenGLVersionFlagsFromString(versionString); + QCOMPARE(versionFlag, expectedFlag); + + QGLWidget glWidget; + glWidget.show(); + glWidget.makeCurrent(); + + // This is unfortunately the only test we can make on the actual openGLVersionFlags() + // However, the complicated parts are in openGLVersionFlags(const QString &versionString) + // tested above + +#if defined(QT_OPENGL_ES_2) + QVERIFY(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0); +#else + if (QOpenGLContext::currentContext()->isOpenGLES()) + QVERIFY(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0); + else + QVERIFY(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_1); +#endif //defined(QT_OPENGL_ES_2) +} +#endif //QT_BUILD_INTERNAL + +static bool fuzzyComparePixels(const QRgb testPixel, const QRgb refPixel, const char* file, int line, int x = -1, int y = -1) +{ + static int maxFuzz = 1; + static bool maxFuzzSet = false; + + // On 16 bpp systems, we need to allow for more fuzz: + if (!maxFuzzSet) { + maxFuzzSet = true; + if (appDefaultDepth() < 24) + maxFuzz = 32; + } + + int redFuzz = qAbs(qRed(testPixel) - qRed(refPixel)); + int greenFuzz = qAbs(qGreen(testPixel) - qGreen(refPixel)); + int blueFuzz = qAbs(qBlue(testPixel) - qBlue(refPixel)); + int alphaFuzz = qAbs(qAlpha(testPixel) - qAlpha(refPixel)); + + if (refPixel != 0 && testPixel == 0) { + QString msg; + if (x >= 0) { + msg = QString("Test pixel [%1, %2] is null (black) when it should be (%3,%4,%5,%6)") + .arg(x).arg(y) + .arg(qRed(refPixel)).arg(qGreen(refPixel)).arg(qBlue(refPixel)).arg(qAlpha(refPixel)); + } else { + msg = QString("Test pixel is null (black) when it should be (%2,%3,%4,%5)") + .arg(qRed(refPixel)).arg(qGreen(refPixel)).arg(qBlue(refPixel)).arg(qAlpha(refPixel)); + } + + QTest::qFail(msg.toLatin1(), file, line); + return false; + } + + if (redFuzz > maxFuzz || greenFuzz > maxFuzz || blueFuzz > maxFuzz || alphaFuzz > maxFuzz) { + QString msg; + + if (x >= 0) + msg = QString("Pixel [%1,%2]: ").arg(x).arg(y); + else + msg = QString("Pixel "); + + msg += QString("Max fuzz (%1) exceeded: (%2,%3,%4,%5) vs (%6,%7,%8,%9)") + .arg(maxFuzz) + .arg(qRed(testPixel)).arg(qGreen(testPixel)).arg(qBlue(testPixel)).arg(qAlpha(testPixel)) + .arg(qRed(refPixel)).arg(qGreen(refPixel)).arg(qBlue(refPixel)).arg(qAlpha(refPixel)); + QTest::qFail(msg.toLatin1(), file, line); + return false; + } + return true; +} + +static void fuzzyCompareImages(const QImage &testImage, const QImage &referenceImage, const char* file, int line) +{ + QCOMPARE(testImage.width(), referenceImage.width()); + QCOMPARE(testImage.height(), referenceImage.height()); + + for (int y = 0; y < testImage.height(); y++) { + for (int x = 0; x < testImage.width(); x++) { + if (!fuzzyComparePixels(testImage.pixel(x, y), referenceImage.pixel(x, y), file, line, x, y)) { + // Might as well save the images for easier debugging: + referenceImage.save("referenceImage.png"); + testImage.save("testImage.png"); + return; + } + } + } +} + +#define QFUZZY_COMPARE_IMAGES(A,B) \ + fuzzyCompareImages(A, B, __FILE__, __LINE__) + +#define QFUZZY_COMPARE_PIXELS(A,B) \ + fuzzyComparePixels(A, B, __FILE__, __LINE__) + +class UnclippedWidget : public QWidget +{ +public: + bool painted; + + UnclippedWidget() + : painted(false) + { + } + + void paintEvent(QPaintEvent *) + { + QPainter p(this); + p.fillRect(rect().adjusted(-1000, -1000, 1000, 1000), Qt::black); + + painted = true; + } +}; + +void tst_QGL::graphicsViewClipping() +{ + const int size = 64; + UnclippedWidget *widget = new UnclippedWidget; + widget->setFixedSize(size, size); + + QGraphicsScene scene; + + scene.addWidget(widget)->setPos(0, 0); + + QGraphicsView view(&scene); + // Use Qt::Tool as fully decorated windows have a minimum width of 160 on Windows. + view.setWindowFlags(view.windowFlags() | Qt::Tool); + view.setBackgroundBrush(Qt::white); + view.resize(2*size, 2*size); + + QGLWidget *viewport = new QGLWidget; + view.setViewport(viewport); + view.show(); + qApp->setActiveWindow(&view); + + if (!viewport->isValid()) + return; + + scene.setSceneRect(view.viewport()->rect()); + + QVERIFY(QTest::qWaitForWindowExposed(view.viewport()->windowHandle())); + #ifdef Q_OS_MAC + // The black rectangle jumps from the center to the upper left for some reason. + QTest::qWait(100); + #endif + + QTRY_VERIFY(widget->painted); + + QImage image = viewport->grabFrameBuffer(); + QImage expected = image; + + QPainter p(&expected); + p.fillRect(expected.rect(), Qt::white); + p.fillRect(QRect(0, 0, size, size), Qt::black); + p.end(); + + QFUZZY_COMPARE_IMAGES(image, expected); +} + +void tst_QGL::partialGLWidgetUpdates_data() +{ + QTest::addColumn<bool>("doubleBufferedContext"); + QTest::addColumn<bool>("autoFillBackground"); + QTest::addColumn<bool>("supportsPartialUpdates"); + + QTest::newRow("Double buffered context") << true << true << false; + QTest::newRow("Double buffered context without auto-fill background") << true << false << false; + QTest::newRow("Single buffered context") << false << true << false; + QTest::newRow("Single buffered context without auto-fill background") << false << false << true; +} + +void tst_QGL::partialGLWidgetUpdates() +{ + QFETCH(bool, doubleBufferedContext); + QFETCH(bool, autoFillBackground); + QFETCH(bool, supportsPartialUpdates); + + class MyGLWidget : public QGLWidget + { + public: + QRegion paintEventRegion; + void paintEvent(QPaintEvent *e) + { + paintEventRegion = e->region(); + } + }; + + QGLFormat format = QGLFormat::defaultFormat(); + format.setDoubleBuffer(doubleBufferedContext); + QGLFormat::setDefaultFormat(format); + + MyGLWidget widget; + widget.setFixedSize(150, 150); + widget.setAutoFillBackground(autoFillBackground); + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + QCoreApplication::processEvents(); // Process all queued paint events + + if (widget.format().doubleBuffer() != doubleBufferedContext) + QSKIP("Platform does not support requested format"); + + widget.paintEventRegion = QRegion(); + widget.repaint(50, 50, 50, 50); + + if (supportsPartialUpdates) + QCOMPARE(widget.paintEventRegion, QRegion(50, 50, 50, 50)); + else + QCOMPARE(widget.paintEventRegion, QRegion(widget.rect())); +} + + +// This tests that rendering to a QGLPBuffer using QPainter works. +void tst_QGL::glPBufferRendering() +{ + if (!QGLPixelBuffer::hasOpenGLPbuffers()) + QSKIP("QGLPixelBuffer not supported on this platform"); + + QGLPixelBuffer* pbuf = new QGLPixelBuffer(128, 128); + + QPainter p; + bool begun = p.begin(pbuf); + QVERIFY(begun); + + QPaintEngine::Type engineType = p.paintEngine()->type(); + QVERIFY(engineType == QPaintEngine::OpenGL || engineType == QPaintEngine::OpenGL2); + + p.fillRect(0, 0, 128, 128, Qt::red); + p.fillRect(32, 32, 64, 64, Qt::blue); + p.end(); + + QImage fb = pbuf->toImage(); + delete pbuf; + + QImage reference(128, 128, fb.format()); + p.begin(&reference); + p.fillRect(0, 0, 128, 128, Qt::red); + p.fillRect(32, 32, 64, 64, Qt::blue); + p.end(); + + QFUZZY_COMPARE_IMAGES(fb, reference); +} + +void tst_QGL::glWidgetWithAlpha() +{ + QGLWidget* w = new QGLWidget(QGLFormat(QGL::AlphaChannel)); + w->show(); + QVERIFY(QTest::qWaitForWindowExposed(w)); + + delete w; +} + + +void qt_opengl_draw_test_pattern(QPainter* painter, int width, int height) +{ + QPainterPath intersectingPath; + intersectingPath.moveTo(0, 0); + intersectingPath.lineTo(100, 0); + intersectingPath.lineTo(0, 100); + intersectingPath.lineTo(100, 100); + intersectingPath.closeSubpath(); + + QPainterPath trianglePath; + trianglePath.moveTo(50, 0); + trianglePath.lineTo(100, 100); + trianglePath.lineTo(0, 100); + trianglePath.closeSubpath(); + + painter->setTransform(QTransform()); // reset xform + painter->fillRect(-1, -1, width+2, height+2, Qt::red); // Background + painter->translate(14, 14); + painter->fillPath(intersectingPath, Qt::blue); // Test stencil buffer works + painter->translate(128, 0); + painter->setClipPath(trianglePath); // Test depth buffer works + painter->setTransform(QTransform()); // reset xform ready for fill + painter->fillRect(-1, -1, width+2, height+2, Qt::green); +} + +void qt_opengl_check_test_pattern(const QImage& img) +{ + // As we're doing more than trivial painting, we can't just compare to + // an image rendered with raster. Instead, we sample at well-defined + // test-points: + QFUZZY_COMPARE_PIXELS(img.pixel(39, 64), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(img.pixel(89, 64), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(img.pixel(64, 39), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(img.pixel(64, 89), QColor(Qt::blue).rgb()); + + QFUZZY_COMPARE_PIXELS(img.pixel(167, 39), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(img.pixel(217, 39), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(img.pixel(192, 64), QColor(Qt::green).rgb()); +} + +class GLWidget : public QGLWidget +{ +public: + GLWidget(QWidget* p = 0) + : QGLWidget(p), beginOk(false), engineType(QPaintEngine::MaxUser) {} + bool beginOk; + QPaintEngine::Type engineType; + void paintGL() + { + QPainter p; + beginOk = p.begin(this); + QPaintEngine* pe = p.paintEngine(); + engineType = pe->type(); + + qt_opengl_draw_test_pattern(&p, width(), height()); + + // No p.end() or swap buffers, should be done automatically + } + +}; + +void tst_QGL::glWidgetRendering() +{ + GLWidget w; + w.resize(256, 128); + w.show(); + + QVERIFY(QTest::qWaitForWindowExposed(&w)); + + QVERIFY(w.beginOk); + QVERIFY(w.engineType == QPaintEngine::OpenGL || w.engineType == QPaintEngine::OpenGL2); + +#if defined(Q_OS_QNX) + // glReadPixels reads from the back buffer. On QNX the buffer is not preserved + // after a buffer swap. This is why we have to swap the buffer explicitly before calling + // grabFrameBuffer to retrieve the content of the front buffer. + w.swapBuffers(); +#endif + QImage fb = w.grabFrameBuffer(false); + qt_opengl_check_test_pattern(fb); +} + +void tst_QGL::glFBOSimpleRendering() +{ + if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) + QSKIP("QGLFramebufferObject not supported on this platform"); + + QGLWidget glw; + glw.makeCurrent(); + + // No multisample with combined depth/stencil attachment: + QGLFramebufferObjectFormat fboFormat; + fboFormat.setAttachment(QGLFramebufferObject::NoAttachment); + + QGLFramebufferObject *fbo = new QGLFramebufferObject(200, 100, fboFormat); + + fbo->bind(); + + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + funcs->glClearColor(1.0, 0.0, 0.0, 1.0); + funcs->glClear(GL_COLOR_BUFFER_BIT); + funcs->glFinish(); + + QImage fb = fbo->toImage().convertToFormat(QImage::Format_RGB32); + QImage reference(fb.size(), QImage::Format_RGB32); + reference.fill(0xffff0000); + + QFUZZY_COMPARE_IMAGES(fb, reference); + + delete fbo; +} + +// NOTE: This tests that CombinedDepthStencil attachment works by assuming the +// GL2 engine is being used and is implemented the same way as it was when +// this autotest was written. If this is not the case, there may be some +// false-positives: I.e. The test passes when either the depth or stencil +// buffer is actually missing. But that's probably ok anyway. +void tst_QGL::glFBORendering() +{ +#if defined(Q_OS_QNX) + QSKIP("Reading the QGLFramebufferObject is unsupported on this platform"); +#endif + if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) + QSKIP("QGLFramebufferObject not supported on this platform"); + + QGLWidget glw; + glw.makeCurrent(); + + // No multisample with combined depth/stencil attachment: + QGLFramebufferObjectFormat fboFormat; + fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + + // Don't complicate things by using NPOT: + QGLFramebufferObject *fbo = new QGLFramebufferObject(256, 128, fboFormat); + + if (fbo->attachment() != QGLFramebufferObject::CombinedDepthStencil) { + delete fbo; + QSKIP("FBOs missing combined depth~stencil support"); + } + + QPainter fboPainter; + bool painterBegun = fboPainter.begin(fbo); + QVERIFY(painterBegun); + + qt_opengl_draw_test_pattern(&fboPainter, fbo->width(), fbo->height()); + + fboPainter.end(); + + QImage fb = fbo->toImage().convertToFormat(QImage::Format_RGB32); + delete fbo; + + qt_opengl_check_test_pattern(fb); +} + +class QOpenGLFramebufferObjectPaintDevice : public QOpenGLPaintDevice +{ +public: + QOpenGLFramebufferObjectPaintDevice(int width, int height) + : QOpenGLPaintDevice(width, height) + , m_fbo(width, height, QOpenGLFramebufferObject::CombinedDepthStencil) + { + } + + void ensureActiveTarget() + { + m_fbo.bind(); + } + + QImage toImage() const + { + return m_fbo.toImage(); + } + +private: + QOpenGLFramebufferObject m_fbo; +}; + +void tst_QGL::currentFboSync() +{ + if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) + QSKIP("QGLFramebufferObject not supported on this platform"); + +#if defined(Q_OS_QNX) + QSKIP("Reading the QGLFramebufferObject is unsupported on this platform"); +#endif + + QGLWidget glw; + glw.makeCurrent(); + + // For some reason we offer inter-operatibility between QGL and QOpenGL + // paint engines. (?!) Let's check if the two engines can be used to perform + // drawing in turns on different targets within the same context. + + { + QGLFramebufferObject fbo1(256, 256, QGLFramebufferObject::CombinedDepthStencil); + + QOpenGLFramebufferObjectPaintDevice fbo2(256, 256); + + QImage sourceImage(256, 256, QImage::Format_ARGB32_Premultiplied); + QPainter sourcePainter(&sourceImage); + qt_opengl_draw_test_pattern(&sourcePainter, 256, 256); + + QPainter fbo1Painter(&fbo1); + + QPainter fbo2Painter(&fbo2); + fbo2Painter.drawImage(0, 0, sourceImage); + fbo2Painter.end(); + + QImage fbo2Image = fbo2.toImage(); + + fbo1Painter.drawImage(0, 0, sourceImage); + fbo1Painter.end(); + + QGLFramebufferObject::bindDefault(); + + // Convert the QGLFBO's result since QOpenGLFBO uses a wider + // variety of possible return formats. + QCOMPARE(fbo1.toImage().convertToFormat(fbo2Image.format()), fbo2Image); + } + + { + QGLFramebufferObject fbo1(512, 512, QGLFramebufferObject::CombinedDepthStencil); + + QOpenGLFramebufferObjectPaintDevice fbo2(256, 256); + + QImage sourceImage(256, 256, QImage::Format_ARGB32_Premultiplied); + QPainter sourcePainter(&sourceImage); + qt_opengl_draw_test_pattern(&sourcePainter, 256, 256); + + QPainter fbo2Painter(&fbo2); + fbo2Painter.drawImage(0, 0, sourceImage); + QImage fbo2Image1 = fbo2.toImage(); + fbo2Painter.fillRect(0, 0, 256, 256, Qt::white); + + QPainter fbo1Painter(&fbo1); + fbo1Painter.drawImage(0, 0, sourceImage); + fbo1Painter.end(); + + // check that the OpenGL paint engine now knows it needs to sync + fbo2Painter.drawImage(0, 0, sourceImage); + QImage fbo2Image2 = fbo2.toImage(); + + fbo2Painter.end(); + + QCOMPARE(fbo2Image1, fbo2Image2); + } +} + +// Tests multiple QPainters active on different FBOs at the same time, with +// interleaving painting. Performance-wise, this is sub-optimal, but it still +// has to work flawlessly +void tst_QGL::multipleFBOInterleavedRendering() +{ + if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) + QSKIP("QGLFramebufferObject not supported on this platform"); + + QGLWidget glw; + glw.makeCurrent(); + + // No multisample with combined depth/stencil attachment: + QGLFramebufferObjectFormat fboFormat; + fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + + QGLFramebufferObject *fbo1 = new QGLFramebufferObject(256, 128, fboFormat); + QGLFramebufferObject *fbo2 = new QGLFramebufferObject(256, 128, fboFormat); + QGLFramebufferObject *fbo3 = new QGLFramebufferObject(256, 128, fboFormat); + + if ( (fbo1->attachment() != QGLFramebufferObject::CombinedDepthStencil) || + (fbo2->attachment() != QGLFramebufferObject::CombinedDepthStencil) || + (fbo3->attachment() != QGLFramebufferObject::CombinedDepthStencil) ) + { + delete fbo1; + delete fbo2; + delete fbo3; + QSKIP("FBOs missing combined depth~stencil support"); + } + + QPainter fbo1Painter; + QPainter fbo2Painter; + QPainter fbo3Painter; + + QVERIFY(fbo1Painter.begin(fbo1)); + QVERIFY(fbo2Painter.begin(fbo2)); + QVERIFY(fbo3Painter.begin(fbo3)); + + // Confirm we're using the GL2 engine, as interleaved rendering isn't supported + // on the GL1 engine: + if (fbo1Painter.paintEngine()->type() != QPaintEngine::OpenGL2) + QSKIP("Interleaved GL rendering requires OpenGL 2.0 or higher"); + + QPainterPath intersectingPath; + intersectingPath.moveTo(0, 0); + intersectingPath.lineTo(100, 0); + intersectingPath.lineTo(0, 100); + intersectingPath.lineTo(100, 100); + intersectingPath.closeSubpath(); + + QPainterPath trianglePath; + trianglePath.moveTo(50, 0); + trianglePath.lineTo(100, 100); + trianglePath.lineTo(0, 100); + trianglePath.closeSubpath(); + + fbo1Painter.fillRect(0, 0, fbo1->width(), fbo1->height(), Qt::red); // Background + fbo2Painter.fillRect(0, 0, fbo2->width(), fbo2->height(), Qt::green); // Background + fbo3Painter.fillRect(0, 0, fbo3->width(), fbo3->height(), Qt::blue); // Background + + fbo1Painter.translate(14, 14); + fbo2Painter.translate(14, 14); + fbo3Painter.translate(14, 14); + + fbo1Painter.fillPath(intersectingPath, Qt::blue); // Test stencil buffer works + fbo2Painter.fillPath(intersectingPath, Qt::red); // Test stencil buffer works + fbo3Painter.fillPath(intersectingPath, Qt::green); // Test stencil buffer works + + fbo1Painter.translate(128, 0); + fbo2Painter.translate(128, 0); + fbo3Painter.translate(128, 0); + + fbo1Painter.setClipPath(trianglePath); + fbo2Painter.setClipPath(trianglePath); + fbo3Painter.setClipPath(trianglePath); + + fbo1Painter.setTransform(QTransform()); // reset xform + fbo2Painter.setTransform(QTransform()); // reset xform + fbo3Painter.setTransform(QTransform()); // reset xform + + fbo1Painter.fillRect(0, 0, fbo1->width(), fbo1->height(), Qt::green); + fbo2Painter.fillRect(0, 0, fbo2->width(), fbo2->height(), Qt::blue); + fbo3Painter.fillRect(0, 0, fbo3->width(), fbo3->height(), Qt::red); + + fbo1Painter.end(); + fbo2Painter.end(); + fbo3Painter.end(); + + QImage fb1 = fbo1->toImage().convertToFormat(QImage::Format_RGB32); + QImage fb2 = fbo2->toImage().convertToFormat(QImage::Format_RGB32); + QImage fb3 = fbo3->toImage().convertToFormat(QImage::Format_RGB32); + delete fbo1; + delete fbo2; + delete fbo3; + + // As we're doing more than trivial painting, we can't just compare to + // an image rendered with raster. Instead, we sample at well-defined + // test-points: + QFUZZY_COMPARE_PIXELS(fb1.pixel(39, 64), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb1.pixel(89, 64), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb1.pixel(64, 39), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(fb1.pixel(64, 89), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(fb1.pixel(167, 39), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb1.pixel(217, 39), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb1.pixel(192, 64), QColor(Qt::green).rgb()); + + QFUZZY_COMPARE_PIXELS(fb2.pixel(39, 64), QColor(Qt::green).rgb()); + QFUZZY_COMPARE_PIXELS(fb2.pixel(89, 64), QColor(Qt::green).rgb()); + QFUZZY_COMPARE_PIXELS(fb2.pixel(64, 39), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb2.pixel(64, 89), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb2.pixel(167, 39), QColor(Qt::green).rgb()); + QFUZZY_COMPARE_PIXELS(fb2.pixel(217, 39), QColor(Qt::green).rgb()); + QFUZZY_COMPARE_PIXELS(fb2.pixel(192, 64), QColor(Qt::blue).rgb()); + + QFUZZY_COMPARE_PIXELS(fb3.pixel(39, 64), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(fb3.pixel(89, 64), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(fb3.pixel(64, 39), QColor(Qt::green).rgb()); + QFUZZY_COMPARE_PIXELS(fb3.pixel(64, 89), QColor(Qt::green).rgb()); + QFUZZY_COMPARE_PIXELS(fb3.pixel(167, 39), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(fb3.pixel(217, 39), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(fb3.pixel(192, 64), QColor(Qt::red).rgb()); +} + +class FBOUseInGLWidget : public QGLWidget +{ +public: + bool widgetPainterBeginOk; + bool fboPainterBeginOk; + QImage fboImage; +protected: + void paintEvent(QPaintEvent*) + { + QPainter widgetPainter; + widgetPainterBeginOk = widgetPainter.begin(this); + QGLFramebufferObjectFormat fboFormat; + fboFormat.setAttachment(QGLFramebufferObject::NoAttachment); + QGLFramebufferObject *fbo = new QGLFramebufferObject(100, 100, fboFormat); + + QPainter fboPainter; + fboPainterBeginOk = fboPainter.begin(fbo); + fboPainter.fillRect(-1, -1, 130, 130, Qt::red); + fboPainter.end(); + fboImage = fbo->toImage(); + + widgetPainter.fillRect(-1, -1, width()+2, height()+2, Qt::blue); + + delete fbo; + } + +}; + +void tst_QGL::glFBOUseInGLWidget() +{ + if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) + QSKIP("QGLFramebufferObject not supported on this platform"); + + FBOUseInGLWidget w; + w.resize(100, 100); + w.showNormal(); + + QVERIFY(QTest::qWaitForWindowExposed(&w)); + + QVERIFY(w.widgetPainterBeginOk); + QVERIFY(w.fboPainterBeginOk); + +#if defined(Q_OS_QNX) + // glReadPixels reads from the back buffer. On QNX the buffer is not preserved + // after a buffer swap. This is why we have to swap the buffer explicitly before calling + // grabFrameBuffer to retrieve the content of the front buffer + w.swapBuffers(); +#endif + + QImage widgetFB = w.grabFrameBuffer(false); + QImage widgetReference(widgetFB.size(), widgetFB.format()); + widgetReference.fill(0xff0000ff); + QFUZZY_COMPARE_IMAGES(widgetFB, widgetReference); + + QImage fboReference(w.fboImage.size(), w.fboImage.format()); + fboReference.fill(0xffff0000); + QFUZZY_COMPARE_IMAGES(w.fboImage, fboReference); +} + +void tst_QGL::glWidgetReparent() +{ + // Try it as a top-level first: + GLWidget *widget = new GLWidget; + widget->setObjectName(QStringLiteral("glWidget1")); + widget->setGeometry(0, 0, 200, 30); + widget->show(); + + QWidget grandParentWidget; + grandParentWidget.setObjectName(QStringLiteral("grandParentWidget")); + grandParentWidget.setPalette(Qt::blue); + QVBoxLayout grandParentLayout(&grandParentWidget); + + QWidget parentWidget(&grandParentWidget); + parentWidget.setObjectName(QStringLiteral("parentWidget")); + grandParentLayout.addWidget(&parentWidget); + parentWidget.setPalette(Qt::green); + parentWidget.setAutoFillBackground(true); + QVBoxLayout parentLayout(&parentWidget); + + grandParentWidget.setGeometry(0, 100, 200, 200); + grandParentWidget.show(); + + QVERIFY(QTest::qWaitForWindowExposed(widget)); + QVERIFY(QTest::qWaitForWindowExposed(&grandParentWidget)); + + QVERIFY(parentWidget.children().count() == 1); // The layout + + // Now both widgets should be created & shown, time to re-parent: + parentLayout.addWidget(widget); + + QVERIFY(QTest::qWaitForWindowExposed(&grandParentWidget)); + + QVERIFY(parentWidget.children().count() == 2); // Layout & glwidget + QVERIFY(parentWidget.children().contains(widget)); + QTRY_VERIFY(widget->height() > 30); + + delete widget; + + QVERIFY(QTest::qWaitForWindowExposed(&grandParentWidget)); + + QVERIFY(parentWidget.children().count() == 1); // The layout + + // Now do pretty much the same thing, but don't show the + // widget first: + widget = new GLWidget; + widget->setObjectName(QStringLiteral("glWidget2")); + parentLayout.addWidget(widget); + + QVERIFY(QTest::qWaitForWindowExposed(&grandParentWidget)); + + QVERIFY(parentWidget.children().count() == 2); // Layout & glwidget + QVERIFY(parentWidget.children().contains(widget)); + QVERIFY(widget->height() > 30); + + delete widget; +} + +class RenderPixmapWidget : public QGLWidget +{ +protected: + void initializeGL() { + // Set some gl state: + QOpenGLContext::currentContext()->functions()->glClearColor(1.0, 0.0, 0.0, 1.0); + } + + void paintGL() { + QOpenGLContext::currentContext()->functions()->glClear(GL_COLOR_BUFFER_BIT); + } +}; + +void tst_QGL::glWidgetRenderPixmap() +{ + RenderPixmapWidget *w = new RenderPixmapWidget; + + QSize pmSize = QSize(100, 100); + QPixmap pm = w->renderPixmap(pmSize.width(), pmSize.height(), false); + + delete w; + + QImage fb = pm.toImage().convertToFormat(QImage::Format_RGB32); + QImage reference(pmSize, QImage::Format_RGB32); + reference.fill(0xffff0000); + + QFUZZY_COMPARE_IMAGES(fb, reference); +} + +class ColormapExtended : public QGLColormap +{ +public: + ColormapExtended() {} + + Qt::HANDLE handle() { return QGLColormap::handle(); } + void setHandle(Qt::HANDLE handle) { QGLColormap::setHandle(handle); } +}; + +void tst_QGL::colormap() +{ + // Check the properties of the default empty colormap. + QGLColormap cmap1; + QVERIFY(cmap1.isEmpty()); + QCOMPARE(cmap1.size(), 0); + QCOMPARE(cmap1.entryRgb(0), QRgb(0)); + QCOMPARE(cmap1.entryRgb(-1), QRgb(0)); + QCOMPARE(cmap1.entryRgb(100), QRgb(0)); + QVERIFY(!cmap1.entryColor(0).isValid()); + QVERIFY(!cmap1.entryColor(-1).isValid()); + QVERIFY(!cmap1.entryColor(100).isValid()); + QCOMPARE(cmap1.find(qRgb(255, 0, 0)), -1); + QCOMPARE(cmap1.findNearest(qRgb(255, 0, 0)), -1); + + // Set an entry and re-test. + cmap1.setEntry(56, qRgb(255, 0, 0)); + // The colormap is still considered "empty" even though it + // has entries in it now. The isEmpty() method is used to + // detect when the colormap is in use by a GL widget, + // not to detect when it is empty! + QVERIFY(cmap1.isEmpty()); + QCOMPARE(cmap1.size(), 256); + QCOMPARE(cmap1.entryRgb(0), QRgb(0)); + QVERIFY(cmap1.entryColor(0) == QColor(0, 0, 0, 255)); + QVERIFY(cmap1.entryRgb(56) == qRgb(255, 0, 0)); + QVERIFY(cmap1.entryColor(56) == QColor(255, 0, 0, 255)); + QCOMPARE(cmap1.find(qRgb(255, 0, 0)), 56); + QCOMPARE(cmap1.findNearest(qRgb(255, 0, 0)), 56); + + // Set some more entries. + static QRgb const colors[] = { + qRgb(255, 0, 0), + qRgb(0, 255, 0), + qRgb(255, 255, 255), + qRgb(0, 0, 255), + qRgb(0, 0, 0) + }; + cmap1.setEntry(57, QColor(0, 255, 0)); + cmap1.setEntries(3, colors + 2, 58); + cmap1.setEntries(5, colors, 251); + int idx; + for (idx = 0; idx < 5; ++idx) { + QVERIFY(cmap1.entryRgb(56 + idx) == colors[idx]); + QVERIFY(cmap1.entryColor(56 + idx) == QColor(colors[idx])); + QVERIFY(cmap1.entryRgb(251 + idx) == colors[idx]); + QVERIFY(cmap1.entryColor(251 + idx) == QColor(colors[idx])); + } + QCOMPARE(cmap1.size(), 256); + + // Perform color lookups. + QCOMPARE(cmap1.find(qRgb(255, 0, 0)), 56); + QCOMPARE(cmap1.find(qRgb(0, 0, 0)), 60); // Actually finds 0, 0, 0, 255. + QCOMPARE(cmap1.find(qRgba(0, 0, 0, 0)), 0); + QCOMPARE(cmap1.find(qRgb(0, 255, 0)), 57); + QCOMPARE(cmap1.find(qRgb(255, 255, 255)), 58); + QCOMPARE(cmap1.find(qRgb(0, 0, 255)), 59); + QCOMPARE(cmap1.find(qRgb(140, 0, 0)), -1); + QCOMPARE(cmap1.find(qRgb(0, 140, 0)), -1); + QCOMPARE(cmap1.find(qRgb(0, 0, 140)), -1); + QCOMPARE(cmap1.find(qRgb(64, 0, 0)), -1); + QCOMPARE(cmap1.find(qRgb(0, 64, 0)), -1); + QCOMPARE(cmap1.find(qRgb(0, 0, 64)), -1); + QCOMPARE(cmap1.findNearest(qRgb(255, 0, 0)), 56); + QCOMPARE(cmap1.findNearest(qRgb(0, 0, 0)), 60); + QCOMPARE(cmap1.findNearest(qRgba(0, 0, 0, 0)), 0); + QCOMPARE(cmap1.findNearest(qRgb(0, 255, 0)), 57); + QCOMPARE(cmap1.findNearest(qRgb(255, 255, 255)), 58); + QCOMPARE(cmap1.findNearest(qRgb(0, 0, 255)), 59); + QCOMPARE(cmap1.findNearest(qRgb(140, 0, 0)), 56); + QCOMPARE(cmap1.findNearest(qRgb(0, 140, 0)), 57); + QCOMPARE(cmap1.findNearest(qRgb(0, 0, 140)), 59); + QCOMPARE(cmap1.findNearest(qRgb(64, 0, 0)), 0); + QCOMPARE(cmap1.findNearest(qRgb(0, 64, 0)), 0); + QCOMPARE(cmap1.findNearest(qRgb(0, 0, 64)), 0); + + // Make some copies of the colormap and check that they are the same. + QGLColormap cmap2(cmap1); + QGLColormap cmap3; + cmap3 = cmap1; + QVERIFY(cmap2.isEmpty()); + QVERIFY(cmap3.isEmpty()); + QCOMPARE(cmap2.size(), 256); + QCOMPARE(cmap3.size(), 256); + for (idx = 0; idx < 256; ++idx) { + QCOMPARE(cmap1.entryRgb(idx), cmap2.entryRgb(idx)); + QCOMPARE(cmap1.entryRgb(idx), cmap3.entryRgb(idx)); + } + + // Modify an entry in one of the copies and recheck the original. + cmap2.setEntry(45, qRgb(255, 0, 0)); + for (idx = 0; idx < 256; ++idx) { + if (idx != 45) + QCOMPARE(cmap1.entryRgb(idx), cmap2.entryRgb(idx)); + else + QCOMPARE(cmap2.entryRgb(45), qRgb(255, 0, 0)); + QCOMPARE(cmap1.entryRgb(idx), cmap3.entryRgb(idx)); + } + + // Check that setting the handle will cause isEmpty() to work right. + ColormapExtended cmap4; + cmap4.setEntry(56, qRgb(255, 0, 0)); + QVERIFY(cmap4.isEmpty()); + QCOMPARE(cmap4.size(), 256); + cmap4.setHandle(Qt::HANDLE(42)); + QCOMPARE(cmap4.handle(), Qt::HANDLE(42)); + QVERIFY(!cmap4.isEmpty()); + QCOMPARE(cmap4.size(), 256); +} + +#ifndef GL_TEXTURE_3D +#define GL_TEXTURE_3D 0x806F +#endif + +#ifndef GL_RGB16 +#define GL_RGB16 0x8054 +#endif + +void tst_QGL::fboFormat() +{ + // Check the initial conditions. + QGLFramebufferObjectFormat format1; + QCOMPARE(format1.samples(), 0); + QCOMPARE(format1.attachment(), QGLFramebufferObject::NoAttachment); + QCOMPARE(int(format1.textureTarget()), int(GL_TEXTURE_2D)); + int expectedFormat = +#ifdef QT_OPENGL_ES_2 + GL_RGBA; +#else + QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL ? GL_RGBA : GL_RGBA8; +#endif + QCOMPARE(int(format1.internalTextureFormat()), expectedFormat); + + // Modify the values and re-check. + format1.setSamples(8); + format1.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + format1.setTextureTarget(GL_TEXTURE_3D); + format1.setInternalTextureFormat(GL_RGB16); + QCOMPARE(format1.samples(), 8); + QCOMPARE(format1.attachment(), QGLFramebufferObject::CombinedDepthStencil); + QCOMPARE(int(format1.textureTarget()), int(GL_TEXTURE_3D)); + QCOMPARE(int(format1.internalTextureFormat()), int(GL_RGB16)); + + // Make copies and check that they are the same. + QGLFramebufferObjectFormat format2(format1); + QGLFramebufferObjectFormat format3; + QCOMPARE(format2.samples(), 8); + QCOMPARE(format2.attachment(), QGLFramebufferObject::CombinedDepthStencil); + QCOMPARE(int(format2.textureTarget()), int(GL_TEXTURE_3D)); + QCOMPARE(int(format2.internalTextureFormat()), int(GL_RGB16)); + format3 = format1; + QCOMPARE(format3.samples(), 8); + QCOMPARE(format3.attachment(), QGLFramebufferObject::CombinedDepthStencil); + QCOMPARE(int(format3.textureTarget()), int(GL_TEXTURE_3D)); + QCOMPARE(int(format3.internalTextureFormat()), int(GL_RGB16)); + + // Modify the copies and check that the original is unchanged. + format2.setSamples(9); + format3.setTextureTarget(GL_TEXTURE_2D); + QCOMPARE(format1.samples(), 8); + QCOMPARE(format1.attachment(), QGLFramebufferObject::CombinedDepthStencil); + QCOMPARE(int(format1.textureTarget()), int(GL_TEXTURE_3D)); + QCOMPARE(int(format1.internalTextureFormat()), int(GL_RGB16)); + + // operator== and operator!= for QGLFramebufferObjectFormat. + QGLFramebufferObjectFormat format1c; + QGLFramebufferObjectFormat format2c; + + QCOMPARE(format1c, format2c); + QVERIFY(!(format1c != format2c)); + format1c.setSamples(8); + QVERIFY(!(format1c == format2c)); + QVERIFY(format1c != format2c); + format2c.setSamples(8); + QCOMPARE(format1c, format2c); + QVERIFY(!(format1c != format2c)); + + format1c.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + QVERIFY(!(format1c == format2c)); + QVERIFY(format1c != format2c); + format2c.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + QCOMPARE(format1c, format2c); + QVERIFY(!(format1c != format2c)); + + format1c.setTextureTarget(GL_TEXTURE_3D); + QVERIFY(!(format1c == format2c)); + QVERIFY(format1c != format2c); + format2c.setTextureTarget(GL_TEXTURE_3D); + QCOMPARE(format1c, format2c); + QVERIFY(!(format1c != format2c)); + + format1c.setInternalTextureFormat(GL_RGB16); + QVERIFY(!(format1c == format2c)); + QVERIFY(format1c != format2c); + format2c.setInternalTextureFormat(GL_RGB16); + QCOMPARE(format1c, format2c); + QVERIFY(!(format1c != format2c)); + + QGLFramebufferObjectFormat format3c(format1c); + QGLFramebufferObjectFormat format4c; + QCOMPARE(format1c, format3c); + QVERIFY(!(format1c != format3c)); + format3c.setInternalTextureFormat( +#ifdef QT_OPENGL_ES_2 + GL_RGBA +#else + QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL ? GL_RGBA : GL_RGBA8 +#endif + ); + QVERIFY(!(format1c == format3c)); + QVERIFY(format1c != format3c); + + format4c = format1c; + QCOMPARE(format1c, format4c); + QVERIFY(!(format1c != format4c)); + format4c.setInternalTextureFormat( +#ifdef QT_OPENGL_ES_2 + GL_RGBA +#else + QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL ? GL_RGBA : GL_RGBA8 +#endif + ); + QVERIFY(!(format1c == format4c)); + QVERIFY(format1c != format4c); +} + +void tst_QGL::testDontCrashOnDanglingResources() +{ + // We have a number of Q_GLOBAL_STATICS inside the Qt OpenGL + // module. This test is verify that we don't crash as a result of + // them calling into libgl on application shutdown. + QWidget *widget = new UnclippedWidget(); + widget->show(); + qApp->processEvents(); + widget->hide(); +} + +class ReplaceClippingGLWidget : public QGLWidget +{ +public: + void paint(QPainter *painter) + { + painter->fillRect(rect(), Qt::white); + + QPainterPath path; + path.addRect(0, 0, 100, 100); + path.addRect(50, 50, 100, 100); + + painter->setClipRect(0, 0, 150, 150); + painter->fillPath(path, Qt::red); + + painter->translate(150, 150); + painter->setClipRect(0, 0, 150, 150); + painter->fillPath(path, Qt::red); + } + +protected: + void paintEvent(QPaintEvent*) + { + // clear the stencil with junk + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + funcs->glStencilMask(0xFFFF); + funcs->glClearStencil(0xFFFF); + funcs->glDisable(GL_STENCIL_TEST); + funcs->glDisable(GL_SCISSOR_TEST); + funcs->glClear(GL_STENCIL_BUFFER_BIT); + + QPainter painter(this); + paint(&painter); + } +}; + +void tst_QGL::replaceClipping() +{ + ReplaceClippingGLWidget glw; + glw.resize(300, 300); + glw.show(); + + QVERIFY(QTest::qWaitForWindowExposed(&glw)); + + QImage reference(300, 300, QImage::Format_RGB32); + QPainter referencePainter(&reference); + glw.paint(&referencePainter); + referencePainter.end(); + +#if defined(Q_OS_QNX) + // glReadPixels reads from the back buffer. On QNX the buffer is not preserved + // after a buffer swap. This is why we have to swap the buffer explicitly before calling + // grabFrameBuffer to retrieve the content of the front buffer + glw.swapBuffers(); +#endif + const QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32); + + // Sample pixels in a grid pattern which avoids false failures due to + // off-by-one pixel errors on some buggy GL implementations + for (int x = 25; x < reference.width(); x += 50) { + for (int y = 25; y < reference.width(); y += 50) { + QFUZZY_COMPARE_PIXELS(widgetFB.pixel(x, y), reference.pixel(x, y)); + } + } +} + +class ClipTestGLWidget : public QGLWidget +{ +public: + void paint(QPainter *painter) + { + painter->fillRect(-1, -1, width()+2, height()+2, Qt::white); + painter->setClipRect(10, 10, width()-20, height()-20); + painter->fillRect(rect(), Qt::cyan); + + painter->save(); + painter->setClipRect(10, 10, 100, 100, Qt::IntersectClip); + + painter->fillRect(rect(), Qt::blue); + + painter->save(); + painter->setClipRect(10, 10, 50, 50, Qt::IntersectClip); + painter->fillRect(rect(), Qt::red); + painter->restore(); + painter->fillRect(0, 0, 40, 40, Qt::white); + painter->save(); + + painter->setClipRect(0, 0, 35, 35, Qt::IntersectClip); + painter->fillRect(rect(), Qt::black); + painter->restore(); + + painter->fillRect(0, 0, 30, 30, Qt::magenta); + + painter->save(); + painter->setClipRect(60, 10, 50, 50, Qt::ReplaceClip); + painter->fillRect(rect(), Qt::green); + painter->restore(); + + painter->restore(); + + painter->translate(100, 100); + + { + QPainterPath path; + path.addRect(10, 10, 100, 100); + path.addRect(10, 10, 10, 10); + painter->setClipPath(path, Qt::IntersectClip); + } + + painter->fillRect(rect(), Qt::blue); + + painter->save(); + { + QPainterPath path; + path.addRect(10, 10, 50, 50); + path.addRect(10, 10, 10, 10); + painter->setClipPath(path, Qt::IntersectClip); + } + painter->fillRect(rect(), Qt::red); + painter->restore(); + painter->fillRect(0, 0, 40, 40, Qt::white); + painter->save(); + + { + QPainterPath path; + path.addRect(0, 0, 35, 35); + path.addRect(10, 10, 10, 10); + painter->setClipPath(path, Qt::IntersectClip); + } + painter->fillRect(rect(), Qt::black); + painter->restore(); + + painter->fillRect(0, 0, 30, 30, Qt::magenta); + + painter->save(); + { + QPainterPath path; + path.addRect(60, 10, 50, 50); + path.addRect(10, 10, 10, 10); + painter->setClipPath(path, Qt::ReplaceClip); + } + painter->fillRect(rect(), Qt::green); + painter->restore(); + } + +protected: + void paintEvent(QPaintEvent*) + { + QPainter painter(this); + paint(&painter); + } +}; + +void tst_QGL::clipTest() +{ + ClipTestGLWidget glw; + glw.resize(220, 220); + glw.showNormal(); + + QVERIFY(QTest::qWaitForWindowExposed(&glw)); + + QImage reference(glw.size(), QImage::Format_RGB32); + QPainter referencePainter(&reference); + glw.paint(&referencePainter); + referencePainter.end(); + +#if defined(Q_OS_QNX) + // glReadPixels reads from the back buffer. On QNX the buffer is not preserved + // after a buffer swap. This is why we have to swap the buffer explicitly before calling + // grabFrameBuffer to retrieve the content of the front buffer + glw.swapBuffers(); +#endif + const QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32); + + // Sample pixels in a grid pattern which avoids false failures due to + // off-by-one pixel errors on some buggy GL implementations + for (int x = 2; x < reference.width(); x += 5) { + for (int y = 2; y < reference.height(); y += 5) { + QFUZZY_COMPARE_PIXELS(widgetFB.pixel(x, y), reference.pixel(x, y)); + } + } +} + +void tst_QGL::destroyFBOAfterContext() +{ + if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) + QSKIP("QGLFramebufferObject not supported on this platform"); + + QGLWidget *glw = new QGLWidget(); + glw->makeCurrent(); + + // No multisample with combined depth/stencil attachment: + QGLFramebufferObjectFormat fboFormat; + fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + + // Don't complicate things by using NPOT: + QGLFramebufferObject *fbo = new QGLFramebufferObject(256, 128, fboFormat); + + // The handle should be valid until the context is destroyed. + QVERIFY(fbo->handle() != 0); + QVERIFY(fbo->isValid()); + + delete glw; + + // The handle should now be zero. + QVERIFY(!fbo->handle()); + QVERIFY(!fbo->isValid()); + + delete fbo; +} + +#ifdef QT_BUILD_INTERNAL + +class tst_QGLResource +{ +public: + tst_QGLResource(const QGLContext * = 0) {} + ~tst_QGLResource() { ++deletions; } + + static int deletions; +}; + +int tst_QGLResource::deletions = 0; + +#ifdef TODO +Q_GLOBAL_STATIC(QOpenGLContextGroupResource<tst_QGLResource>, qt_shared_test) +#endif //TODO +#endif // QT_BUILD_INTERNAL + +#ifdef QT_BUILD_INTERNAL +void tst_QGL::shareRegister() +{ +#ifdef TODO + // Create a context. + QGLWidget *glw1 = new QGLWidget(); + glw1->makeCurrent(); + + // Nothing should be sharing with glw1's context yet. + QVERIFY(!glw1->isSharing()); + + // Create a guard for the first context. + QOpenGLSharedResourceGuard guard(glw1->context()->contextHandle()); + QCOMPARE(guard.id(), 0); + guard.setId(3); + QCOMPARE(guard.id(), 3); + + // Request a tst_QGLResource object for the first context. + tst_QGLResource *res1 = qt_shared_test()->value(glw1->context()->contextHandle()); + QVERIFY(res1); + QCOMPARE(qt_shared_test()->value(glw1->context()->contextHandle()), res1); + + // Create another context that shares with the first. + QVERIFY(!glw1->isSharing()); + QGLWidget *glw2 = new QGLWidget(0, glw1); + if (!glw2->isSharing()) { + delete glw2; + delete glw1; + QSKIP("Context sharing is not supported"); + } + QVERIFY(glw1->isSharing()); + QVERIFY(glw1->context() != glw2->context()); + + // Check that the first context's resource is also on the second. + QCOMPARE(qt_shared_test()->value(glw1->context()), res1); + QCOMPARE(qt_shared_test()->value(glw2->context()), res1); + + // Guard should still be the same. + QCOMPARE(guard.context(), glw1->context()); + QCOMPARE(guard.id(), 3); + + // Check the sharing relationships. + QVERIFY(QGLContext::areSharing(glw1->context(), glw1->context())); + QVERIFY(QGLContext::areSharing(glw2->context(), glw2->context())); + QVERIFY(QGLContext::areSharing(glw1->context(), glw2->context())); + QVERIFY(QGLContext::areSharing(glw2->context(), glw1->context())); + QVERIFY(!QGLContext::areSharing(0, glw2->context())); + QVERIFY(!QGLContext::areSharing(glw1->context(), 0)); + QVERIFY(!QGLContext::areSharing(0, 0)); + + // Create a third context, not sharing with the others. + QGLWidget *glw3 = new QGLWidget(); + QVERIFY(!glw3->isSharing()); + + // Create a guard on the standalone context. + QGLSharedResourceGuard guard3(glw3->context()); + guard3.setId(5); + + // Request a resource to the third context. + tst_QGLResource *res3 = qt_shared_test()->value(glw3->context()); + QVERIFY(res3); + QCOMPARE(qt_shared_test()->value(glw1->context()), res1); + QCOMPARE(qt_shared_test()->value(glw2->context()), res1); + QCOMPARE(qt_shared_test()->value(glw3->context()), res3); + + // Check the sharing relationships again. + QVERIFY(QGLContext::areSharing(glw1->context(), glw1->context())); + QVERIFY(QGLContext::areSharing(glw2->context(), glw2->context())); + QVERIFY(QGLContext::areSharing(glw1->context(), glw2->context())); + QVERIFY(QGLContext::areSharing(glw2->context(), glw1->context())); + QVERIFY(!QGLContext::areSharing(glw1->context(), glw3->context())); + QVERIFY(!QGLContext::areSharing(glw2->context(), glw3->context())); + QVERIFY(!QGLContext::areSharing(glw3->context(), glw1->context())); + QVERIFY(!QGLContext::areSharing(glw3->context(), glw2->context())); + QVERIFY(QGLContext::areSharing(glw3->context(), glw3->context())); + QVERIFY(!QGLContext::areSharing(0, glw2->context())); + QVERIFY(!QGLContext::areSharing(glw1->context(), 0)); + QVERIFY(!QGLContext::areSharing(0, glw3->context())); + QVERIFY(!QGLContext::areSharing(glw3->context(), 0)); + QVERIFY(!QGLContext::areSharing(0, 0)); + + // Shared guard should still be the same. + QCOMPARE(guard.context(), glw1->context()); + QCOMPARE(guard.id(), 3); + + // Delete the first context. + delete glw1; + + // The second context should no longer register as sharing. + QVERIFY(!glw2->isSharing()); + + // The first context's resource should transfer to the second context. + QCOMPARE(tst_QGLResource::deletions, 0); + QCOMPARE(qt_shared_test()->value(glw2->context()), res1); + QCOMPARE(qt_shared_test()->value(glw3->context()), res3); + + // Shared guard should now be the second context, with the id the same. + QCOMPARE(guard.context(), glw2->context()); + QCOMPARE(guard.id(), 3); + QCOMPARE(guard3.context(), glw3->context()); + QCOMPARE(guard3.id(), 5); + + // Clean up and check that the resources are properly deleted. + delete glw2; + QCOMPARE(tst_QGLResource::deletions, 1); + delete glw3; + QCOMPARE(tst_QGLResource::deletions, 2); + + // Guards should now be null and the id zero. + QVERIFY(guard.context() == 0); + QVERIFY(guard.id() == 0); + QVERIFY(guard3.context() == 0); + QVERIFY(guard3.id() == 0); +#endif //TODO +} +#endif + +// Tests QGLContext::bindTexture with default options +#ifdef QT_BUILD_INTERNAL +void tst_QGL::qglContextDefaultBindTexture() +{ + QGLWidget w; + w.makeCurrent(); + QGLContext *ctx = const_cast<QGLContext*>(w.context()); + + QImage *boundImage = new QImage(256, 256, QImage::Format_RGB32); + boundImage->fill(0xFFFFFFFF); + QPixmap *boundPixmap = new QPixmap(256, 256); + boundPixmap->fill(Qt::red); + + int startCacheItemCount = QGLTextureCache::instance()->size(); + + GLuint boundImageTextureId = ctx->bindTexture(*boundImage); + GLuint boundPixmapTextureId = ctx->bindTexture(*boundPixmap); + + // Make sure the image & pixmap have been added to the cache: + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2); + + // Make sure the image & pixmap have the is_cached flag set: + QVERIFY(QImagePixmapCleanupHooks::isImageCached(*boundImage)); + QVERIFY(QImagePixmapCleanupHooks::isPixmapCached(*boundPixmap)); + + QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + // Make sure the texture IDs returned are valid: + QCOMPARE(funcs->glIsTexture(boundImageTextureId), GLboolean(GL_TRUE)); + QCOMPARE(funcs->glIsTexture(boundPixmapTextureId), GLboolean(GL_TRUE)); + + // Make sure the textures are still valid after we delete the image/pixmap: + // Also check that although the textures are left intact, the cache entries are removed: + delete boundImage; + boundImage = 0; + QCOMPARE(funcs->glIsTexture(boundImageTextureId), GLboolean(GL_TRUE)); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + delete boundPixmap; + boundPixmap = 0; + QCOMPARE(funcs->glIsTexture(boundPixmapTextureId), GLboolean(GL_TRUE)); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount); + + // Finally, make sure QGLContext::deleteTexture deletes the texture IDs: + ctx->deleteTexture(boundImageTextureId); + ctx->deleteTexture(boundPixmapTextureId); + QCOMPARE(funcs->glIsTexture(boundImageTextureId), GLboolean(GL_FALSE)); + QCOMPARE(funcs->glIsTexture(boundPixmapTextureId), GLboolean(GL_FALSE)); +} +#endif + +#ifdef QT_BUILD_INTERNAL +void tst_QGL::textureCleanup() +{ + QGLWidget w; + w.resize(200,200); + w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); + w.makeCurrent(); + + // Test pixmaps which have been loaded via QPixmapCache are removed from the texture cache + // when the pixmap cache is cleared + { + int startCacheItemCount = QGLTextureCache::instance()->size(); + QPainter p(&w); + + QPixmap boundPixmap(":designer.png"); + + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount); + + p.drawPixmap(0, 0, boundPixmap); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + // Need to call end for the GL2 paint engine to release references to pixmap if using tfp + p.end(); + + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + // Check that the texture doesn't get removed from the cache when the pixmap is cleared + // as it should still be in the cache: + boundPixmap = QPixmap(); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + QPixmapCache::clear(); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount); + } + + // Test pixmaps which have been loaded via QPixmapCache are removed from the texture cache + // when they are explicitly removed from the pixmap cache + { + int startCacheItemCount = QGLTextureCache::instance()->size(); + QPainter p(&w); + + QPixmap boundPixmap(128, 128); + QString cacheKey = QString::fromLatin1("myPixmap"); + QPixmapCache::insert(cacheKey, boundPixmap); + + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount); + + p.drawPixmap(0, 0, boundPixmap); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + // Need to call end for the GL2 paint engine to release references to pixmap if using tfp + p.end(); + + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + // Check that the texture doesn't get removed from the cache when the pixmap is cleared + // as it should still be in the cache: + boundPixmap = QPixmap(); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + // Finally, we check that the texture cache entry is removed when we remove the + // pixmap cache entry, which should hold the last reference: + QPixmapCache::remove(cacheKey); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount); + } + + // Check images & pixmaps are removed from the cache when they are deleted + { + int startCacheItemCount = QGLTextureCache::instance()->size(); + QPainter p(&w); + + QImage *boundImage = new QImage(256, 256, QImage::Format_RGB32); + boundImage->fill(0xFFFFFFFF); + QPixmap *boundPixmap = new QPixmap(256, 256); + boundPixmap->fill(Qt::red); + + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount); + + p.drawImage(0, 0, *boundImage); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + p.drawPixmap(0, 0, *boundPixmap); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2); + + // Need to call end for the GL2 paint engine to release references to pixmap if using tfp + p.end(); + + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2); + + delete boundImage; + boundImage = 0; + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + delete boundPixmap; + boundPixmap = 0; + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount); + } + + // Check images & pixmaps are removed from the cache when they are assigned to + { + int startCacheItemCount = QGLTextureCache::instance()->size(); + QPainter p(&w); + + QImage boundImage(256, 256, QImage::Format_RGB32); + boundImage.fill(0xFFFFFFFF); + QPixmap boundPixmap(256, 256); + boundPixmap.fill(Qt::red); + + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount); + + p.drawImage(0, 0, boundImage); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + p.drawPixmap(0, 0, boundPixmap); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2); + + // Need to call end for the GL2 paint engine to release references to pixmap if using tfp + p.end(); + + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2); + + boundImage = QImage(64, 64, QImage::Format_RGB32); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + boundPixmap = QPixmap(64, 64); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount); + } + + // Check images & pixmaps are removed from the cache when they are modified (detached) + { + int startCacheItemCount = QGLTextureCache::instance()->size(); + QPainter p(&w); + + QImage boundImage(256, 256, QImage::Format_RGB32); + boundImage.fill(0xFFFFFFFF); + QPixmap boundPixmap(256, 256); + boundPixmap.fill(Qt::red); + + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount); + + p.drawImage(0, 0, boundImage); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + p.drawPixmap(0, 0, boundPixmap); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2); + + // Need to call end for the GL2 paint engine to release references to pixmap if using tfp + p.end(); + + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2); + + boundImage.fill(0x00000000); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + boundPixmap.fill(Qt::blue); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount); + } + + // Check that images/pixmaps aren't removed from the cache if a shallow copy has been made + QImage copyOfImage; + QPixmap copyOfPixmap; + int startCacheItemCount = QGLTextureCache::instance()->size(); + { + QPainter p(&w); + + QImage boundImage(256, 256, QImage::Format_RGB32); + boundImage.fill(0xFFFFFFFF); + QPixmap boundPixmap(256, 256); + boundPixmap.fill(Qt::red); + + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount); + + p.drawImage(0, 0, boundImage); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + p.drawPixmap(0, 0, boundPixmap); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2); + + // Need to call end for the GL2 paint engine to release references to pixmap if using tfp + p.end(); + + copyOfImage = boundImage; + copyOfPixmap = boundPixmap; + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2); + } // boundImage & boundPixmap would have been deleted when they went out of scope + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2); + + copyOfImage = QImage(); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1); + + copyOfPixmap = QPixmap(); + QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount); +} +#endif + +namespace ThreadImages { + +class Producer : public QObject +{ + Q_OBJECT +public: + Producer() + { + startTimer(20); + + QThread *thread = new QThread; + thread->start(); + + connect(this, SIGNAL(destroyed()), thread, SLOT(quit())); + + moveToThread(thread); + connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); + } + +signals: + void imageReady(const QImage &image); + +protected: + void timerEvent(QTimerEvent *) + { + QImage image(256, 256, QImage::Format_RGB32); + QLinearGradient g(0, 0, 0, 256); + g.setColorAt(0, QColor(255, 180, 180)); + g.setColorAt(1, Qt::white); + g.setSpread(QGradient::ReflectSpread); + + QBrush brush(g); + brush.setTransform(QTransform::fromTranslate(0, delta)); + delta += 10; + + QPainter p(&image); + p.fillRect(image.rect(), brush); + + if (images.size() > 10) + images.removeFirst(); + + images.append(image); + + emit imageReady(image); + } + +private: + QList<QImage> images; + int delta; +}; + + +class DisplayWidget : public QGLWidget +{ + Q_OBJECT +public: + DisplayWidget(QWidget *parent) : QGLWidget(parent) {} + void paintEvent(QPaintEvent *) + { + QPainter p(this); + p.drawImage(rect(), m_image); + } + +public slots: + void setImage(const QImage &image) + { + m_image = image; + update(); + } + +private: + QImage m_image; +}; + +class Widget : public QWidget +{ + Q_OBJECT +public: + Widget() + : iterations(0) + , display(0) + , producer(new Producer) + { + startTimer(400); + connect(this, SIGNAL(destroyed()), producer, SLOT(deleteLater())); + } + + int iterations; + +protected: + void timerEvent(QTimerEvent *) + { + ++iterations; + + delete display; + display = new DisplayWidget(this); + connect(producer, SIGNAL(imageReady(QImage)), display, SLOT(setImage(QImage))); + + display->setGeometry(rect()); + display->show(); + } + +private: + DisplayWidget *display; + Producer *producer; +}; + +} + +void tst_QGL::threadImages() +{ + ThreadImages::Widget *widget = new ThreadImages::Widget; + widget->show(); + + while (widget->iterations <= 5) { + qApp->processEvents(); + } + + delete widget; +} + +void tst_QGL::nullRectCrash() +{ + if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) + QSKIP("QGLFramebufferObject not supported on this platform"); + + QGLWidget glw; + glw.makeCurrent(); + + QGLFramebufferObjectFormat fboFormat; + fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + + QGLFramebufferObject *fbo = new QGLFramebufferObject(128, 128, fboFormat); + + QPainter fboPainter(fbo); + + fboPainter.setPen(QPen(QColor(255, 127, 127, 127), 2)); + fboPainter.setBrush(QColor(127, 255, 127, 127)); + fboPainter.drawRect(QRectF()); + + fboPainter.end(); +} + +void tst_QGL::extensions() +{ + QGLWidget glw; + glw.makeCurrent(); + + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + QVERIFY(ctx); + QOpenGLFunctions *funcs = ctx->functions(); + QVERIFY(funcs); + QSurfaceFormat format = ctx->format(); + +#ifdef QT_BUILD_INTERNAL + QOpenGLExtensions *exts = static_cast<QOpenGLExtensions *>(funcs); + QOpenGLExtensions::OpenGLExtensions allExts = exts->openGLExtensions(); + // Mipmapping is always available in GL2/GLES2+. Verify this. + if (format.majorVersion() >= 2) + QVERIFY(allExts.testFlag(QOpenGLExtensions::GenerateMipmap)); +#endif + + // Now look for some features should always be available in a given version. + QOpenGLFunctions::OpenGLFeatures allFeatures = funcs->openGLFeatures(); + QVERIFY(allFeatures.testFlag(QOpenGLFunctions::Multitexture)); + if (format.majorVersion() >= 2) { + QVERIFY(allFeatures.testFlag(QOpenGLFunctions::Shaders)); + QVERIFY(allFeatures.testFlag(QOpenGLFunctions::Buffers)); + QVERIFY(allFeatures.testFlag(QOpenGLFunctions::Multisample)); + QVERIFY(!ctx->isOpenGLES() || allFeatures.testFlag(QOpenGLFunctions::Framebuffers)); + QVERIFY(allFeatures.testFlag(QOpenGLFunctions::NPOTTextures) + && allFeatures.testFlag(QOpenGLFunctions::NPOTTextureRepeat)); + if (ctx->isOpenGLES()) { + QVERIFY(!allFeatures.testFlag(QOpenGLFunctions::FixedFunctionPipeline)); + QVERIFY(allFeatures.testFlag(QOpenGLFunctions::Framebuffers)); + } + } + if (format.majorVersion() >= 3) + QVERIFY(allFeatures.testFlag(QOpenGLFunctions::Framebuffers)); +} + +QTEST_MAIN(tst_QGL) +#include "tst_qgl.moc" diff --git a/tests/auto/other/lancelot/paintcommands.cpp b/tests/auto/other/lancelot/paintcommands.cpp index c1ff7e7a87..e98df3781e 100644 --- a/tests/auto/other/lancelot/paintcommands.cpp +++ b/tests/auto/other/lancelot/paintcommands.cpp @@ -31,6 +31,7 @@ #include <qfile.h> #include <qfileinfo.h> #include <qpainter.h> +#include <qpainterpath.h> #include <qbitmap.h> #include <qtextstream.h> #include <qtextlayout.h> diff --git a/tests/auto/testlib/selftests/expected_pass.junitxml b/tests/auto/testlib/selftests/expected_pass.junitxml new file mode 100644 index 0000000000..b148593bd0 --- /dev/null +++ b/tests/auto/testlib/selftests/expected_pass.junitxml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<testsuite errors="0" failures="0" tests="5" name="tst_Pass"> + <properties> + <property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/> + <property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/> + <property value="" name="QtBuild"/> + </properties> + <testcase result="pass" name="initTestCase"/> + <testcase result="pass" name="testNumber1"/> + <testcase result="pass" name="testNumber2"/> + <testcase result="pass" name="testNumber3"/> + <testcase result="pass" name="cleanupTestCase"/> + <system-err/> +</testsuite> diff --git a/tests/auto/testlib/selftests/expected_pass.lightxml b/tests/auto/testlib/selftests/expected_pass.lightxml new file mode 100644 index 0000000000..4d344e93cf --- /dev/null +++ b/tests/auto/testlib/selftests/expected_pass.lightxml @@ -0,0 +1,26 @@ +<Environment> + <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion> + <QtBuild/> + <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion> +</Environment> +<TestFunction name="initTestCase"> +<Incident type="pass" file="" line="0" /> + <Duration msecs="0"/> +</TestFunction> +<TestFunction name="testNumber1"> +<Incident type="pass" file="" line="0" /> + <Duration msecs="0"/> +</TestFunction> +<TestFunction name="testNumber2"> +<Incident type="pass" file="" line="0" /> + <Duration msecs="0"/> +</TestFunction> +<TestFunction name="testNumber3"> +<Incident type="pass" file="" line="0" /> + <Duration msecs="0"/> +</TestFunction> +<TestFunction name="cleanupTestCase"> +<Incident type="pass" file="" line="0" /> + <Duration msecs="0"/> +</TestFunction> +<Duration msecs="0"/> diff --git a/tests/auto/testlib/selftests/expected_pass.tap b/tests/auto/testlib/selftests/expected_pass.tap new file mode 100644 index 0000000000..a01755dc25 --- /dev/null +++ b/tests/auto/testlib/selftests/expected_pass.tap @@ -0,0 +1,11 @@ +TAP version 13 +# tst_Pass +ok 1 - initTestCase() +ok 2 - testNumber1() +ok 3 - testNumber2() +ok 4 - testNumber3() +ok 5 - cleanupTestCase() +1..5 +# tests 5 +# pass 5 +# fail 0 diff --git a/tests/auto/testlib/selftests/expected_pass.teamcity b/tests/auto/testlib/selftests/expected_pass.teamcity new file mode 100644 index 0000000000..11dc666fb7 --- /dev/null +++ b/tests/auto/testlib/selftests/expected_pass.teamcity @@ -0,0 +1,12 @@ +##teamcity[testSuiteStarted name='tst_Pass' flowId='tst_Pass'] +##teamcity[testStarted name='initTestCase()' flowId='tst_Pass'] +##teamcity[testFinished name='initTestCase()' flowId='tst_Pass'] +##teamcity[testStarted name='testNumber1()' flowId='tst_Pass'] +##teamcity[testFinished name='testNumber1()' flowId='tst_Pass'] +##teamcity[testStarted name='testNumber2()' flowId='tst_Pass'] +##teamcity[testFinished name='testNumber2()' flowId='tst_Pass'] +##teamcity[testStarted name='testNumber3()' flowId='tst_Pass'] +##teamcity[testFinished name='testNumber3()' flowId='tst_Pass'] +##teamcity[testStarted name='cleanupTestCase()' flowId='tst_Pass'] +##teamcity[testFinished name='cleanupTestCase()' flowId='tst_Pass'] +##teamcity[testSuiteFinished name='tst_Pass' flowId='tst_Pass'] diff --git a/tests/auto/testlib/selftests/expected_pass.txt b/tests/auto/testlib/selftests/expected_pass.txt new file mode 100644 index 0000000000..0d7265f970 --- /dev/null +++ b/tests/auto/testlib/selftests/expected_pass.txt @@ -0,0 +1,9 @@ +********* Start testing of tst_Pass ********* +Config: Using QtTest library +PASS : tst_Pass::initTestCase() +PASS : tst_Pass::testNumber1() +PASS : tst_Pass::testNumber2() +PASS : tst_Pass::testNumber3() +PASS : tst_Pass::cleanupTestCase() +Totals: 5 passed, 0 failed, 0 skipped, 0 blacklisted, 0ms +********* Finished testing of tst_Pass ********* diff --git a/tests/auto/testlib/selftests/expected_pass.xml b/tests/auto/testlib/selftests/expected_pass.xml new file mode 100644 index 0000000000..b221cb5411 --- /dev/null +++ b/tests/auto/testlib/selftests/expected_pass.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<TestCase name="tst_Pass"> +<Environment> + <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion> + <QtBuild/> + <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion> +</Environment> +<TestFunction name="initTestCase"> +<Incident type="pass" file="" line="0" /> + <Duration msecs="0"/> +</TestFunction> +<TestFunction name="testNumber1"> +<Incident type="pass" file="" line="0" /> + <Duration msecs="0"/> +</TestFunction> +<TestFunction name="testNumber2"> +<Incident type="pass" file="" line="0" /> + <Duration msecs="0"/> +</TestFunction> +<TestFunction name="testNumber3"> +<Incident type="pass" file="" line="0" /> + <Duration msecs="0"/> +</TestFunction> +<TestFunction name="cleanupTestCase"> +<Incident type="pass" file="" line="0" /> + <Duration msecs="0"/> +</TestFunction> +<Duration msecs="0"/> +</TestCase> diff --git a/tests/auto/testlib/selftests/pass/pass.pro b/tests/auto/testlib/selftests/pass/pass.pro new file mode 100644 index 0000000000..dd00a1c744 --- /dev/null +++ b/tests/auto/testlib/selftests/pass/pass.pro @@ -0,0 +1,9 @@ +SOURCES += tst_pass.cpp +QT = core testlib + +macos:CONFIG -= app_bundle +CONFIG -= debug_and_release_target + +TARGET = pass + +include($$QT_SOURCE_TREE/src/testlib/selfcover.pri) diff --git a/tests/auto/testlib/selftests/pass/tst_pass.cpp b/tests/auto/testlib/selftests/pass/tst_pass.cpp new file mode 100644 index 0000000000..6fa5f6a209 --- /dev/null +++ b/tests/auto/testlib/selftests/pass/tst_pass.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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$ +** +****************************************************************************/ + +#include <QtCore/QCoreApplication> +#include <QtTest/QtTest> + +class tst_Pass: public QObject +{ + Q_OBJECT + +private slots: + void testNumber1() const; + void testNumber2() const; + void testNumber3() const; +}; + +void tst_Pass::testNumber1() const +{ +} + +void tst_Pass::testNumber2() const +{ +} + +void tst_Pass::testNumber3() const +{ +} + +QTEST_MAIN(tst_Pass) + +#include "tst_pass.moc" diff --git a/tests/auto/testlib/selftests/selftests.pri b/tests/auto/testlib/selftests/selftests.pri index 2cad0b7e17..b124b21981 100644 --- a/tests/auto/testlib/selftests/selftests.pri +++ b/tests/auto/testlib/selftests/selftests.pri @@ -31,6 +31,7 @@ SUBPROGRAMS = \ longstring \ maxwarnings \ multiexec \ + pass \ pairdiagnostics \ printdatatags \ printdatatagswithglobaltags \ diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp index be64752ceb..cab6589984 100644 --- a/tests/auto/testlib/selftests/tst_selftests.cpp +++ b/tests/auto/testlib/selftests/tst_selftests.cpp @@ -422,9 +422,9 @@ void tst_Selftests::initTestCase() { QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString())); //Detect the location of the sub programs - QString subProgram = QLatin1String("float/float"); + QString subProgram = QLatin1String("pass/pass"); #if defined(Q_OS_WIN) - subProgram = QLatin1String("float/float.exe"); + subProgram = QLatin1String("pass/pass.exe"); #endif QString testdataDir = QFINDTESTDATA(subProgram); if (testdataDir.lastIndexOf(subProgram) > 0) @@ -487,6 +487,7 @@ void tst_Selftests::runSubTest_data() << "longstring" << "maxwarnings" << "multiexec" + << "pass" << "pairdiagnostics" << "printdatatags" << "printdatatagswithglobaltags" diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp index fe6ef5a00a..1cc793503a 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp @@ -59,6 +59,7 @@ #include <QSharedPointer> #include <float.h> #include <QStyleHints> +#include <QPainterPath> using AbstractGraphicsShapeItemPtr = QSharedPointer<QAbstractGraphicsShapeItem>; using GraphicsItems = QVector<QGraphicsItem *>; diff --git a/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp index 2822279190..e7bba010d9 100644 --- a/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp @@ -30,6 +30,7 @@ #include <QtTest/QtTest> #include <qgraphicsscene.h> #include <qgraphicsitem.h> +#include <qpainterpath.h> class tst_QGraphicsPixmapItem : public QObject { diff --git a/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp index fbdd38804d..5380dd0daf 100644 --- a/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp @@ -29,6 +29,7 @@ #include <QtTest/QtTest> #include <qgraphicsitem.h> +#include <qpainterpath.h> #include <qpen.h> diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp index cfbe1f96ee..7e5d94da22 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp @@ -37,6 +37,7 @@ #include <QtWidgets/QStyleFactory> #include <QtWidgets/QVBoxLayout> +#include <QtGui/QPainterPath> #include <QtGui/QScreen> #include <QtTest/QtTest> diff --git a/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index baccf7bff8..ff01810938 100644 --- a/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -28,6 +28,7 @@ #include <QtTest/QtTest> +#include <QtGui/QPainterPath> #include <QtWidgets/qgraphicsscene.h> #include <private/qgraphicsscenebsptreeindex_p.h> #include <private/qgraphicssceneindex_p.h> diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp index bd470dbcfc..297e83421b 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp @@ -30,6 +30,7 @@ #include <QtCore/QRectF> #include <QtGui/QTransform> #include <QtGui/QGuiApplication> +#include <QtGui/QPainterPath> #include <QtGui/QScreen> #include <QtWidgets/QStyle> #include <QtWidgets/QStyleFactory> diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 1f2060942b..2483d7b5bb 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -58,6 +58,7 @@ #include <qtoolbutton.h> #include <QtCore/qoperatingsystemversion.h> #include <QtGui/qpaintengine.h> +#include <QtGui/qpainterpath.h> #include <QtGui/qbackingstore.h> #include <QtGui/qguiapplication.h> #include <QtGui/qpa/qplatformwindow.h> |