summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorTarja Sundqvist <[email protected]>2025-06-03 13:43:30 +0300
committerTarja Sundqvist <[email protected]>2025-06-03 13:43:30 +0300
commit4a6a9dcc73b82cd49a846d5eadadc1835d7b0ec8 (patch)
tree2f027d908308b8ad503b746cd9012fbc98ea32f2 /tests
parent3fe9e69e4d7510480544f928e8a07f0f110b2181 (diff)
parent5d8e9a8415562ba004b38508d91e1fa0254c17d3 (diff)
Merge tag 'v6.5.6-lts-lgpl' into 6.56.5
Qt 6.5.6-lts-lgpl release
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/cmake/mockplugins/.cmake.conf2
-rw-r--r--tests/auto/cmake/test_generating_cpp_exports/.cmake.conf2
-rw-r--r--tests/auto/cmake/test_static_resources/.cmake.conf2
-rw-r--r--tests/auto/corelib/io/qfile/tst_qfile.cpp5
-rw-r--r--tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp14
-rw-r--r--tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp7
-rw-r--r--tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp44
-rw-r--r--tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.cpp2
-rw-r--r--tests/auto/corelib/plugin/qfactoryloader/plugin2/plugin2.cpp2
-rw-r--r--tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp125
-rw-r--r--tests/auto/corelib/text/qlocale/tst_qlocale.cpp3
-rw-r--r--tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp72
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp2
-rw-r--r--tests/auto/corelib/thread/qmutex/tst_qmutex.cpp2
-rw-r--r--tests/auto/corelib/thread/qthread/tst_qthread.cpp55
-rw-r--r--tests/auto/corelib/tools/qlist/tst_qlist.cpp2
-rw-r--r--tests/auto/corelib/tools/quniquehandle/tst_quniquehandle.cpp2
-rw-r--r--tests/auto/dbus/qdbusmarshall/common.h4
-rw-r--r--tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp11
-rw-r--r--tests/auto/gui/image/qmovie/tst_qmovie.cpp12
-rw-r--r--tests/auto/gui/painting/qpainter/tst_qpainter.cpp11
-rw-r--r--tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp28
-rw-r--r--tests/auto/gui/qvulkan/tst_qvulkan.cpp16
-rw-r--r--tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp39
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp16
-rw-r--r--tests/auto/network/socket/qudpsocket/CMakeLists.txt2
-rw-r--r--tests/auto/network/socket/qudpsocket/test/CMakeLists.txt4
-rw-r--r--tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp75
-rw-r--r--tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp37
-rw-r--r--tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp56
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/BLACKLIST2
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp28
-rw-r--r--tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp1
-rw-r--r--tests/auto/widgets/kernel/qwidget/BLACKLIST2
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp187
-rw-r--r--tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp89
-rw-r--r--tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp37
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp40
-rw-r--r--tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp50
-rw-r--r--tests/baseline/stylesheet/qss/qheaderview/selectedFontWeight.qss16
-rw-r--r--tests/baseline/stylesheet/tst_baseline_stylesheet.cpp19
-rw-r--r--tests/baseline/text/data/colored_list.html68
-rw-r--r--tests/manual/qopenglwidget/openglwidget/main.cpp11
43 files changed, 1019 insertions, 185 deletions
diff --git a/tests/auto/cmake/mockplugins/.cmake.conf b/tests/auto/cmake/mockplugins/.cmake.conf
index 8f509afaa3a..8b61d211171 100644
--- a/tests/auto/cmake/mockplugins/.cmake.conf
+++ b/tests/auto/cmake/mockplugins/.cmake.conf
@@ -1 +1 @@
-set(QT_REPO_MODULE_VERSION "6.5.5")
+set(QT_REPO_MODULE_VERSION "6.5.6")
diff --git a/tests/auto/cmake/test_generating_cpp_exports/.cmake.conf b/tests/auto/cmake/test_generating_cpp_exports/.cmake.conf
index 8f509afaa3a..8b61d211171 100644
--- a/tests/auto/cmake/test_generating_cpp_exports/.cmake.conf
+++ b/tests/auto/cmake/test_generating_cpp_exports/.cmake.conf
@@ -1 +1 @@
-set(QT_REPO_MODULE_VERSION "6.5.5")
+set(QT_REPO_MODULE_VERSION "6.5.6")
diff --git a/tests/auto/cmake/test_static_resources/.cmake.conf b/tests/auto/cmake/test_static_resources/.cmake.conf
index 8f509afaa3a..8b61d211171 100644
--- a/tests/auto/cmake/test_static_resources/.cmake.conf
+++ b/tests/auto/cmake/test_static_resources/.cmake.conf
@@ -1 +1 @@
-set(QT_REPO_MODULE_VERSION "6.5.5")
+set(QT_REPO_MODULE_VERSION "6.5.6")
diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp
index 03bfaa8f368..2ecf0f24eb1 100644
--- a/tests/auto/corelib/io/qfile/tst_qfile.cpp
+++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp
@@ -2673,9 +2673,8 @@ void tst_QFile::socketPair()
void tst_QFile::textFile()
{
- const char *openMode = QOperatingSystemVersion::current().type() != QOperatingSystemVersion::Windows
- ? "w" : "wt";
- StdioFileGuard fs(fopen("writeabletextfile", openMode));
+ // The "t" is ignored everywhere except on Windows
+ StdioFileGuard fs(fopen("writeabletextfile", "wt"));
QVERIFY(fs);
QFile f;
QByteArray part1("This\nis\na\nfile\nwith\nnewlines\n");
diff --git a/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp b/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp
index 227c6260d36..e7a505cfd71 100644
--- a/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp
+++ b/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp
@@ -54,7 +54,7 @@ private slots:
void QTBUG_4796_data();
void QTBUG_4796();
- void QTBUG43352_failedSetPermissions();
+ void nestedTempDirs();
private:
QString m_previousCurrent;
@@ -555,16 +555,18 @@ void tst_QTemporaryDir::QTBUG_4796() // unicode support
cleaner.reset();
}
-void tst_QTemporaryDir::QTBUG43352_failedSetPermissions()
+void tst_QTemporaryDir::nestedTempDirs()
{
- QString path = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + QStringLiteral("/");
- int count = QDir(path).entryList().size();
+ QTemporaryDir parentDir;
+ const QString &parentPath = parentDir.path();
{
- QTemporaryDir dir(path);
+ QTemporaryDir tempdir(parentPath);
}
- QCOMPARE(QDir(path).entryList().size(), count);
+ QDir dir(parentPath);
+ dir.setFilter(QDir::NoDotAndDotDot);
+ QCOMPARE(dir.count(), 0);
}
QTEST_MAIN(tst_QTemporaryDir)
diff --git a/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp b/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp
index 4cc15159e7f..4b502700fd4 100644
--- a/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp
+++ b/tests/auto/corelib/kernel/qmetamethod/tst_qmetamethod.cpp
@@ -22,6 +22,7 @@ private slots:
void comparisonOperators();
void fromSignal();
+ void fromSignalOfNullSignalIsInvalid();
void gadget();
void revision();
@@ -719,6 +720,12 @@ void tst_QMetaMethod::fromSignal()
#undef FROMSIGNAL_HELPER
}
+void tst_QMetaMethod::fromSignalOfNullSignalIsInvalid()
+{
+ constexpr decltype(&QObject::destroyed) ptr = nullptr;
+ QVERIFY(!QMetaMethod::fromSignal(ptr).isValid());
+}
+
class MyGadget {
Q_GADGET
public:
diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
index 09df5d12ed7..fdbf9aca970 100644
--- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
+++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
@@ -107,6 +107,8 @@ private slots:
void propertyAdaptorBinding();
void propertyUpdateViaSignaledProperty();
+
+ void derefFromObserver();
};
void tst_QProperty::functorBinding()
@@ -261,6 +263,7 @@ void tst_QProperty::bindingAfterUse()
void tst_QProperty::bindingFunctionDtorCalled()
{
+ DtorCounter::counter = 0;
DtorCounter dc;
{
QProperty<int> prop;
@@ -2469,6 +2472,47 @@ void tst_QProperty::propertyUpdateViaSignaledProperty()
QCOMPARE(o.bindable2(), 36);
}
+void tst_QProperty::derefFromObserver()
+{
+ int triggered = 0;
+ QProperty<int> source(11);
+
+ DtorCounter::counter = 0;
+ DtorCounter dc;
+
+ QProperty<int> target([&triggered, &source, dc]() mutable {
+ dc.shouldIncrement = true;
+ return ++triggered + source.value();
+ });
+ QCOMPARE(triggered, 1);
+
+ {
+ auto propObserver = std::make_unique<QPropertyObserver>();
+ QPropertyObserverPointer propObserverPtr { propObserver.get() };
+ propObserverPtr.setBindingToNotify(QPropertyBindingPrivate::get(target.binding()));
+
+ QBindingObserverPtr bindingPtr(propObserver.get());
+
+ QCOMPARE(triggered, 1);
+ source = 25;
+ QCOMPARE(triggered, 2);
+ QCOMPARE(target, 27);
+
+ target.setBinding([]() { return 8; });
+ QCOMPARE(target, 8);
+
+ // The QBindingObserverPtr still holds on to the binding.
+ QCOMPARE(dc.counter, 0);
+ }
+
+ // The binding is actually gone now.
+ QCOMPARE(dc.counter, 1);
+
+ source = 26;
+ QCOMPARE(triggered, 2);
+ QCOMPARE(target, 8);
+}
+
QTEST_MAIN(tst_QProperty);
#undef QT_SOURCE_LOCATION_NAMESPACE
diff --git a/tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.cpp b/tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.cpp
index 51825f00175..9e73e84364f 100644
--- a/tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.cpp
+++ b/tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.cpp
@@ -7,3 +7,5 @@ QString Plugin1::pluginName() const
{
return QLatin1String("Plugin1 ok");
}
+
+#include "moc_plugin1.cpp"
diff --git a/tests/auto/corelib/plugin/qfactoryloader/plugin2/plugin2.cpp b/tests/auto/corelib/plugin/qfactoryloader/plugin2/plugin2.cpp
index 88a34ac73e0..552b4dd8103 100644
--- a/tests/auto/corelib/plugin/qfactoryloader/plugin2/plugin2.cpp
+++ b/tests/auto/corelib/plugin/qfactoryloader/plugin2/plugin2.cpp
@@ -7,3 +7,5 @@ QString Plugin2::pluginName() const
{
return QLatin1String("Plugin2 ok");
}
+
+#include "moc_plugin2.cpp"
diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
index aa35468b936..08de2c36356 100644
--- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
+++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
@@ -569,6 +569,12 @@ private slots:
void hasAttribute() const;
void writeWithUtf8Codec() const;
void writeWithStandalone() const;
+ void writeCharacters_data() const;
+ void writeCharacters() const;
+ void writeAttribute_data() const;
+ void writeAttribute() const;
+ void writeBadCharactersUtf8_data() const;
+ void writeBadCharactersUtf8() const;
void entitiesAndWhitespace_1() const;
void entitiesAndWhitespace_2() const;
void testFalsePrematureError() const;
@@ -1368,6 +1374,125 @@ void tst_QXmlStream::writeWithStandalone() const
}
}
+static void writeCharacters_data_common()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("output");
+
+ QTest::newRow("empty") << QString() << QString();
+
+ // invalid content
+ QTest::newRow("null-character") << u"\0"_s << QString();
+ QTest::newRow("vertical-tab") << "\v" << QString();
+ QTest::newRow("form-feed") << "\f" << QString();
+ QTest::newRow("esc") << "\x1f" << QString();
+ QTest::newRow("U+FFFE") << u"\xfffe"_s << QString();
+ QTest::newRow("U+FFFF") << u"\xffff"_s << QString();
+
+ // simple strings
+ QTest::newRow("us-ascii") << "Hello, world" << "Hello, world";
+ QTest::newRow("latin1") << "Bokmål" << "Bokmål";
+ QTest::newRow("nonlatin1") << "Ελληνικά" << "Ελληνικά";
+ QTest::newRow("nonbmp") << u"\U00010000"_s << u"\U00010000"_s;
+
+ // escaped content
+ QTest::newRow("less-than") << "<" << "&lt;";
+ QTest::newRow("greater-than") << ">" << "&gt;";
+ QTest::newRow("ampersand") << "&" << "&amp;";
+ QTest::newRow("quote") << "\"" << "&quot;";
+}
+
+template <typename Execute, typename Transform>
+static void writeCharacters_common(Execute &&exec, Transform &&transform)
+{
+ QFETCH(QString, input);
+ QFETCH(QString, output);
+ QStringView utf16 = input;
+ QByteArray utf8ba = input.toUtf8();
+ QUtf8StringView utf8(utf8ba);
+
+ // may be invalid if input is not Latin1
+ QByteArray l1ba = input.toLatin1();
+ QLatin1StringView l1(l1ba);
+ if (l1 != input)
+ l1 = {};
+
+ auto write = [&](auto input) -> std::optional<QString> {
+ QString result;
+ QXmlStreamWriter writer(&result);
+ writer.writeStartElement("a");
+ exec(writer, input);
+ writer.writeEndElement();
+ if (writer.hasError())
+ return std::nullopt;
+ return result;
+ };
+
+ if (input.isNull() != output.isNull()) {
+ // error
+ QCOMPARE(write(utf16), std::nullopt);
+ QCOMPARE(write(utf8), std::nullopt);
+ if (!l1.isEmpty())
+ QCOMPARE(write(l1), std::nullopt);
+ } else {
+ output = transform(output);
+ QCOMPARE(write(utf16), output);
+ QCOMPARE(write(utf8), output);
+ if (!l1.isEmpty())
+ QCOMPARE(write(l1), output);
+ }
+}
+
+void tst_QXmlStream::writeCharacters_data() const
+{
+ writeCharacters_data_common();
+ QTest::newRow("tab") << "\t" << "\t";
+ QTest::newRow("newline") << "\n" << "\n";
+ QTest::newRow("carriage-return") << "\r" << "\r";
+}
+
+void tst_QXmlStream::writeCharacters() const
+{
+ auto exec = [](QXmlStreamWriter &writer, auto input) {
+ writer.writeCharacters(input);
+ };
+ auto transform = [](auto output) { return "<a>" + output + "</a>"; };
+ writeCharacters_common(exec, transform);
+}
+
+void tst_QXmlStream::writeAttribute_data() const
+{
+ writeCharacters_data_common();
+ QTest::newRow("tab") << "\t" << "&#9;";
+ QTest::newRow("newline") << "\n" << "&#10;";
+ QTest::newRow("carriage-return") << "\r" << "&#13;";
+}
+
+void tst_QXmlStream::writeAttribute() const
+{
+ auto exec = [](QXmlStreamWriter &writer, auto input) {
+ writer.writeAttribute("b", input);
+ };
+ auto transform = [](auto output) { return "<a b=\"" + output + "\"/>"; };
+ writeCharacters_common(exec, transform);
+}
+
+#include "../../io/qurlinternal/utf8data.cpp"
+void tst_QXmlStream::writeBadCharactersUtf8_data() const
+{
+ QTest::addColumn<QByteArray>("input");
+ loadInvalidUtf8Rows();
+}
+
+void tst_QXmlStream::writeBadCharactersUtf8() const
+{
+ QFETCH(QByteArray, input);
+ QString target;
+ QXmlStreamWriter writer(&target);
+ writer.writeTextElement("a", QUtf8StringView(input));
+ QVERIFY(writer.hasError());
+}
+
void tst_QXmlStream::entitiesAndWhitespace_1() const
{
QXmlStreamReader reader(QLatin1String("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\"><test>&extEnt;</test>"));
diff --git a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
index 4829a361b4d..1f17fdccf9f 100644
--- a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
@@ -3627,13 +3627,14 @@ void tst_QLocale::bcp47Name()
#ifdef QT_BUILD_INTERNAL
class MySystemLocale : public QSystemLocale
{
+ Q_DISABLE_COPY_MOVE(MySystemLocale)
public:
MySystemLocale(const QString &locale)
: m_name(locale), m_id(QLocaleId::fromName(locale)), m_locale(locale)
{
}
- QVariant query(QueryType type, QVariant /*in*/) const override
+ QVariant query(QueryType type, QVariant &&/*in*/) const override
{
switch (type) {
case UILanguages:
diff --git a/tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp b/tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp
index f37935f6655..ebe6280385a 100644
--- a/tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp
+++ b/tests/auto/corelib/text/qstringconverter/tst_qstringconverter.cpp
@@ -540,11 +540,10 @@ void tst_QStringConverter::charByCharConsistency_data()
void tst_QStringConverter::charByCharConsistency()
{
- QFETCH(QStringView, source);
- QFETCH(QByteArray, codec);
+ QFETCH(const QStringView, source);
+ QFETCH(const QByteArray, codec);
- {
- QStringEncoder encoder(codec);
+ const auto check = [&](QStringEncoder encoder){
if (!encoder.isValid())
QSKIP("Unsupported codec");
@@ -555,19 +554,28 @@ void tst_QStringConverter::charByCharConsistency()
stepByStepConverted += encoder.encode(codeUnit);
}
QCOMPARE(stepByStepConverted, fullyConverted);
- }
+ };
+
+ check(QStringEncoder(codec));
+ if (QTest::currentTestResolved()) return;
+
+ check(QStringEncoder(codec, QStringConverter::Flag::ConvertInvalidToNull));
+ if (QTest::currentTestResolved()) return;
+
+ // moved codecs also work:
{
- QStringEncoder encoder(codec, QStringConverter::Flag::ConvertInvalidToNull);
+ QStringEncoder dec(codec);
+ check(std::move(dec));
+ }
+ if (QTest::currentTestResolved()) return;
- QByteArray fullyConverted = encoder.encode(source);
- encoder.resetState();
- QByteArray stepByStepConverted;
- for (const auto& codeUnit: source) {
- stepByStepConverted += encoder.encode(codeUnit);
- }
- QCOMPARE(stepByStepConverted, fullyConverted);
+ {
+ QStringEncoder dec(codec, QStringConverter::Flag::ConvertInvalidToNull);
+ check(std::move(dec));
}
+ if (QTest::currentTestResolved()) return;
+
}
void tst_QStringConverter::byteByByteConsistency_data()
@@ -584,11 +592,10 @@ void tst_QStringConverter::byteByByteConsistency_data()
void tst_QStringConverter::byteByByteConsistency()
{
- QFETCH(QByteArray, source);
- QFETCH(QByteArray, codec);
+ QFETCH(const QByteArray, source);
+ QFETCH(const QByteArray, codec);
- {
- QStringDecoder decoder(codec);
+ const auto check = [&](QStringDecoder decoder) {
if (!decoder.isValid())
QSKIP("Unsupported codec");
@@ -601,23 +608,28 @@ void tst_QStringConverter::byteByByteConsistency()
stepByStepConverted += decoder.decode(singleChar);
}
QCOMPARE(stepByStepConverted, fullyConverted);
- }
+ };
+
+ check(QStringDecoder(codec));
+ if (QTest::currentTestResolved()) return;
+
+ check(QStringDecoder(codec, QStringConverter::Flag::ConvertInvalidToNull));
+ if (QTest::currentTestResolved()) return;
+
+ // moved codecs also work:
{
- QStringDecoder decoder(codec, QStringConverter::Flag::ConvertInvalidToNull);
- if (!decoder.isValid())
- QSKIP("Unsupported codec");
+ QStringDecoder dec(codec);
+ check(std::move(dec));
+ }
+ if (QTest::currentTestResolved()) return;
- QString fullyConverted = decoder.decode(source);
- decoder.resetState();
- QString stepByStepConverted;
- for (const auto& byte: source) {
- QByteArray singleChar;
- singleChar.append(byte);
- stepByStepConverted += decoder.decode(singleChar);
- }
- QCOMPARE(stepByStepConverted, fullyConverted);
+ {
+ QStringDecoder dec(codec, QStringConverter::Flag::ConvertInvalidToNull);
+ check(std::move(dec));
}
+ if (QTest::currentTestResolved()) return;
+
}
void tst_QStringConverter::statefulPieceWise()
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index 33f920368e7..d306af4873f 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -3833,7 +3833,7 @@ void tst_QFuture::signalConnect()
{
SenderObject sender;
-#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
+#if defined(Q_CC_MSVC_ONLY) && (Q_CC_MSVC < 1940 || __cplusplus < 202002L)
#define EXPECT_FUTURE_CONNECT_FAIL() QEXPECT_FAIL("", "QTBUG-101761, test fails on Windows/MSVC", Continue)
#else
QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in SenderObject");
diff --git a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
index e4f98608ae4..dd253d1ff6a 100644
--- a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
+++ b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
@@ -61,6 +61,8 @@ static QSemaphore threadsTurn;
enum {
#ifdef Q_OS_WIN
systemTimersResolution = 16,
+#elif defined(Q_OS_QNX)
+ systemTimersResolution = 10,
#else
systemTimersResolution = 1,
#endif
diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
index 1cade32545b..953d81cb1e4 100644
--- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp
+++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
@@ -38,6 +38,10 @@
#include <QtTest/private/qemulationdetector_p.h>
+#include <chrono>
+
+using namespace std::chrono_literals;
+
class tst_QThread : public QObject
{
Q_OBJECT
@@ -51,6 +55,7 @@ private slots:
void setStackSize();
void exit();
void start();
+ void startSlotUsedInStringBasedLookups();
void terminate();
void quit();
void started();
@@ -462,6 +467,56 @@ void tst_QThread::start()
}
}
+class QThreadStarter : public QObject
+{
+ Q_OBJECT
+public:
+ using QObject::QObject;
+Q_SIGNALS:
+ void start(QThread::Priority);
+};
+
+class QThreadSelfStarter : public QThread
+{
+ Q_OBJECT
+public:
+ using QThread::QThread;
+
+ void check()
+ {
+ QVERIFY(connect(this, SIGNAL(starting(Priority)),
+ this, SLOT(start(Priority))));
+ QVERIFY(QMetaObject::invokeMethod(this, "start", Q_ARG(Priority, IdlePriority)));
+ }
+
+Q_SIGNALS:
+ void starting(Priority);
+};
+
+void tst_QThread::startSlotUsedInStringBasedLookups()
+{
+ // QTBUG-124723
+
+ QThread thread;
+ {
+ QThreadStarter starter;
+ QVERIFY(QObject::connect(&starter, SIGNAL(start(QThread::Priority)),
+ &thread, SLOT(start(QThread::Priority))));
+ }
+ {
+ QThreadSelfStarter selfStarter;
+ selfStarter.check();
+ if (QTest::currentTestFailed())
+ return;
+ selfStarter.exit();
+ selfStarter.wait(30s);
+ }
+ QVERIFY(QMetaObject::invokeMethod(&thread, "start",
+ Q_ARG(QThread::Priority, QThread::IdlePriority)));
+ thread.exit();
+ thread.wait(30s);
+}
+
void tst_QThread::terminate()
{
#if defined(Q_OS_ANDROID)
diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp
index 482079b0fea..6dfaea91159 100644
--- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp
+++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp
@@ -9,7 +9,7 @@
#include <qlist.h>
-#if __cplusplus >= 202002L && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE >= 11)
+#ifdef QT_COMPILER_HAS_LWG3346
# if __has_include(<concepts>)
# include <concepts>
# if defined(__cpp_lib_concepts) && __cpp_lib_concepts >= 202002L
diff --git a/tests/auto/corelib/tools/quniquehandle/tst_quniquehandle.cpp b/tests/auto/corelib/tools/quniquehandle/tst_quniquehandle.cpp
index 82fb39ece74..6a750467272 100644
--- a/tests/auto/corelib/tools/quniquehandle/tst_quniquehandle.cpp
+++ b/tests/auto/corelib/tools/quniquehandle/tst_quniquehandle.cpp
@@ -248,7 +248,7 @@ private slots:
{
using Type = int;
- static bool close(Type handle)
+ static bool close(Type)
{
return true;
}
diff --git a/tests/auto/dbus/qdbusmarshall/common.h b/tests/auto/dbus/qdbusmarshall/common.h
index 916370c3773..646c46dde24 100644
--- a/tests/auto/dbus/qdbusmarshall/common.h
+++ b/tests/auto/dbus/qdbusmarshall/common.h
@@ -152,7 +152,9 @@ void commonInit()
qDBusRegisterMetaType<QMap<QDBusObjectPath, QString> >();
qDBusRegisterMetaType<QMap<qlonglong, QDateTime> >();
qDBusRegisterMetaType<QMap<QDBusSignature, QString> >();
+ qDBusRegisterMetaType<QMap<QString, std::pair<int, int>>>();
+ qDBusRegisterMetaType<std::pair<int, int>>();
qDBusRegisterMetaType<MyStruct>();
qDBusRegisterMetaType<MyVariantMapStruct>();
qDBusRegisterMetaType<QList<MyVariantMapStruct> >();
@@ -468,6 +470,8 @@ bool compareToArgument(const QDBusArgument &arg, const QVariant &v2)
return compare<QMap<qlonglong, QDateTime> >(arg, v2);
else if (id == qMetaTypeId<QMap<QDBusSignature, QString> >())
return compare<QMap<QDBusSignature, QString> >(arg, v2);
+ else if (id == qMetaTypeId<QMap<QString, std::pair<int, int>>>())
+ return compare<QMap<QString, std::pair<int, int>>>(arg, v2);
else if (id == qMetaTypeId<QList<QByteArray> >())
return compare<QList<QByteArray> >(arg, v2);
diff --git a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp
index aecc958536b..1c9f16ccfeb 100644
--- a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp
+++ b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp
@@ -475,6 +475,17 @@ void tst_QDBusMarshall::sendMaps_data()
QTest::newRow("gs-map") << QVariant::fromValue(gsmap) << "a{gs}"
<< "[Argument: a{gs} {[Signature: a{gs}] = \"array of dict_entry of (signature, string)\", [Signature: i] = \"int32\", [Signature: s] = \"string\"}]";
+ QMap<QString, std::pair<int, int>> siimap;
+ QTest::newRow("empty-sii-map") << QVariant::fromValue(siimap) << "a{s(ii)}"
+ << "[Argument: a{s(ii)} {}]";
+ siimap["0,0"] = { 0, 0 };
+ siimap["1,-1"] = { 1, -1 };
+ QTest::newRow("sii-map") << QVariant::fromValue(siimap) << "a{s(ii)}"
+ << "[Argument: a{s(ii)} {"
+ "\"0,0\" = [Argument: (ii) 0, 0], "
+ "\"1,-1\" = [Argument: (ii) 1, -1]"
+ "}]";
+
if (fileDescriptorPassing) {
svmap["zzfiledescriptor"] = QVariant::fromValue(QDBusUnixFileDescriptor(fileDescriptorForTest()));
QTest::newRow("sv-map1-fd") << QVariant::fromValue(svmap) << "a{sv}"
diff --git a/tests/auto/gui/image/qmovie/tst_qmovie.cpp b/tests/auto/gui/image/qmovie/tst_qmovie.cpp
index 13014e04daa..ba921a66dc0 100644
--- a/tests/auto/gui/image/qmovie/tst_qmovie.cpp
+++ b/tests/auto/gui/image/qmovie/tst_qmovie.cpp
@@ -36,6 +36,7 @@ private slots:
void playMovie();
void jumpToFrame_data();
void jumpToFrame();
+ void frameDelay();
void changeMovieFile();
#ifndef QT_NO_WIDGETS
void infiniteLoop();
@@ -181,6 +182,17 @@ void tst_QMovie::jumpToFrame()
QCOMPARE(movie.currentFrameNumber(), 0);
}
+void tst_QMovie::frameDelay()
+{
+ QMovie movie(QFINDTESTDATA("animations/comicsecard.gif"));
+ QList<int> frameDelays{ 200, 800, 800, 2000, 2600 };
+ for (int i = 0; i < movie.frameCount(); i++) {
+ movie.jumpToFrame(i);
+ // Processing may have taken a little time, so round to nearest 100ms
+ QCOMPARE(100 * qRound(movie.nextFrameDelay() / 100.0f), frameDelays[i]);
+ }
+}
+
void tst_QMovie::changeMovieFile()
{
QMovie movie(QFINDTESTDATA("animations/comicsecard.gif"));
diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
index 92c3ea4a5a7..65812643f5f 100644
--- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
+++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
@@ -62,6 +62,7 @@ private slots:
#endif
void drawPixmapFragments();
void drawPixmapNegativeScale();
+ void drawPixmapRounding();
void drawLine_data();
void drawLine();
@@ -747,6 +748,16 @@ void tst_QPainter::drawPixmapNegativeScale()
QVERIFY(resultImage.pixel(12, 8) == qRgba(0, 0, 0, 255)); // and right strip is now black
}
+void tst_QPainter::drawPixmapRounding()
+{
+ // Just test that we don't assert
+ QBitmap bm(8, 8);
+ QImage out(64, 64, QImage::Format_RGB32);
+ QPainter p(&out);
+ qreal y = 26.499999999999996;
+ p.drawPixmap(QPointF(0, y), bm);
+}
+
void tst_QPainter::drawLine_data()
{
QTest::addColumn<QLine>("line");
diff --git a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
index 20ee6e07c78..cb03d6cf469 100644
--- a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
+++ b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
@@ -81,6 +81,8 @@ private slots:
void intersectionEquality();
void intersectionPointOnEdge();
+
+ void boundsAtStartPoint();
};
void tst_QPainterPath::cleanupTestCase()
@@ -1442,6 +1444,32 @@ void tst_QPainterPath::intersectionPointOnEdge()
QVERIFY(p.intersects(r));
}
+void tst_QPainterPath::boundsAtStartPoint()
+{
+ const QPointF startPoint(10, 10);
+ const QPainterPath constructedPath(startPoint);
+ {
+ const auto boundingRect = constructedPath.boundingRect();
+ const auto topLeft = boundingRect.topLeft();
+ QCOMPARE(topLeft, startPoint);
+ QCOMPARE(topLeft, constructedPath.elementAt(0));
+ QCOMPARE(boundingRect, constructedPath.controlPointRect());
+ }
+
+ QPainterPath defaultPath;
+ defaultPath.moveTo(startPoint);
+ {
+ const auto boundingRect = defaultPath.boundingRect();
+ const auto topLeft = boundingRect.topLeft();
+ QCOMPARE(topLeft, startPoint);
+ QCOMPARE(topLeft, defaultPath.elementAt(0));
+ QCOMPARE(boundingRect, defaultPath.controlPointRect());
+ }
+
+ QCOMPARE(constructedPath.boundingRect(), defaultPath.boundingRect());
+ QCOMPARE(constructedPath.controlPointRect(), defaultPath.controlPointRect());
+}
+
QTEST_APPLESS_MAIN(tst_QPainterPath)
#include "tst_qpainterpath.moc"
diff --git a/tests/auto/gui/qvulkan/tst_qvulkan.cpp b/tests/auto/gui/qvulkan/tst_qvulkan.cpp
index 0afebfba28f..1be39f77a7d 100644
--- a/tests/auto/gui/qvulkan/tst_qvulkan.cpp
+++ b/tests/auto/gui/qvulkan/tst_qvulkan.cpp
@@ -27,10 +27,6 @@ private slots:
void tst_QVulkan::vulkanInstance()
{
-#ifdef Q_OS_ANDROID
- if (QNativeInterface::QAndroidApplication::sdkVersion() >= 31)
- QSKIP("Fails on Android 12 (QTBUG-111236)");
-#endif
QVulkanInstance inst;
if (!inst.create())
QSKIP("Vulkan init failed; skip");
@@ -67,10 +63,6 @@ void tst_QVulkan::vulkanInstance()
void tst_QVulkan::vulkanCheckSupported()
{
-#ifdef Q_OS_ANDROID
- if (QNativeInterface::QAndroidApplication::sdkVersion() >= 31)
- QSKIP("Fails on Android 12 (QTBUG-111236)");
-#endif
// Test the early calls to supportedLayers/extensions/apiVersion that need
// the library and some basics, but do not initialize the instance.
QVulkanInstance inst;
@@ -214,10 +206,6 @@ void tst_QVulkan::vulkanPlainWindow()
void tst_QVulkan::vulkanVersionRequest()
{
-#ifdef Q_OS_ANDROID
- if (QNativeInterface::QAndroidApplication::sdkVersion() >= 31)
- QSKIP("Fails on Android 12 (QTBUG-111236)");
-#endif
QVulkanInstance inst;
if (!inst.create())
QSKIP("Vulkan init failed; skip");
@@ -264,10 +252,6 @@ static void waitForUnexposed(QWindow *w)
void tst_QVulkan::vulkanWindow()
{
-#ifdef Q_OS_ANDROID
- if (QNativeInterface::QAndroidApplication::sdkVersion() >= 31)
- QSKIP("Fails on Android 12 (QTBUG-111236)");
-#endif
QVulkanInstance inst;
if (!inst.create())
QSKIP("Vulkan init failed; skip");
diff --git a/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp b/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp
index 43cb6667ec5..d729cfbf6ee 100644
--- a/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp
+++ b/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp
@@ -56,9 +56,6 @@ private slots:
void shapingDisabledDevanagari();
void shapingDisabledLatin();
-
- void privateUseArea();
-
private:
bool haveTestFonts;
};
@@ -1316,41 +1313,5 @@ void tst_QTextScriptEngine::shapingDisabledDevanagari()
QCOMPARE(noShapingRuns.first().glyphIndexes().size(), normalRuns.first().glyphIndexes().size());
}
-void tst_QTextScriptEngine::privateUseArea()
-{
- QString privateUseAreaString = QString::fromUtf8("");
-
- QFont font;
- QList<QGlyphRun> withFontMerging;
- {
- QTextLayout layout;
- layout.setText(privateUseAreaString);
- layout.setFont(font);
- layout.beginLayout();
- layout.createLine();
- layout.endLayout();
-
- withFontMerging = layout.glyphRuns();
- }
-
- font.setStyleStrategy(QFont::NoFontMerging);
- QList<QGlyphRun> withoutFontMerging;
- {
- QTextLayout layout;
- layout.setText(privateUseAreaString);
- layout.setFont(font);
- layout.beginLayout();
- layout.createLine();
- layout.endLayout();
-
- withoutFontMerging = layout.glyphRuns();
- }
-
- QCOMPARE(withFontMerging.size(), withoutFontMerging.size());
-
- for (int i = 0; i < withFontMerging.size(); ++i)
- QCOMPARE(withFontMerging.at(i).glyphIndexes(), withoutFontMerging.at(i).glyphIndexes());
-}
-
QTEST_MAIN(tst_QTextScriptEngine)
#include "tst_qtextscriptengine.moc"
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 05ee120f970..36fe6aaef8f 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -6054,14 +6054,6 @@ struct QThreadCleanup
}
};
-struct QDeleteLaterCleanup
-{
- static inline void cleanup(QObject *o)
- {
- o->deleteLater();
- }
-};
-
#if QT_CONFIG(networkproxy)
void tst_QNetworkReply::httpProxyCommandsSynchronous()
{
@@ -6073,7 +6065,7 @@ void tst_QNetworkReply::httpProxyCommandsSynchronous()
// the server thread, because the client is never returning to the
// event loop
QScopedPointer<QThread, QThreadCleanup> serverThread(new QThread);
- QScopedPointer<MiniHttpServer, QDeleteLaterCleanup> proxyServer(new MiniHttpServer(responseToSend, false, serverThread.data()));
+ QScopedPointer<MiniHttpServer, QScopedPointerDeleteLater> proxyServer(new MiniHttpServer(responseToSend, false, serverThread.data()));
QNetworkProxy proxy(QNetworkProxy::HttpProxy, "127.0.0.1", proxyServer->serverPort());
manager.setProxy(proxy);
@@ -8276,7 +8268,7 @@ void tst_QNetworkReply::synchronousAuthenticationCache()
// the server thread, because the client is never returning to the
// event loop
QScopedPointer<QThread, QThreadCleanup> serverThread(new QThread);
- QScopedPointer<MiniHttpServer, QDeleteLaterCleanup> server(new MiniAuthServer(serverThread.data()));
+ QScopedPointer<MiniHttpServer, QScopedPointerDeleteLater> server(new MiniAuthServer(serverThread.data()));
server->doClose = true;
//1) URL without credentials, we are not authenticated
@@ -8436,9 +8428,9 @@ void tst_QNetworkReply::emitErrorForAllReplies() // QTBUG-36890
for (int a = 0; a < urls.size(); ++a) {
QVERIFY(replies.at(a)->isFinished());
QCOMPARE(errorSpies.at(a)->size(), 1);
- errorSpies.at(a)->deleteLater();
+ delete errorSpies.at(a);
QCOMPARE(finishedSpies.at(a)->size(), 1);
- finishedSpies.at(a)->deleteLater();
+ delete finishedSpies.at(a);
replies.at(a)->deleteLater();
}
}
diff --git a/tests/auto/network/socket/qudpsocket/CMakeLists.txt b/tests/auto/network/socket/qudpsocket/CMakeLists.txt
index 4d81f852d7b..8b00b9937e1 100644
--- a/tests/auto/network/socket/qudpsocket/CMakeLists.txt
+++ b/tests/auto/network/socket/qudpsocket/CMakeLists.txt
@@ -1,5 +1,5 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-add_subdirectory(test)
add_subdirectory(clientserver)
+add_subdirectory(test)
diff --git a/tests/auto/network/socket/qudpsocket/test/CMakeLists.txt b/tests/auto/network/socket/qudpsocket/test/CMakeLists.txt
index 550ea534388..69b62c2f9fa 100644
--- a/tests/auto/network/socket/qudpsocket/test/CMakeLists.txt
+++ b/tests/auto/network/socket/qudpsocket/test/CMakeLists.txt
@@ -14,3 +14,7 @@ qt_internal_add_test(tst_qudpsocket
Qt::TestPrivate
QT_TEST_SERVER_LIST "danted" "echo"
)
+
+if(QT_FEATURE_process)
+ add_dependencies(tst_qudpsocket clientserver)
+endif()
diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
index 4380433899e..d33fd661d3f 100644
--- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
+++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
@@ -11,6 +11,7 @@
#endif
#include <QScopeGuard>
#include <QVersionNumber>
+#include <QSemaphore>
#include <qcoreapplication.h>
#include <qfileinfo.h>
@@ -103,6 +104,8 @@ private slots:
void asyncReadDatagram();
void writeInHostLookupState();
+ void readyReadConnectionThrottling();
+
protected slots:
void empty_readyReadSlot();
void empty_connectedSlot();
@@ -1908,5 +1911,77 @@ void tst_QUdpSocket::writeInHostLookupState()
QVERIFY(!socket.putChar('0'));
}
+void tst_QUdpSocket::readyReadConnectionThrottling()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ // QTBUG-105871:
+ // We have some signal/slot connection throttling in QAbstractSocket, but it
+ // was caring about the bytes, not about the datagrams.
+ // Test that we don't disable read notifications until we have at least one
+ // datagram available. Otherwise our good users who use the datagram APIs
+ // can get into scenarios where they no longer get the readyRead signal
+ // unless they call a read function once in a while.
+
+ QUdpSocket receiver;
+ QVERIFY(receiver.bind(QHostAddress(QHostAddress::LocalHost), 0));
+
+ QSemaphore semaphore;
+
+ // Repro-ing deterministically eludes me, so we are bruteforcing it:
+ // The thread acts as a remote sender, flooding the receiver with datagrams,
+ // and at some point the receiver would get into the broken state mentioned
+ // earlier.
+ std::unique_ptr<QThread> thread(QThread::create([&semaphore, port = receiver.localPort()]() {
+ QUdpSocket sender;
+ sender.connectToHost(QHostAddress(QHostAddress::LocalHost), port);
+ QCOMPARE(sender.state(), QUdpSocket::ConnectedState);
+
+ constexpr qsizetype PayloadSize = 242;
+ const QByteArray payload(PayloadSize, 'a');
+
+ semaphore.acquire(); // Wait for main thread to be ready
+ while (true) {
+ // We send 100 datagrams at a time, then sleep.
+ // This is mostly to let the main thread catch up between bursts so
+ // it doesn't get stuck in the loop.
+ for (int i = 0; i < 100; ++i) {
+ [[maybe_unused]]
+ qsizetype sent = sender.write(payload);
+ Q_ASSERT(sent > 0);
+ }
+ if (QThread::currentThread()->isInterruptionRequested())
+ break;
+ QThread::msleep(20);
+ }
+ }));
+ thread->start();
+ auto threadStopAndWaitGuard = qScopeGuard([&thread] {
+ thread->requestInterruption();
+ thread->quit();
+ thread->wait();
+ });
+
+ qsizetype count = 0;
+ QObject::connect(&receiver, &QUdpSocket::readyRead, &receiver,
+ [&] {
+ while (receiver.hasPendingDatagrams()) {
+ receiver.readDatagram(nullptr, 0);
+ ++count;
+ }
+ // If this prints `false, xxxx` we were pretty much guaranteed
+ // that we would not get called again:
+ // qDebug() << receiver.hasPendingDatagrams() << receiver.bytesAvailable();
+ },
+ Qt::QueuedConnection);
+
+ semaphore.release();
+ constexpr qsizetype MaxCount = 500;
+ QVERIFY2(QTest::qWaitFor([&] { return count >= MaxCount; }, 10'000),
+ QByteArray::number(count).constData());
+}
+
QTEST_MAIN(tst_QUdpSocket)
#include "tst_qudpsocket.moc"
diff --git a/tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp b/tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp
index 8b0319679fb..ecbe5c7576e 100644
--- a/tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp
+++ b/tests/auto/testlib/qsignalspy/tst_qsignalspy.cpp
@@ -6,9 +6,10 @@
#include <QSignalSpy>
#include <QTimer>
-
#include <qdatetime.h>
+using namespace Qt::StringLiterals;
+
class tst_QSignalSpy : public QObject
{
Q_OBJECT
@@ -48,6 +49,8 @@ private slots:
void spyOnMetaMethod_invalid();
void spyOnMetaMethod_invalid_data();
+
+ void signalSpyDoesNotRaceOnCrossThreadSignal();
};
struct CustomType {};
@@ -460,30 +463,62 @@ void tst_QSignalSpy::spyOnMetaMethod()
Q_DECLARE_METATYPE(QMetaMethod);
void tst_QSignalSpy::spyOnMetaMethod_invalid()
{
+ QFETCH(const QByteArray, message);
QFETCH(QObject*, object);
QFETCH(QMetaMethod, signal);
+ QTest::ignoreMessage(QtWarningMsg, message.data());
QSignalSpy spy(object, signal);
QVERIFY(!spy.isValid());
}
void tst_QSignalSpy::spyOnMetaMethod_invalid_data()
{
+ QTest::addColumn<QByteArray>("message");
QTest::addColumn<QObject*>("object");
QTest::addColumn<QMetaMethod>("signal");
QTest::addRow("Invalid object")
+ << "QSignalSpy: Cannot spy on a null object"_ba
<< static_cast<QObject*>(nullptr)
<< QMetaMethod();
QTest::addRow("Empty signal")
+ << "QSignalSpy: Not a valid signal: ''"_ba
<< new QObject(this)
<< QMetaMethod();
QTest::addRow("Method is not a signal")
+ << "QSignalSpy: Not a valid signal: 'deleteLater()'"_ba
<< new QObject(this)
<< QObject::staticMetaObject.method(QObject::staticMetaObject.indexOfMethod("deleteLater()"));
}
+class EmitSignal_Thread : public QThread
+{
+ Q_OBJECT
+public:
+ void run() override
+ {
+ emit valueChanged(42, u"is the answer"_s);
+ }
+
+Q_SIGNALS:
+ void valueChanged(int value, const QString &str);
+};
+
+void tst_QSignalSpy::signalSpyDoesNotRaceOnCrossThreadSignal()
+{
+ EmitSignal_Thread thread;
+ QSignalSpy valueChangedSpy(&thread, &EmitSignal_Thread::valueChanged);
+ QVERIFY(valueChangedSpy.isValid());
+
+ thread.start();
+ QVERIFY(valueChangedSpy.wait(5000));
+ QCOMPARE(valueChangedSpy[0][0].toInt(), 42);
+ QCOMPARE(valueChangedSpy[0][1].toString(), u"is the answer"_s);
+ QVERIFY(thread.wait(5000));
+}
+
QTEST_MAIN(tst_QSignalSpy)
#include "tst_qsignalspy.moc"
diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
index 02e3cfd05a0..158081fa69b 100644
--- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
+++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
@@ -60,6 +60,8 @@ private slots:
void hideNativeByDestruction();
+ void explicitDoneAfterButtonClicked();
+
void cleanup();
};
@@ -435,7 +437,7 @@ void tst_QMessageBox::shortcut()
msgBox.addButton("&Maybe", QMessageBox::YesRole);
ExecCloseHelper closeHelper;
closeHelper.start(Qt::Key_M, &msgBox);
- QCOMPARE(msgBox.exec(), 2);
+ QCOMPARE(msgBox.exec(), 4);
}
#endif
@@ -514,7 +516,7 @@ QT_WARNING_DISABLE_DEPRECATED
// the button text versions
closeHelper.start(Qt::Key_Enter);
ret = QMessageBox::information(nullptr, "title", "text", "Yes", "No", QString(), 1);
- COMPARE(ret, 1);
+ COMPARE(ret, 3); // Custom button opaque result
QVERIFY(closeHelper.done());
if (0) { // don't run these tests since the dialog won't close!
@@ -555,9 +557,9 @@ void tst_QMessageBox::instanceSourceCompat()
#ifndef Q_OS_MAC
// mnemonics are not used on OS X
closeHelper.start(QKeyCombination(Qt::ALT | Qt::Key_R).toCombined(), &mb);
- QCOMPARE(mb.exec(), 0);
+ QCOMPARE(mb.exec(), 2);
closeHelper.start(QKeyCombination(Qt::ALT | Qt::Key_Z).toCombined(), &mb);
- QCOMPARE(mb.exec(), 1);
+ QCOMPARE(mb.exec(), 3);
#endif
}
@@ -818,5 +820,51 @@ void tst_QMessageBox::hideNativeByDestruction()
QVERIFY(QTest::qWaitFor(windowActive));
}
+void tst_QMessageBox::explicitDoneAfterButtonClicked()
+{
+ QMessageBox msgBox;
+ auto *standardButton = msgBox.addButton(QMessageBox::Ok);
+ auto *customButton = msgBox.addButton("Custom", QMessageBox::RejectRole);
+
+ QSignalSpy acceptedSpy(&msgBox, &QDialog::accepted);
+ QSignalSpy rejectedSpy(&msgBox, &QDialog::rejected);
+
+ msgBox.setDefaultButton(standardButton);
+ ExecCloseHelper closeHelper;
+ closeHelper.start(Qt::Key_Enter, &msgBox);
+ msgBox.exec();
+ QCOMPARE(msgBox.clickedButton(), standardButton);
+ QCOMPARE(msgBox.result(), QMessageBox::Ok);
+ QCOMPARE(acceptedSpy.size(), 1);
+ QCOMPARE(rejectedSpy.size(), 0);
+
+ msgBox.accept();
+ QCOMPARE(msgBox.result(), QDialog::Accepted);
+ QCOMPARE(acceptedSpy.size(), 2);
+ QCOMPARE(rejectedSpy.size(), 0);
+ msgBox.reject();
+ QCOMPARE(msgBox.result(), QDialog::Rejected);
+ QCOMPARE(acceptedSpy.size(), 2);
+ QCOMPARE(rejectedSpy.size(), 1);
+
+ msgBox.setDefaultButton(customButton);
+ closeHelper.start(Qt::Key_Enter, &msgBox);
+ msgBox.exec();
+ QCOMPARE(msgBox.clickedButton(), customButton);
+ QVERIFY(msgBox.result() != QDialog::Accepted);
+ QVERIFY(msgBox.result() != QDialog::Rejected);
+ QCOMPARE(acceptedSpy.size(), 2);
+ QCOMPARE(rejectedSpy.size(), 2);
+
+ msgBox.accept();
+ QCOMPARE(msgBox.result(), QDialog::Accepted);
+ QCOMPARE(acceptedSpy.size(), 3);
+ QCOMPARE(rejectedSpy.size(), 2);
+ msgBox.reject();
+ QCOMPARE(msgBox.result(), QDialog::Rejected);
+ QCOMPARE(acceptedSpy.size(), 3);
+ QCOMPARE(rejectedSpy.size(), 3);
+}
+
QTEST_MAIN(tst_QMessageBox)
#include "tst_qmessagebox.moc"
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/BLACKLIST b/tests/auto/widgets/itemviews/qabstractitemview/BLACKLIST
index c1688a7627e..778a25b2e46 100644
--- a/tests/auto/widgets/itemviews/qabstractitemview/BLACKLIST
+++ b/tests/auto/widgets/itemviews/qabstractitemview/BLACKLIST
@@ -1,2 +1,4 @@
+[focusNextOnHide]
+wayland
[selectionAutoScrolling]
wayland
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
index 30b9e9c4b28..8479e08b38f 100644
--- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
+++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
@@ -150,6 +150,7 @@ private slots:
void testSpinBoxAsEditor_data();
void testSpinBoxAsEditor();
void removeIndexWhileEditing();
+ void focusNextOnHide();
private:
static QAbstractItemView *viewFromString(const QByteArray &viewType, QWidget *parent = nullptr)
@@ -3523,5 +3524,32 @@ void tst_QAbstractItemView::removeIndexWhileEditing()
}
}
+void tst_QAbstractItemView::focusNextOnHide()
+{
+ QWidget widget;
+ QTableWidget table(10, 10);
+ table.setTabKeyNavigation(true);
+ QLineEdit lineEdit;
+
+ QHBoxLayout layout;
+ layout.addWidget(&table);
+ layout.addWidget(&lineEdit);
+ widget.setLayout(&layout);
+
+ widget.setTabOrder(&table, &lineEdit);
+
+ widget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&widget));
+
+ QVERIFY(table.hasFocus());
+ QCOMPARE(table.currentIndex(), table.model()->index(0, 0));
+ QTest::keyPress(&table, Qt::Key_Tab);
+ QCOMPARE(table.currentIndex(), table.model()->index(0, 1));
+
+ table.hide();
+ QCOMPARE(table.currentIndex(), table.model()->index(0, 1));
+ QVERIFY(lineEdit.hasFocus());
+}
+
QTEST_MAIN(tst_QAbstractItemView)
#include "tst_qabstractitemview.moc"
diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
index bdfa7ab04dc..5872da6d4f3 100644
--- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
+++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
@@ -4922,6 +4922,7 @@ void tst_QTableView::resetDefaultSectionSize()
view.verticalHeader()->resetDefaultSectionSize();
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
+ QEXPECT_FAIL("", "Reverted fix for QTBUG-116013 due to QTBUG-122109", Continue);
QCOMPARE(view.verticalHeader()->logicalIndexAt(9, 45), 1);
}
diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST
index 00b1248d5d9..2198f8771fa 100644
--- a/tests/auto/widgets/kernel/qwidget/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST
@@ -44,8 +44,6 @@ android
android
[optimizedResize_topLevel]
android
-[render]
-wayland
[hoverPosition]
macos-14 x86
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index cbada55a4a6..456a1f035b7 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -434,6 +434,9 @@ private slots:
void setVisibleDuringDestruction();
+ void reparentWindowHandles_data();
+ void reparentWindowHandles();
+
private:
const QString m_platform;
QSize m_testWidgetSize;
@@ -2230,6 +2233,13 @@ void tst_QWidget::tabOrderWithProxy()
QVERIFY(firstEdit->hasFocus());
}
+static QString focusWidgetName()
+{
+ return QApplication::focusWidget() != nullptr
+ ? QApplication::focusWidget()->objectName()
+ : QStringLiteral("No focus widget");
+}
+
void tst_QWidget::tabOrderWithProxyDisabled()
{
Container container;
@@ -2262,23 +2272,23 @@ void tst_QWidget::tabOrderWithProxyDisabled()
QSKIP("Window failed to activate, skipping test");
QVERIFY2(lineEdit1.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
container.tab();
QVERIFY2(!lineEdit2.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
QVERIFY2(lineEdit3.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
container.tab();
QVERIFY2(lineEdit1.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
container.backTab();
QVERIFY2(lineEdit3.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
container.backTab();
QVERIFY2(!lineEdit2.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
QVERIFY2(lineEdit1.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
}
//#define DEBUG_FOCUS_CHAIN
@@ -2592,23 +2602,23 @@ void tst_QWidget::tabOrderWithCompoundWidgetsNoFocusPolicy()
QSKIP("Window failed to activate, skipping test");
QVERIFY2(spinbox1.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
container.tab();
QVERIFY2(!spinbox2.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
QVERIFY2(spinbox3.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
container.tab();
QVERIFY2(spinbox1.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
container.backTab();
QVERIFY2(spinbox3.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
container.backTab();
QVERIFY2(!spinbox2.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
QVERIFY2(spinbox1.hasFocus(),
- qPrintable(QApplication::focusWidget()->objectName()));
+ qPrintable(focusWidgetName()));
}
void tst_QWidget::tabOrderNoChange()
@@ -13393,5 +13403,154 @@ void tst_QWidget::setVisibleDuringDestruction()
QTRY_COMPARE(signalSpy.count(), 4);
}
+void tst_QWidget::reparentWindowHandles_data()
+{
+ QTest::addColumn<int>("stage");
+ QTest::addRow("reparent child") << 1;
+ QTest::addRow("top level to child") << 2;
+ QTest::addRow("transient parent") << 3;
+ QTest::addRow("window container") << 4;
+}
+
+void tst_QWidget::reparentWindowHandles()
+{
+ const bool nativeSiblingsOriginal = qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
+ qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
+ auto nativeSiblingGuard = qScopeGuard([&]{
+ qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, nativeSiblingsOriginal);
+ });
+
+ QFETCH(int, stage);
+
+ switch (stage) {
+ case 1: {
+ // Reparent child widget
+
+ QWidget topLevel;
+ topLevel.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(topLevel.windowHandle());
+ QPointer<QWidget> child = new QWidget(&topLevel);
+ child->setAttribute(Qt::WA_DontCreateNativeAncestors);
+ child->setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(child->windowHandle());
+
+ QWidget anotherTopLevel;
+ anotherTopLevel.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(anotherTopLevel.windowHandle());
+ QPointer<QWidget> intermediate = new QWidget(&anotherTopLevel);
+ QPointer<QWidget> leaf = new QWidget(intermediate);
+ leaf->setAttribute(Qt::WA_DontCreateNativeAncestors);
+ leaf->setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(leaf->windowHandle());
+ QVERIFY(!intermediate->windowHandle());
+
+ // Reparenting a native widget should reparent the QWindow
+ child->setParent(leaf);
+ QCOMPARE(child->windowHandle()->parent(), leaf->windowHandle());
+ QCOMPARE(child->windowHandle()->transientParent(), nullptr);
+ QVERIFY(!intermediate->windowHandle());
+
+ // So should reparenting a non-native widget with native children
+ intermediate->setParent(&topLevel);
+ QVERIFY(!intermediate->windowHandle());
+ QCOMPARE(leaf->windowHandle()->parent(), topLevel.windowHandle());
+ QCOMPARE(leaf->windowHandle()->transientParent(), nullptr);
+ QCOMPARE(child->windowHandle()->parent(), leaf->windowHandle());
+ QCOMPARE(child->windowHandle()->transientParent(), nullptr);
+ }
+ break;
+ case 2: {
+ // Top level to child
+
+ QWidget topLevel;
+ topLevel.setAttribute(Qt::WA_NativeWindow);
+
+ // A regular top level loses its nativeness
+ QPointer<QWidget> regularToplevel = new QWidget;
+ regularToplevel->show();
+ QVERIFY(QTest::qWaitForWindowExposed(regularToplevel));
+ QVERIFY(regularToplevel->windowHandle());
+ regularToplevel->setParent(&topLevel);
+ QVERIFY(!regularToplevel->windowHandle());
+
+ // A regular top level loses its nativeness
+ QPointer<QWidget> regularToplevelWithNativeChildren = new QWidget;
+ QPointer<QWidget> nativeChild = new QWidget(regularToplevelWithNativeChildren);
+ nativeChild->setAttribute(Qt::WA_DontCreateNativeAncestors);
+ nativeChild->setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(nativeChild->windowHandle());
+ regularToplevelWithNativeChildren->show();
+ QVERIFY(QTest::qWaitForWindowExposed(regularToplevelWithNativeChildren));
+ QVERIFY(regularToplevelWithNativeChildren->windowHandle());
+ regularToplevelWithNativeChildren->setParent(&topLevel);
+ QVERIFY(!regularToplevelWithNativeChildren->windowHandle());
+ // But the native child does not
+ QVERIFY(nativeChild->windowHandle());
+ QCOMPARE(nativeChild->windowHandle()->parent(), topLevel.windowHandle());
+
+ // An explicitly native top level keeps its nativeness, and the window handle moves
+ QPointer<QWidget> nativeTopLevel = new QWidget;
+ nativeTopLevel->setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(nativeTopLevel->windowHandle());
+ nativeTopLevel->setParent(&topLevel);
+ QVERIFY(nativeTopLevel->windowHandle());
+ QCOMPARE(nativeTopLevel->windowHandle()->parent(), topLevel.windowHandle());
+ }
+ break;
+ case 3: {
+ // Transient parent
+
+ QWidget topLevel;
+ topLevel.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(topLevel.windowHandle());
+ QPointer<QWidget> child = new QWidget(&topLevel);
+ child->setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(child->windowHandle());
+
+ QWidget anotherTopLevel;
+ anotherTopLevel.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(anotherTopLevel.windowHandle());
+
+ // Make transient child of top level
+ anotherTopLevel.setParent(&topLevel, Qt::Window);
+ QCOMPARE(anotherTopLevel.windowHandle()->parent(), nullptr);
+ QCOMPARE(anotherTopLevel.windowHandle()->transientParent(), topLevel.windowHandle());
+
+ // Make transient child of child
+ anotherTopLevel.setParent(child, Qt::Window);
+ QCOMPARE(anotherTopLevel.windowHandle()->parent(), nullptr);
+ QCOMPARE(anotherTopLevel.windowHandle()->transientParent(), topLevel.windowHandle());
+ }
+ break;
+ case 4: {
+ // Window container
+
+ QWidget topLevel;
+ topLevel.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(topLevel.windowHandle());
+
+ QPointer<QWidget> child = new QWidget(&topLevel);
+ QVERIFY(!child->windowHandle());
+
+ QWindow *window = new QWindow;
+ QWidget *container = QWidget::createWindowContainer(window);
+ container->setParent(child);
+ topLevel.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+ QCOMPARE(window->parent(), topLevel.windowHandle());
+
+ QWidget anotherTopLevel;
+ anotherTopLevel.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(anotherTopLevel.windowHandle());
+
+ child->setParent(&anotherTopLevel);
+ QCOMPARE(window->parent(), anotherTopLevel.windowHandle());
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+}
+
QTEST_MAIN(tst_QWidget)
#include "tst_qwidget.moc"
diff --git a/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp b/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp
index f53d5aeb050..96a342eb6ba 100644
--- a/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp
+++ b/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp
@@ -75,8 +75,11 @@ public:
const auto type = event->type();
if (type == QEvent::WindowActivate || type == QEvent::WindowDeactivate)
return true;
+ if (type == QEvent::UpdateRequest)
+ ++updateRequests;
return QWidget::event(event);
}
+ int updateRequests = 0;
protected:
void paintEvent(QPaintEvent *event) override
@@ -254,6 +257,8 @@ private slots:
void opaqueChildren();
void staticContents();
void scroll();
+ void paintOnScreenUpdates();
+
#if defined(QT_BUILD_INTERNAL)
void scrollWithOverlap();
void overlappedRegion();
@@ -479,6 +484,90 @@ void tst_QWidgetRepaintManager::scroll()
QCOMPARE(widget.takePaintedRegions(), QRegion());
}
+class PaintOnScreenWidget : public TestWidget
+{
+public:
+ using TestWidget::TestWidget;
+
+ // Explicit override to prevent noPaintOnScreen on Windows
+ QPaintEngine *paintEngine() const override
+ {
+ return nullptr;
+ }
+};
+
+void tst_QWidgetRepaintManager::paintOnScreenUpdates()
+{
+ {
+ TestWidget topLevel;
+ topLevel.setObjectName("TopLevel");
+ topLevel.resize(500, 500);
+ TestWidget renderToTextureWidget(&topLevel);
+ renderToTextureWidget.setObjectName("RenderToTexture");
+ renderToTextureWidget.setGeometry(0, 0, 200, 200);
+ QWidgetPrivate::get(&renderToTextureWidget)->setRenderToTexture();
+
+ PaintOnScreenWidget paintOnScreenWidget(&topLevel);
+ paintOnScreenWidget.setObjectName("PaintOnScreen");
+ paintOnScreenWidget.setGeometry(200, 200, 300, 300);
+
+ topLevel.initialShow();
+
+ // Updating before toggling WA_PaintOnScreen should work fine
+ paintOnScreenWidget.update();
+ paintOnScreenWidget.waitForPainted();
+ QVERIFY(paintOnScreenWidget.waitForPainted());
+
+#ifdef Q_OS_ANDROID
+ QEXPECT_FAIL("", "This test fails on Android", Abort);
+#endif
+ QCOMPARE(paintOnScreenWidget.takePaintedRegions(), paintOnScreenWidget.rect());
+
+ renderToTextureWidget.update();
+ QVERIFY(renderToTextureWidget.waitForPainted());
+ QCOMPARE(renderToTextureWidget.takePaintedRegions(), renderToTextureWidget.rect());
+
+ // Then toggle WA_PaintOnScreen
+ paintOnScreenWidget.setAttribute(Qt::WA_PaintOnScreen);
+
+ // The render-to-texture widget updates fine
+ renderToTextureWidget.update();
+ QVERIFY(renderToTextureWidget.waitForPainted());
+ QCOMPARE(renderToTextureWidget.takePaintedRegions(), renderToTextureWidget.rect());
+
+ // Updating the paint-on-screen texture widget will not result
+ // in a paint event, but should result in an update request.
+ paintOnScreenWidget.updateRequests = 0;
+ paintOnScreenWidget.update();
+ QVERIFY(QTest::qWaitFor([&]{ return paintOnScreenWidget.updateRequests > 0; }));
+
+ // And should not prevent the render-to-texture widget from receiving updates
+ renderToTextureWidget.update();
+ QVERIFY(renderToTextureWidget.waitForPainted());
+ QCOMPARE(renderToTextureWidget.takePaintedRegions(), renderToTextureWidget.rect());
+ }
+
+ {
+ TestWidget paintOnScreenTopLevel;
+ paintOnScreenTopLevel.setObjectName("PaintOnScreenTopLevel");
+ paintOnScreenTopLevel.setAttribute(Qt::WA_PaintOnScreen);
+
+ paintOnScreenTopLevel.initialShow();
+
+ paintOnScreenTopLevel.updateRequests = 0;
+ paintOnScreenTopLevel.update();
+ QVERIFY(QTest::qWaitFor([&]{ return paintOnScreenTopLevel.updateRequests > 0; }));
+
+ // Turn off paint on screen and make it a render-to-texture widget.
+ // This will lead us into a QWidgetRepaintManager::markDirty() code
+ // path that checks updateRequestSent, which is still set from the
+ // update above since paint-on-screen handling doesn't reset it.
+ paintOnScreenTopLevel.setAttribute(Qt::WA_PaintOnScreen, false);
+ QWidgetPrivate::get(&paintOnScreenTopLevel)->setRenderToTexture();
+ paintOnScreenTopLevel.update();
+ QVERIFY(QTest::qWaitFor([&]{ return paintOnScreenTopLevel.updateRequests > 1; }));
+ }
+}
#if defined(QT_BUILD_INTERNAL)
diff --git a/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
index 9f405a8bebe..83abf0e8e36 100644
--- a/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
+++ b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
@@ -6,6 +6,7 @@
#include <QtWidgets/QStyle>
#include <QtWidgets/QLayout>
#include <QtWidgets/QDialog>
+#include <QtWidgets/QLineEdit>
#include <QtGui/QAction>
#include <QtGui/QStyleHints>
#include <qdialogbuttonbox.h>
@@ -82,6 +83,8 @@ private slots:
void task191642_default();
void testDeletedStandardButton();
void automaticDefaultButton();
+ void initialFocus_data();
+ void initialFocus();
private:
qint64 timeStamp;
@@ -958,5 +961,39 @@ void tst_QDialogButtonBox::automaticDefaultButton()
}
}
+void tst_QDialogButtonBox::initialFocus_data()
+{
+ QTest::addColumn<Qt::FocusPolicy>("focusPolicy");
+ QTest::addColumn<bool>("lineEditHasFocus");
+
+ QTest::addRow("TabFocus") << Qt::FocusPolicy::TabFocus << false;
+ QTest::addRow("StrongFocus") << Qt::FocusPolicy::StrongFocus << true;
+ QTest::addRow("NoFocus") << Qt::FocusPolicy::NoFocus << false;
+ QTest::addRow("ClickFocus") << Qt::FocusPolicy::ClickFocus << false;
+ QTest::addRow("WheelFocus") << Qt::FocusPolicy::WheelFocus << false;
+}
+
+void tst_QDialogButtonBox::initialFocus()
+{
+ QFETCH(const Qt::FocusPolicy, focusPolicy);
+ QFETCH(const bool, lineEditHasFocus);
+ QDialog dialog;
+ QVBoxLayout *layout = new QVBoxLayout(&dialog);
+ QLineEdit *lineEdit = new QLineEdit(&dialog);
+ lineEdit->setFocusPolicy(focusPolicy);
+ layout->addWidget(lineEdit);
+ QDialogButtonBox *dialogButtonBox = new QDialogButtonBox(&dialog);
+ layout->addWidget(dialogButtonBox);
+ dialogButtonBox->addButton(QDialogButtonBox::Reset);
+ const auto *firstAcceptButton = dialogButtonBox->addButton(QDialogButtonBox::Ok);
+ dialogButtonBox->addButton(QDialogButtonBox::Cancel);
+ dialog.show();
+ dialog.activateWindow();
+ if (lineEditHasFocus)
+ QTRY_VERIFY(lineEdit->hasFocus());
+ else
+ QTRY_VERIFY(firstAcceptButton->hasFocus());
+}
+
QTEST_MAIN(tst_QDialogButtonBox)
#include "tst_qdialogbuttonbox.moc"
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index df65ac932b4..702fd5aab70 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -1593,44 +1593,14 @@ void tst_QLineEdit::textMask()
QCOMPARE( testWidget->text(), insertString );
}
-class LineEditChangingText : public QLineEdit
-{
- Q_OBJECT
-
-public:
- LineEditChangingText(QWidget *parent) : QLineEdit(parent)
- {
- connect(this, &QLineEdit::textEdited, this, &LineEditChangingText::onTextEdited);
- }
-
-public slots:
- void onTextEdited(const QString &text)
- {
- if (text.length() == 3)
- setText(text + "-");
- }
-};
-
void tst_QLineEdit::setText()
{
QLineEdit *testWidget = ensureTestWidget();
- {
- QSignalSpy editedSpy(testWidget, &QLineEdit::textEdited);
- QSignalSpy changedSpy(testWidget, &QLineEdit::textChanged);
- testWidget->setText("hello");
- QCOMPARE(editedSpy.size(), 0);
- QCOMPARE(changedSpy.value(0).value(0).toString(), QString("hello"));
- }
-
- QTestEventList keys;
- keys.addKeyClick(Qt::Key_A);
- keys.addKeyClick(Qt::Key_B);
- keys.addKeyClick(Qt::Key_C);
-
- LineEditChangingText lineEdit(nullptr);
- keys.simulate(&lineEdit);
- QCOMPARE(lineEdit.text(), "abc-");
- QCOMPARE(lineEdit.cursorPosition(), 4);
+ QSignalSpy editedSpy(testWidget, SIGNAL(textEdited(QString)));
+ QSignalSpy changedSpy(testWidget, SIGNAL(textChanged(QString)));
+ testWidget->setText("hello");
+ QCOMPARE(editedSpy.size(), 0);
+ QCOMPARE(changedSpy.value(0).value(0).toString(), QString("hello"));
}
void tst_QLineEdit::displayText_data()
diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
index b95f2b5216c..394409b97b7 100644
--- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
+++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
@@ -4,6 +4,7 @@
#include <QtOpenGLWidgets/QOpenGLWidget>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QPainter>
+#include <QtGui/QBackingStore>
#include <QtGui/QScreen>
#include <QtGui/QStaticText>
#include <QtWidgets/QGraphicsView>
@@ -21,7 +22,10 @@
#include <private/qopengltextureglyphcache_p.h>
#include <qpa/qplatformintegration.h>
#include <private/qguiapplication_p.h>
+#include <qpa/qplatformbackingstore.h>
#include <qpa/qplatformintegration.h>
+#include <private/qrhi_p.h>
+#include <private/qrhigles2_p.h>
class tst_QOpenGLWidget : public QObject
{
@@ -33,6 +37,9 @@ private slots:
void clearAndGrab();
void clearAndResizeAndGrab();
void createNonTopLevel();
+#if QT_CONFIG(egl)
+ void deviceLoss();
+#endif
void painter();
void reparentToAlreadyCreated();
void reparentToNotYetCreated();
@@ -189,6 +196,45 @@ void tst_QOpenGLWidget::createNonTopLevel()
QVERIFY(QOpenGLContext::currentContext() == glw->context() && glw->context());
}
+#if QT_CONFIG(egl)
+void tst_QOpenGLWidget::deviceLoss()
+{
+ QScopedPointer<QOpenGLWidget> w(new ClearWidget(0, 640, 480));
+
+ w->resize(640, 480);
+ w->show();
+
+ auto rhi = w->backingStore()->handle()->rhi();
+ QNativeInterface::QEGLContext *rhiContext = nullptr;
+ if (rhi->backend() == QRhi::OpenGLES2) {
+ auto rhiHandles = static_cast<const QRhiGles2NativeHandles *>(rhi->nativeHandles());
+ rhiContext = rhiHandles->context->nativeInterface<QNativeInterface::QEGLContext>();
+ }
+ if (!rhiContext)
+ QSKIP("deviceLoss needs EGL");
+
+ QVERIFY(QTest::qWaitForWindowExposed(w.data()));
+
+ QImage image = w->grabFramebuffer();
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.width(), w->width());
+ QCOMPARE(image.height(), w->height());
+ QVERIFY(image.pixel(30, 40) == qRgb(255, 0, 0));
+
+ rhiContext->invalidateContext();
+
+ w->resize(600, 600);
+ QSignalSpy frameSwappedSpy(w.get(), &QOpenGLWidget::resized);
+ QTRY_VERIFY(frameSwappedSpy.size() > 0);
+
+ image = w->grabFramebuffer();
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.width(), w->width());
+ QCOMPARE(image.height(), w->height());
+ QVERIFY(image.pixel(30, 40) == qRgb(255, 0, 0));
+}
+#endif
+
class PainterWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
public:
@@ -281,10 +327,6 @@ void tst_QOpenGLWidget::reparentToNotYetCreated()
void tst_QOpenGLWidget::reparentHidden()
{
-#ifdef Q_OS_ANDROID
- if (QNativeInterface::QAndroidApplication::sdkVersion() >= 31)
- QSKIP("Fails on Android 12 (QTBUG-111235)");
-#endif
// Tests QTBUG-60896
QWidget topLevel1;
diff --git a/tests/baseline/stylesheet/qss/qheaderview/selectedFontWeight.qss b/tests/baseline/stylesheet/qss/qheaderview/selectedFontWeight.qss
new file mode 100644
index 00000000000..1c45a997672
--- /dev/null
+++ b/tests/baseline/stylesheet/qss/qheaderview/selectedFontWeight.qss
@@ -0,0 +1,16 @@
+QHeaderView::section {
+ background-color: red;
+ font-size: 10px;
+}
+
+QHeaderView::section:checked {
+ background-color: green;
+ font-size: 20px;
+ font-weight: bold;
+}
+
+QHeaderView::section:first {
+ background-color: yellow;
+ font-size: 20px;
+ font-weight: normal;
+}
diff --git a/tests/baseline/stylesheet/tst_baseline_stylesheet.cpp b/tests/baseline/stylesheet/tst_baseline_stylesheet.cpp
index 3a4d8e8f15d..dde3dcc7178 100644
--- a/tests/baseline/stylesheet/tst_baseline_stylesheet.cpp
+++ b/tests/baseline/stylesheet/tst_baseline_stylesheet.cpp
@@ -27,6 +27,9 @@ private slots:
void tst_QTreeView_data();
void tst_QTreeView();
+ void tst_QHeaderView_data();
+ void tst_QHeaderView();
+
private:
QDir styleSheetDir;
};
@@ -205,6 +208,22 @@ void tst_Stylesheet::tst_QTreeView()
QBASELINE_CHECK_DEFERRED(takeSnapshot(), "itemSelected");
}
+void tst_Stylesheet::tst_QHeaderView_data()
+{
+ loadTestFiles();
+}
+
+void tst_Stylesheet::tst_QHeaderView()
+{
+ QHBoxLayout *layout = new QHBoxLayout;
+ QTableWidget *tw = new QTableWidget(10, 10);
+ tw->setCurrentCell(1, 1);
+ layout->addWidget(tw);
+ testWindow()->setLayout(layout);
+ makeVisible();
+ QBASELINE_TEST(takeSnapshot());
+}
+
#define main _realmain
QTEST_MAIN(tst_Stylesheet)
#undef main
diff --git a/tests/baseline/text/data/colored_list.html b/tests/baseline/text/data/colored_list.html
new file mode 100644
index 00000000000..d1cca94460f
--- /dev/null
+++ b/tests/baseline/text/data/colored_list.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html>
+<head>
+<style type="text/css">
+p, li { white-space: pre-wrap; }
+hr { height: 1px; border-width: 0; }
+li.unchecked::marker { content: "\2610"; }
+li.checked::marker { content: "\2612"; }
+body { background-color: #111155; color: #ffffff; }
+</style>
+</head>
+<body>
+
+<ul>
+<li>disc</li>
+<li style=" color:#a58d47;">bronze</li>
+<li style=" color:red;"><span style=" color:#ffcdb9;">red bullet, pink text</span></li>
+<li style=" color:#dddddd;" class="checked">checked</li>
+<li style=" color:#dddddd;" class="unchecked">unchecked</li>
+</ul>
+
+<ul type="circle">
+<li>circle</li>
+<li style=" color:#dddddd;">silver</li>
+<li style=" color:lightgrey;"><span style=" color:#ffcdb9;">grey bullet, pink text</span></li>
+<li style=" color:#dddddd;" class="checked">checked</li>
+<li style=" color:#dddddd;" class="unchecked">unchecked</li>
+</ul>
+
+<ul type="square">
+<li style=" color:#ffffff;">square</li>
+<li style=" color:#fceebb;">gold</li>
+<li style=" color:yellow;"><span style=" color:#ffcdb9;">yellow bullet, pink text</span></li>
+<li style=" color:#dddddd;" class="checked">checked</li>
+<li style=" color:#dddddd;" class="unchecked">unchecked</li>
+</ul>
+
+<ol>
+<li>decimal</li>
+<li style=" color:#a58d47;">bronze decimal</li>
+<li style=" color:red;"><span style=" color:#ffcdb9;">red number, pink text</span></li>
+</ol>
+
+<ol type="A">
+<li>uppercase</li>
+<li style=" color:#a58d47;">bronze uppercase</li>
+<li style=" color:red;"><span style=" color:#ffcdb9;">red letter, pink text</span></li>
+</ol>
+
+<ol type="a">
+<li>lowercase</li>
+<li style=" color:#a58d47;">bronze lowercase</li>
+<li style=" color:red;"><span style=" color:#ffcdb9;">red letter, pink text</span></li>
+</ol>
+
+<ol type="i">
+<li>lower roman</li>
+<li style=" color:#a58d47;">bronze roman</li>
+<li style=" color:red;"><span style=" color:#ffcdb9;">red number, pink text</span></li>
+</ol>
+
+<ol type="I">
+<li>upper roman</li>
+<li style=" color:#a58d47;">bronze roman</li>
+<li style=" color:red;"><span style=" color:#ffcdb9;">red number, pink text</span></li>
+</ol>
+</body>
+</html>
diff --git a/tests/manual/qopenglwidget/openglwidget/main.cpp b/tests/manual/qopenglwidget/openglwidget/main.cpp
index 7ea5a4e7d7a..2cc9458c3ec 100644
--- a/tests/manual/qopenglwidget/openglwidget/main.cpp
+++ b/tests/manual/qopenglwidget/openglwidget/main.cpp
@@ -31,7 +31,6 @@ public:
private slots:
void turnNative();
void hideShowAllGL();
- void dumpCompositingStatus();
signals:
void aboutToShowGLWidgets();
@@ -83,12 +82,6 @@ void Tools::dumpWidget(QWidget *w, int indent)
}
}
-void Tools::dumpCompositingStatus()
-{
- QWindow *w = m_root->window()->windowHandle();
- qDebug() << "Compositing status for" << w << m_root->window() << "is" << QWindowPrivate::get(w)->compositing;
-}
-
class TabWidgetResetter : public QObject
{
Q_OBJECT
@@ -193,10 +186,6 @@ int main(int argc, char *argv[])
toolsMenu->addAction("&Turn widgets (or some parent) into native", &t, SLOT(turnNative()));
toolsMenu->addAction("&Hide/show all OpenGL widgets", &t, SLOT(hideShowAllGL()));
- QTimer compStatusDumpTimer;
- QObject::connect(&compStatusDumpTimer, SIGNAL(timeout()), &t, SLOT(dumpCompositingStatus()));
- compStatusDumpTimer.start(5000);
-
wnd.show();
if (glw->isValid())