diff options
Diffstat (limited to 'tests')
65 files changed, 1379 insertions, 320 deletions
diff --git a/tests/auto/cmake/mockplugins/.cmake.conf b/tests/auto/cmake/mockplugins/.cmake.conf index b9c40d1839..f6f7fed367 100644 --- a/tests/auto/cmake/mockplugins/.cmake.conf +++ b/tests/auto/cmake/mockplugins/.cmake.conf @@ -1 +1 @@ -set(QT_REPO_MODULE_VERSION "6.2.6") +set(QT_REPO_MODULE_VERSION "6.2.7") diff --git a/tests/auto/cmake/test_static_resources/.cmake.conf b/tests/auto/cmake/test_static_resources/.cmake.conf index b9c40d1839..f6f7fed367 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.2.6") +set(QT_REPO_MODULE_VERSION "6.2.7") diff --git a/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp b/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp index 540856ad6e..87ab016fe6 100644 --- a/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp +++ b/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp @@ -33,9 +33,7 @@ #include <QTest> #include <QTimer> -#if __has_include(<chrono>) -# include <chrono> -#endif +#include <chrono> static const int minResolution = 400; // the minimum resolution for the tests @@ -520,9 +518,6 @@ void tst_QDeadlineTimer::expire() void tst_QDeadlineTimer::stdchrono() { -#if !__has_include(<chrono>) - QSKIP("std::chrono not found on this system"); -#else using namespace std::chrono; QFETCH_GLOBAL(Qt::TimerType, timerType); @@ -722,7 +717,6 @@ void tst_QDeadlineTimer::stdchrono() QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + seconds(1) + milliseconds(minResolution))); QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + seconds(1) - milliseconds(minResolution))); QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + seconds(1) + milliseconds(minResolution))); -#endif } QTEST_MAIN(tst_QDeadlineTimer) diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp index b3a500fbd8..6cc9dd9220 100644 --- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp +++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp @@ -265,19 +265,14 @@ void tst_QTimer::remainingTimeDuringActivation() namespace { -#if __has_include(<chrono>) template <typename T> std::chrono::milliseconds to_ms(T t) { return std::chrono::duration_cast<std::chrono::milliseconds>(t); } -#endif } // unnamed namespace void tst_QTimer::basic_chrono() { -#if !__has_include(<chrono>) - QSKIP("This test requires C++11 <chrono> support"); -#else // duplicates zeroTimer, singleShotTimeout, interval and remainingTime using namespace std::chrono; QTimer timer; @@ -318,7 +313,6 @@ void tst_QTimer::basic_chrono() QCOMPARE(timeoutSpy.count(), 1); QTest::qWait(500); QCOMPARE(timeoutSpy.count(), 1); -#endif } void tst_QTimer::livelock_data() @@ -915,9 +909,6 @@ void tst_QTimer::singleShotToFunctors() void tst_QTimer::singleShot_chrono() { -#if !__has_include(<chrono>) - QSKIP("This test requires C++11 <chrono> support"); -#else // duplicates singleShotStaticFunctionZeroTimeout and singleShotToFunctors using namespace std::chrono; { @@ -954,7 +945,6 @@ void tst_QTimer::singleShot_chrono() QTRY_COMPARE(count, 3); _e.reset(); -#endif } class DontBlockEvents : public QObject diff --git a/tests/auto/corelib/platform/android/CMakeLists.txt b/tests/auto/corelib/platform/android/CMakeLists.txt index c2749825ac..6c08080e6a 100644 --- a/tests/auto/corelib/platform/android/CMakeLists.txt +++ b/tests/auto/corelib/platform/android/CMakeLists.txt @@ -7,6 +7,10 @@ qt_internal_add_test(tst_android SOURCES tst_android.cpp + LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::GuiPrivate ) if(ANDROID) diff --git a/tests/auto/corelib/platform/android/tst_android.cpp b/tests/auto/corelib/platform/android/tst_android.cpp index 710e5b2ecf..7e66e1fd3b 100644 --- a/tests/auto/corelib/platform/android/tst_android.cpp +++ b/tests/auto/corelib/platform/android/tst_android.cpp @@ -29,8 +29,12 @@ #include <jni.h> #include <QTest> +#include <QGuiApplication> #include <QtCore/qnativeinterface.h> #include <QtCore/qjniobject.h> +#include <QScreen> +#include <qpa/qplatformscreen.h> +#include <qpa/qplatformnativeinterface.h> class tst_Android : public QObject { @@ -41,6 +45,7 @@ private slots: void testAndroidSdkVersion(); void testAndroidActivity(); void testRunOnAndroidMainThread(); + void testFullScreenDimensions(); }; void tst_Android::assetsRead() @@ -189,6 +194,103 @@ void tst_Android::testRunOnAndroidMainThread() } } +void setSystemUiVisibility(int visibility) +{ + QNativeInterface::QAndroidApplication::runOnAndroidMainThread([visibility] { + QJniObject::callStaticMethod<void>("org/qtproject/qt/android/QtNative", + "setSystemUiVisibility", "(I)V", visibility); + }).waitForFinished(); +} + +// QTBUG-107604 +void tst_Android::testFullScreenDimensions() +{ + static int SYSTEM_UI_VISIBILITY_NORMAL = 0; + static int SYSTEM_UI_VISIBILITY_FULLSCREEN = 1; + static int SYSTEM_UI_VISIBILITY_TRANSLUCENT = 2; + + // this will trigger new layout updates + setSystemUiVisibility(SYSTEM_UI_VISIBILITY_FULLSCREEN); + setSystemUiVisibility(SYSTEM_UI_VISIBILITY_NORMAL); + + QJniObject activity = QNativeInterface::QAndroidApplication::context(); + QVERIFY(activity.isValid()); + + QJniObject windowManager = + activity.callObjectMethod("getWindowManager", "()Landroid/view/WindowManager;"); + QVERIFY(windowManager.isValid()); + + QJniObject display = windowManager.callObjectMethod("getDefaultDisplay", "()Landroid/view/Display;"); + QVERIFY(display.isValid()); + + QJniObject appSize("android/graphics/Point"); + QVERIFY(appSize.isValid()); + + display.callMethod<void>("getSize", "(Landroid/graphics/Point;)V", appSize.object()); + + QJniObject realSize("android/graphics/Point"); + QVERIFY(realSize.isValid()); + + display.callMethod<void>("getRealSize", "(Landroid/graphics/Point;)V", realSize.object()); + + QPlatformScreen *screen = QGuiApplication::primaryScreen()->handle(); + + { + // Normal - + // available geometry == app size (system bars visible and removed from available geometry) + QCoreApplication::processEvents(); + QJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;"); + QVERIFY(window.isValid()); + + QJniObject decorView = window.callObjectMethod("getDecorView", "()Landroid/view/View;"); + QVERIFY(decorView.isValid()); + + QJniObject insets = + decorView.callObjectMethod("getRootWindowInsets", "()Landroid/view/WindowInsets;"); + QVERIFY(insets.isValid()); + + int insetsWidth = insets.callMethod<jint>("getSystemWindowInsetRight") + + insets.callMethod<jint>("getSystemWindowInsetLeft"); + + int insetsHeight = insets.callMethod<jint>("getSystemWindowInsetTop") + + insets.callMethod<jint>("getSystemWindowInsetBottom"); + + QTRY_COMPARE(screen->availableGeometry().width(), + int(appSize.getField<jint>("x")) - insetsWidth); + QTRY_COMPARE(screen->availableGeometry().height(), + int(appSize.getField<jint>("y")) - insetsHeight); + + QTRY_COMPARE(screen->geometry().width(), int(realSize.getField<jint>("x"))); + QTRY_COMPARE(screen->geometry().height(), int(realSize.getField<jint>("y"))); + } + + { + setSystemUiVisibility(SYSTEM_UI_VISIBILITY_FULLSCREEN); + + // Fullscreen + // available geometry == full display size (system bars hidden) + QCoreApplication::processEvents(); + QTRY_COMPARE(screen->availableGeometry().width(), int(realSize.getField<jint>("x"))); + QTRY_COMPARE(screen->availableGeometry().height(), int(realSize.getField<jint>("y"))); + + QTRY_COMPARE(screen->geometry().width(), int(realSize.getField<jint>("x"))); + QTRY_COMPARE(screen->geometry().height(), int(realSize.getField<jint>("y"))); + } + + { + setSystemUiVisibility(SYSTEM_UI_VISIBILITY_TRANSLUCENT); + + // Translucent + // available geometry == full display size (system bars visible but drawable under) + QCoreApplication::processEvents(); + QTRY_COMPARE(screen->availableGeometry().width(), int(realSize.getField<jint>("x"))); + QTRY_COMPARE(screen->availableGeometry().height(), int(realSize.getField<jint>("y"))); + + QTRY_COMPARE(screen->geometry().width(), int(realSize.getField<jint>("x"))); + QTRY_COMPARE(screen->geometry().height(), int(realSize.getField<jint>("y"))); + } +} + QTEST_MAIN(tst_Android) #include "tst_android.moc" diff --git a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp index 72a6427930..fc7247b733 100644 --- a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp @@ -35,6 +35,7 @@ #include <limits.h> #include <private/qtools_p.h> +#include <iterator> #include <stdexcept> #include <string_view> @@ -53,6 +54,7 @@ private slots: void qCompress(); void qUncompressCorruptedData_data(); void qUncompressCorruptedData(); + void qUncompress4GiBPlus(); void qCompressionZeroTermination(); #endif void constByteArray(); @@ -343,6 +345,79 @@ void tst_QByteArray::qUncompressCorruptedData() #endif } +void tst_QByteArray::qUncompress4GiBPlus() +{ + // after three rounds, this decompresses to 4GiB + 1 'X' bytes: + constexpr uchar compressed_3x[] = { + 0x00, 0x00, 0x1a, 0x76, 0x78, 0x9c, 0x63, 0xb0, 0xdf, 0xb4, 0xad, 0x62, + 0xce, 0xdb, 0x3b, 0x0b, 0xf3, 0x26, 0x27, 0x4a, 0xb4, 0x3d, 0x34, 0x5b, + 0xed, 0xb4, 0x41, 0xf1, 0xc0, 0x99, 0x2f, 0x02, 0x05, 0x67, 0x26, 0x88, + 0x6c, 0x66, 0x71, 0x34, 0x62, 0x9c, 0x75, 0x26, 0xb1, 0xa0, 0xe5, 0xcc, + 0xda, 0x94, 0x83, 0xc9, 0x05, 0x73, 0x0e, 0x3c, 0x39, 0xc2, 0xc7, 0xd0, + 0xae, 0x38, 0x53, 0x7b, 0x87, 0xdc, 0x01, 0x91, 0x45, 0x59, 0x4f, 0xda, + 0xbf, 0xca, 0xcc, 0x52, 0xdb, 0xbb, 0xde, 0xbb, 0xf6, 0xd3, 0x55, 0xff, + 0x7d, 0x77, 0x0e, 0x1b, 0xf0, 0xa4, 0xdf, 0xcf, 0xdb, 0x5f, 0x2f, 0xf5, + 0xd7, 0x7c, 0xfe, 0xbf, 0x3f, 0xbf, 0x3f, 0x9d, 0x7c, 0xda, 0x2c, 0xc8, + 0xc0, 0xc0, 0xb0, 0xe1, 0xf1, 0xb3, 0xfd, 0xfa, 0xdf, 0x8e, 0x7d, 0xef, + 0x7f, 0xb9, 0xc1, 0xc2, 0xae, 0x92, 0x19, 0x28, 0xf2, 0x66, 0xd7, 0xe5, + 0xbf, 0xed, 0x93, 0xbf, 0x6a, 0x14, 0x7c, 0xff, 0xf6, 0xe1, 0xe8, 0xb6, + 0x7e, 0x46, 0xa0, 0x90, 0xd9, 0xbb, 0xcf, 0x9f, 0x17, 0x37, 0x7f, 0xe5, + 0x6f, 0xb4, 0x7f, 0xfe, 0x5e, 0xfd, 0xb6, 0x1d, 0x1b, 0x50, 0xe8, 0xc6, + 0x8e, 0xe3, 0xab, 0x9f, 0xe6, 0xec, 0x65, 0xfd, 0x23, 0xb1, 0x4e, 0x7e, + 0xef, 0xbd, 0x6f, 0xa6, 0x40, 0xa1, 0x03, 0xc7, 0xfe, 0x0a, 0xf1, 0x00, + 0xe9, 0x06, 0x91, 0x83, 0x40, 0x92, 0x21, 0x43, 0x10, 0xcc, 0x11, 0x03, + 0x73, 0x3a, 0x90, 0x39, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, + 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, + 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, + 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, + 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0x34, 0x90, 0x99, 0xb6, 0x7e, 0xf5, + 0xd3, 0xe9, 0xbf, 0x35, 0x13, 0xca, 0x8c, 0x75, 0xec, 0xec, 0xa4, 0x2f, + 0x7e, 0x2d, 0xf9, 0xf3, 0xf0, 0xee, 0xea, 0xd5, 0xf5, 0xd3, 0x14, 0x57, + 0x06, 0x00, 0x00, 0xb9, 0x1e, 0x35, 0xce + }; + + constexpr qint64 GiB = 1024LL * 1024 * 1024; + + if constexpr (sizeof(qsizetype) == sizeof(int)) { + QSKIP("This is a 64-bit-only test."); + } else { + + // 1st + auto c = ::qUncompress(std::data(compressed_3x), qsizetype(std::size(compressed_3x))); + QVERIFY(!c.isNull()); // check for decompression error + + // 2nd + c = ::qUncompress(c); + QVERIFY(!c.isNull()); + + // 3rd + try { + c = ::qUncompress(c); + if (c.isNull()) // this step (~18MiB -> 4GiB) might have run out of memory + QSKIP("Failed to allocate enough memory."); + } catch (const std::bad_alloc &) { + QSKIP("Failed to allocate enough memory."); + } + + QCOMPARE(c.size(), 4 * GiB + 1); + QCOMPARE(std::string_view{c}.find_first_not_of('X'), + std::string_view::npos); + + // re-compress once + // (produces 18MiB, we shouldn't use much more than that in allocated capacity) + c = ::qCompress(c); + QVERIFY(!c.isNull()); + + // and un-compress again, to make sure compression worked (we + // can't compare with compressed_3x, because zlib may change): + c = ::qUncompress(c); + + QCOMPARE(c.size(), 4 * GiB + 1); + QCOMPARE(std::string_view{c}.find_first_not_of('X'), + std::string_view::npos); + } +} + void tst_QByteArray::qCompressionZeroTermination() { QString s = "Hello, I'm a string."; diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index d105f32912..2a9b0ba189 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -1361,6 +1361,43 @@ void tst_QString::asprintf() double d = -514.25683; QCOMPARE(QString::asprintf("%f", d), QLatin1String("-514.256830")); + QCOMPARE(QString::asprintf("%.f", d), QLatin1String("-514")); + QCOMPARE(QString::asprintf("%.0f", d), QLatin1String("-514")); + QCOMPARE(QString::asprintf("%1f", d), QLatin1String("-514.256830")); + QCOMPARE(QString::asprintf("%1.f", d), QLatin1String("-514")); + QCOMPARE(QString::asprintf("%1.0f", d), QLatin1String("-514")); + QCOMPARE(QString::asprintf("%1.6f", d), QLatin1String("-514.256830")); + QCOMPARE(QString::asprintf("%1.10f", d), QLatin1String("-514.2568300000")); + QCOMPARE(QString::asprintf("%-1f", d), QLatin1String("-514.256830")); + QCOMPARE(QString::asprintf("%-1.f", d), QLatin1String("-514")); + QCOMPARE(QString::asprintf("%-1.0f", d), QLatin1String("-514")); + QCOMPARE(QString::asprintf("%-1.6f", d), QLatin1String("-514.256830")); + QCOMPARE(QString::asprintf("%-1.10f", d), QLatin1String("-514.2568300000")); + QCOMPARE(QString::asprintf("%10f", d), QLatin1String("-514.256830")); + QCOMPARE(QString::asprintf("%10.f", d), QLatin1String(" -514")); + QCOMPARE(QString::asprintf("%10.0f", d), QLatin1String(" -514")); + QCOMPARE(QString::asprintf("%-10f", d), QLatin1String("-514.256830")); + QCOMPARE(QString::asprintf("%-10.f", d), QLatin1String("-514 ")); + QCOMPARE(QString::asprintf("%-10.0f", d), QLatin1String("-514 ")); + QCOMPARE(QString::asprintf("%010f", d), QLatin1String("-514.256830")); + QCOMPARE(QString::asprintf("%010.f", d), QLatin1String("-000000514")); + QCOMPARE(QString::asprintf("%010.0f", d), QLatin1String("-000000514")); + QCOMPARE(QString::asprintf("%15f", d), QLatin1String(" -514.256830")); + QCOMPARE(QString::asprintf("%15.6f", d), QLatin1String(" -514.256830")); + QCOMPARE(QString::asprintf("%15.10f", d), QLatin1String("-514.2568300000")); + QCOMPARE(QString::asprintf("%-15f", d), QLatin1String("-514.256830 ")); + QCOMPARE(QString::asprintf("%-15.6f", d), QLatin1String("-514.256830 ")); + QCOMPARE(QString::asprintf("%-15.10f", d), QLatin1String("-514.2568300000")); + QCOMPARE(QString::asprintf("%015f", d), QLatin1String("-0000514.256830")); + QCOMPARE(QString::asprintf("%015.6f", d), QLatin1String("-0000514.256830")); + QCOMPARE(QString::asprintf("%015.10f", d), QLatin1String("-514.2568300000")); +QT_WARNING_PUSH +QT_WARNING_DISABLE_GCC("-Wformat") +QT_WARNING_DISABLE_CLANG("-Wformat") // Flag '0' ignored when flag '-' is present + QCOMPARE(QString::asprintf("%-015f", d), QLatin1String("-514.256830 ")); + QCOMPARE(QString::asprintf("%-015.6f", d), QLatin1String("-514.256830 ")); + QCOMPARE(QString::asprintf("%-015.10f", d), QLatin1String("-514.2568300000")); +QT_WARNING_POP { /* This code crashed. I don't know how to reduce it further. In other words, diff --git a/tests/auto/corelib/thread/CMakeLists.txt b/tests/auto/corelib/thread/CMakeLists.txt index 356ae0346c..d51d108d83 100644 --- a/tests/auto/corelib/thread/CMakeLists.txt +++ b/tests/auto/corelib/thread/CMakeLists.txt @@ -5,7 +5,7 @@ if(QT_FEATURE_thread) add_subdirectory(qatomicinteger) add_subdirectory(qatomicpointer) add_subdirectory(qresultstore) - if(NOT INTEGRITY) + if(QT_FEATURE_concurrent AND NOT INTEGRITY) add_subdirectory(qfuture) endif() add_subdirectory(qfuturesynchronizer) diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp index 7b508b8a22..603d2eb21a 100644 --- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp +++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp @@ -2157,6 +2157,26 @@ void tst_QFuture::then() QVERIFY(threadId1 != QThread::currentThreadId()); QVERIFY(threadId2 != QThread::currentThreadId()); } + + // QTBUG-106083 & QTBUG-105182 + { + QThread thread; + thread.start(); + + QObject context; + context.moveToThread(&thread); + + auto future = QtConcurrent::run([] { + return 42; + }).then([] (int result) { + return result + 1; + }).then(&context, [] (int result) { + return result + 1; + }); + QCOMPARE(future.result(), 44); + thread.quit(); + thread.wait(); + } } template<class Type, class Callable> @@ -3033,6 +3053,57 @@ void tst_QFuture::cancelContinuations() QCOMPARE(checkpoint, 3); } #endif // QT_NO_EXCEPTIONS + + // Check notifications from QFutureWatcher + { + QPromise<void> p; + auto f = p.future(); + + auto f1 = f.then([] {}); + auto f2 = f1.then([] {}); + + QFutureWatcher<void> watcher1, watcher2; + int state = 0; + QObject::connect(&watcher1, &QFutureWatcher<void>::started, [&] { + QCOMPARE(state, 0); + ++state; + }); + QObject::connect(&watcher1, &QFutureWatcher<void>::canceled, [&] { + QCOMPARE(state, 1); + ++state; + }); + QObject::connect(&watcher1, &QFutureWatcher<void>::finished, [&] { + QCOMPARE(state, 2); + ++state; + }); + QObject::connect(&watcher2, &QFutureWatcher<void>::started, [&] { + QCOMPARE(state, 3); + ++state; + }); + QObject::connect(&watcher2, &QFutureWatcher<void>::canceled, [&] { + QCOMPARE(state, 4); + ++state; + }); + QObject::connect(&watcher2, &QFutureWatcher<int>::finished, [&] { + QCOMPARE(state, 5); + ++state; + }); + + watcher1.setFuture(f1); + watcher2.setFuture(f2); + + p.start(); + f.cancel(); + p.finish(); + + qApp->processEvents(); + + QCOMPARE(state, 6); + QVERIFY(watcher1.isFinished()); + QVERIFY(watcher1.isCanceled()); + QVERIFY(watcher2.isFinished()); + QVERIFY(watcher2.isCanceled()); + } } void tst_QFuture::continuationsWithContext() diff --git a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp index fb080a1a12..24e8fad4cc 100644 --- a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp +++ b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp @@ -90,9 +90,7 @@ enum { waitTime = 100 }; -#if __has_include(<chrono>) static constexpr std::chrono::milliseconds waitTimeAsDuration(waitTime); -#endif void tst_QMutex::convertToMilliseconds_data() { @@ -101,10 +99,6 @@ void tst_QMutex::convertToMilliseconds_data() QTest::addColumn<qint64>("intValue"); QTest::addColumn<qint64>("expected"); -#if !__has_include(<chrono>) - QSKIP("This test requires <chrono>"); -#endif - auto add = [](TimeUnit unit, double d, long long i, qint64 expected) { const QScopedArrayPointer<char> enumName(QTest::toString(unit)); QTest::addRow("%s:%f:%lld", enumName.data(), d, i) @@ -157,9 +151,6 @@ void tst_QMutex::convertToMilliseconds_data() void tst_QMutex::convertToMilliseconds() { -#if !__has_include(<chrono>) - QSKIP("This test requires <chrono>"); -#else QFETCH(TimeUnit, unit); QFETCH(double, doubleValue); QFETCH(qint64, intValue); @@ -197,7 +188,6 @@ void tst_QMutex::convertToMilliseconds() #undef DO #undef CASE } -#endif } void tst_QMutex::tryLock_non_recursive() @@ -325,10 +315,8 @@ void tst_QMutex::tryLock_non_recursive() thread.wait(); } -void tst_QMutex::try_lock_for_non_recursive() { -#if !__has_include(<chrono>) - QSKIP("This test requires <chrono>"); -#else +void tst_QMutex::try_lock_for_non_recursive() +{ class Thread : public QThread { public: @@ -450,14 +438,10 @@ void tst_QMutex::try_lock_for_non_recursive() { testsTurn.acquire(); threadsTurn.release(); thread.wait(); -#endif } void tst_QMutex::try_lock_until_non_recursive() { -#if !__has_include(<chrono>) - QSKIP("This test requires <chrono>"); -#else class Thread : public QThread { public: @@ -579,7 +563,6 @@ void tst_QMutex::try_lock_until_non_recursive() testsTurn.acquire(); threadsTurn.release(); thread.wait(); -#endif } void tst_QMutex::tryLock_recursive() @@ -708,9 +691,6 @@ void tst_QMutex::tryLock_recursive() void tst_QMutex::try_lock_for_recursive() { -#if !__has_include(<chrono>) - QSKIP("This test requires <chrono>"); -#else class Thread : public QThread { public: @@ -831,14 +811,10 @@ void tst_QMutex::try_lock_for_recursive() testsTurn.acquire(); threadsTurn.release(); thread.wait(); -#endif } void tst_QMutex::try_lock_until_recursive() { -#if !__has_include(<chrono>) - QSKIP("This test requires <chrono>"); -#else class Thread : public QThread { public: @@ -960,7 +936,6 @@ void tst_QMutex::try_lock_until_recursive() testsTurn.acquire(); threadsTurn.release(); thread.wait(); -#endif } class mutex_Thread : public QThread diff --git a/tests/auto/corelib/tools/collections/tst_collections.cpp b/tests/auto/corelib/tools/collections/tst_collections.cpp index be2a4dbc05..6c0f0f86ac 100644 --- a/tests/auto/corelib/tools/collections/tst_collections.cpp +++ b/tests/auto/corelib/tools/collections/tst_collections.cpp @@ -63,6 +63,9 @@ void foo() #include <QTest> #include <QVector> +#include <QScopedPointer> +#include <QThread> +#include <QSemaphore> #include <algorithm> @@ -123,6 +126,15 @@ private slots: void foreach_2(); void insert_remove_loop(); + + void detachAssociativeContainerQMap() { detachAssociativeContainerImpl<QMap>(); } + void detachAssociativeContainerQMultiMap() { detachAssociativeContainerImpl<QMultiMap>(); } + void detachAssociativeContainerQHash() { detachAssociativeContainerImpl<QHash>(); } + void detachAssociativeContainerQMultiHash() { detachAssociativeContainerImpl<QMultiHash>(); } + +private: + template <template<typename, typename> typename Container> + void detachAssociativeContainerImpl(); }; struct LargeStatic { @@ -3547,7 +3559,63 @@ void tst_Collections::insert_remove_loop() insert_remove_loop_impl<QVarLengthArray<std::string, 15>>(); } +template <template<typename, typename> typename Container> +void tst_Collections::detachAssociativeContainerImpl() +{ + constexpr int RUNS = 50; + + for (int run = 0; run < RUNS; ++run) { + Container<int, int> container; + + for (int i = 0; i < 1'000; ++i) { + container.insert(i, i); + container.insert(i, i); // for multi-keyed containers + } + + const auto it = container.constBegin(); + const auto &key = it.key(); + const auto &value = it.value(); + const auto keyCopy = key; + const auto valueCopy = value; + + QSemaphore sem1, sem2; + auto detachInAnotherThread = [&sem1, &sem2, copy = container]() mutable { + sem1.release(); + sem2.acquire(); + copy.clear(); // <== + }; + QScopedPointer thread(QThread::create(std::move(detachInAnotherThread))); + thread->start(); + + sem2.release(); + sem1.acquire(); + + // The following call may detach (because the container is + // shared), and then use key/value to search+insert. + // + // This means that key/value, as references, have to be valid + // throughout the insertion procedure. Note that they are + // references into the container *itself*; and that the + // insertion procedure is working on a new (detached) copy of + // the container's payload. + // + // There is now a possible scenario in which the clear() above + // finds the copy's refcount at 1, hence not perform a detach, + // and destroy its payload. But key/value were references into + // *that* payload (it's the payload that `container` itself + // used to share). If inside insert() we don't take extra + // measures to keep the payload alive, now they're dangling and + // the insertion will malfunction. + + container.insert(key, value); + + QVERIFY(container.contains(keyCopy)); + QCOMPARE(container.value(keyCopy), valueCopy); + + thread->wait(); + } +} QTEST_APPLESS_MAIN(tst_Collections) #include "tst_collections.moc" diff --git a/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp b/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp index 263083972c..79943a99eb 100644 --- a/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp +++ b/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp @@ -168,6 +168,7 @@ void tst_QBitArray::countBits() bits.setBit(i); } + QCOMPARE(bits.size(), numBits); QCOMPARE(bits.count(), numBits); QCOMPARE(bits.count(true), onBits); QCOMPARE(bits.count(false), numBits - onBits); diff --git a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp index b25ed55648..59cb9648b7 100644 --- a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp +++ b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp @@ -75,10 +75,12 @@ void tst_QContiguousCache::empty() { QContiguousCache<int> c(10); QCOMPARE(c.capacity(), 10); + QCOMPARE(c.size(), 0); QCOMPARE(c.count(), 0); QVERIFY(c.isEmpty()); c.append(1); QCOMPARE(c.count(), 1); + QCOMPARE(c.size(), 1); QVERIFY(!c.isEmpty()); c.clear(); QCOMPARE(c.capacity(), 10); diff --git a/tests/auto/corelib/tools/qmap/tst_qmap.cpp b/tests/auto/corelib/tools/qmap/tst_qmap.cpp index 2dd5db6e8a..3febe1a73f 100644 --- a/tests/auto/corelib/tools/qmap/tst_qmap.cpp +++ b/tests/auto/corelib/tools/qmap/tst_qmap.cpp @@ -1866,12 +1866,6 @@ void tst_QMap::equal_range() QCOMPARE(map.count(1), 2); } -template <class T> -const T &const_(const T &t) -{ - return t; -} - void tst_QMap::insert() { QMap<QString, float> map; diff --git a/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp index dcc966fc2f..d1e89d407b 100644 --- a/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp +++ b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp @@ -36,6 +36,7 @@ class tst_QTaggedPointer : public QObject private Q_SLOTS: void constExpr(); void construction(); + void assignment(); void dereferenceOperator(); void pointerOperator(); void negationOperator(); @@ -105,6 +106,47 @@ void tst_QTaggedPointer::construction() } } +void tst_QTaggedPointer::assignment() +{ + QScopedPointer<int> rawPointer(new int(5)); + QTaggedPointer<int> p(rawPointer.data(), 0x1); + QTaggedPointer<int> p2(rawPointer.data(), 0x2); + + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x1)); + + QCOMPARE(p2.data(), rawPointer.data()); + QCOMPARE(p2.tag(), quintptr(0x2)); + + p = nullptr; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x1)); + + p = rawPointer.data(); + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x1)); + + p = {}; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x0)); + + p = p2; + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x2)); + + p = nullptr; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x2)); + + p = {}; + QCOMPARE(p.data(), nullptr); + QCOMPARE(p.tag(), quintptr(0x0)); + + p = rawPointer.data(); + QCOMPARE(p.data(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x0)); +} + class AbstractClass { public: diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp index b0c59245b1..b504cf1561 100644 --- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp +++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp @@ -1038,8 +1038,6 @@ void tst_QGuiApplication::genericPluginsAndWindowSystemEvents() QVERIFY(QGuiApplication::primaryScreen()); QCOMPARE(QGuiApplication::primaryScreen()->orientation(), testOrientationToSend); - if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) - QEXPECT_FAIL("", "Wayland: This fails. See QTBUG-100891.", Abort); QCOMPARE(testReceiver.customEvents, 0); QCoreApplication::sendPostedEvents(&testReceiver); QCOMPARE(testReceiver.customEvents, 1); diff --git a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp index a81e6187e5..13365b01fe 100644 --- a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp +++ b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp @@ -47,6 +47,7 @@ private Q_SLOTS: void noBrushesSetForDefaultPalette(); void cannotCheckIfInvalidBrushSet(); void checkIfBrushForCurrentGroupSet(); + void cacheKey(); }; void tst_QPalette::roleValues_data() @@ -290,5 +291,61 @@ void tst_QPalette::checkIfBrushForCurrentGroupSet() QVERIFY(p.isBrushSet(QPalette::Current, QPalette::Link)); } +void tst_QPalette::cacheKey() +{ + const QPalette defaultPalette; + // precondition: all palettes are expected to have contrasting text on base + QVERIFY(defaultPalette.base() != defaultPalette.text()); + const auto defaultCacheKey = defaultPalette.cacheKey(); + const auto defaultSerNo = defaultCacheKey >> 32; + const auto defaultDetachNo = defaultCacheKey & 0xffffffff; + + QPalette copyDifferentData(defaultPalette); + QPalette copyDifferentMask(defaultPalette); + QPalette copyDifferentMaskAndData(defaultPalette); + + QCOMPARE(defaultPalette.cacheKey(), copyDifferentData.cacheKey()); + + // deep detach of both private and data + copyDifferentData.setBrush(QPalette::Base, defaultPalette.text()); + const auto differentDataKey = copyDifferentData.cacheKey(); + const auto differentDataSerNo = differentDataKey >> 32; + const auto differentDataDetachNo = differentDataKey & 0xffffffff; + + QVERIFY(copyDifferentData.cacheKey() != defaultCacheKey); + QCOMPARE(defaultPalette.cacheKey(), defaultCacheKey); + + // shallow detach, both privates reference the same data + copyDifferentMask.setResolveMask(0xffffffffffffffff); + const auto differentMaskKey = copyDifferentMask.cacheKey(); + const auto differentMaskSerNo = differentMaskKey >> 32; + const auto differentMaskDetachNo = differentMaskKey & 0xffffffff; + QCOMPARE(differentMaskSerNo, defaultSerNo); + QVERIFY(differentMaskSerNo != defaultDetachNo); + QVERIFY(differentMaskKey != defaultCacheKey); + QVERIFY(differentMaskKey != differentDataKey); + + // shallow detach, both privates reference the same data + copyDifferentMaskAndData.setResolveMask(0xeeeeeeeeeeeeeeee); + const auto modifiedCacheKey = copyDifferentMaskAndData.cacheKey(); + QVERIFY(modifiedCacheKey != copyDifferentMask.cacheKey()); + QVERIFY(modifiedCacheKey != defaultCacheKey); + QVERIFY(modifiedCacheKey != copyDifferentData.cacheKey()); + QVERIFY(copyDifferentMask.cacheKey() != defaultCacheKey); + + // full detach - both key elements are different + copyDifferentMaskAndData.setBrush(QPalette::Base, defaultPalette.text()); + const auto modifiedAllKey = copyDifferentMaskAndData.cacheKey(); + const auto modifiedAllSerNo = modifiedAllKey >> 32; + const auto modifiedAllDetachNo = modifiedAllKey & 0xffffffff; + QVERIFY(modifiedAllSerNo != defaultSerNo); + QVERIFY(modifiedAllDetachNo != defaultDetachNo); + + QVERIFY(modifiedAllKey != copyDifferentMask.cacheKey()); + QVERIFY(modifiedAllKey != defaultCacheKey); + QVERIFY(modifiedAllKey != differentDataKey); + QVERIFY(modifiedAllKey != modifiedCacheKey); +} + QTEST_MAIN(tst_QPalette) #include "tst_qpalette.moc" diff --git a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp index 8deb4589c6..7310cb5596 100644 --- a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp +++ b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp @@ -39,6 +39,8 @@ #include <private/qevent_p.h> #include <private/qhighdpiscaling_p.h> #include <private/qpointingdevice_p.h> +#include <private/qguiapplication_p.h> +#include <qpa/qplatformintegration.h> Q_LOGGING_CATEGORY(lcTests, "qt.gui.tests") @@ -1149,6 +1151,9 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() QSKIP("The macOS mouse cursor interferes with this test can cannot be moved away"); #endif + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + tst_QTouchEventWidget touchWidget; touchWidget.setObjectName("touchWidget"); touchWidget.setWindowTitle(QTest::currentTestFunction()); diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index 5e7cd0f801..17e812297f 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -95,6 +95,7 @@ private slots: void modalWithChildWindow(); void modalWindowModallity(); void modalWindowPosition(); + void modalCloseWhileBlocked(); #ifndef QT_NO_CURSOR void modalWindowEnterEventOnHide_QTBUG35109(); void spuriousMouseMove(); @@ -2305,6 +2306,22 @@ void tst_QWindow::modalWindowPosition() QCOMPARE(window.geometry(), origGeo); } +void tst_QWindow::modalCloseWhileBlocked() +{ + QWindow first; + first.setModality(Qt::ApplicationModal); + first.show(); + QVERIFY(QTest::qWaitForWindowExposed(&first)); + + QWindow second; + second.setModality(Qt::ApplicationModal); + second.show(); + QVERIFY(QTest::qWaitForWindowExposed(&first)); + + first.close(); + QTRY_VERIFY(!first.isVisible()); +} + #ifndef QT_NO_CURSOR void tst_QWindow::modalWindowEnterEventOnHide_QTBUG35109() { diff --git a/tests/auto/gui/qopengl/tst_qopengl.cpp b/tests/auto/gui/qopengl/tst_qopengl.cpp index 5d9053fb92..34bd12fdb1 100644 --- a/tests/auto/gui/qopengl/tst_qopengl.cpp +++ b/tests/auto/gui/qopengl/tst_qopengl.cpp @@ -1651,8 +1651,6 @@ void tst_QOpenGL::bufferMapRange() buf.unmap(); p = (char *) buf.mapRange(0, sizeof(data), QOpenGLBuffer::RangeRead); - if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) - QEXPECT_FAIL("", "This fails on Wayland, see QTBUG-100918.", Abort); QVERIFY(!strcmp(p, "sOMe data")); buf.unmap(); diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 550284c9a0..4c599ba258 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -280,6 +280,7 @@ private Q_SLOTS: void ioGetFromFileSpecial(); void ioGetFromFile_data(); void ioGetFromFile(); + void ioGetFromFileUrl(); void ioGetFromFtp_data(); void ioGetFromFtp(); void ioGetFromFtpWithReuse(); @@ -3315,6 +3316,18 @@ void tst_QNetworkReply::ioGetFromFile() QCOMPARE(reader.data, data); } +void tst_QNetworkReply::ioGetFromFileUrl() +{ + // This immediately fails on non-windows platforms: + QNetworkRequest request(QUrl("file://unc-server/some/path")); + QNetworkReplyPtr reply(manager.get(request)); + QSignalSpy finishedSpy(reply.get(), &QNetworkReply::finished); + // QTBUG-105618: This would, on non-Windows platforms, never happen because the signal + // was emitted before the constructor finished, leaving no chance at all to connect to the + // signal + QVERIFY(finishedSpy.wait()); +} + void tst_QNetworkReply::ioGetFromFtp_data() { if (!ftpSupported) diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp index 78f072fb54..ef45561f1a 100644 --- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp +++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp @@ -351,6 +351,12 @@ void tst_QHostAddress::isEqual_data() QTest::newRow("anyv6-anyv4-local") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::ConvertLocalHost << false; QTest::newRow("any-anyv4-local") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::ConvertLocalHost << false; QTest::newRow("any-anyv6-local") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv6) << (int)QHostAddress::ConvertLocalHost << false; + QTest::newRow("localhostv6-any-tolerant") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress(QHostAddress::Any) << (int)QHostAddress::TolerantConversion << false; + QTest::newRow("localhostv4-any-tolerant") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::Any) << (int)QHostAddress::TolerantConversion << false; + QTest::newRow("localhostv6-anyv6-tolerant") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress(QHostAddress::AnyIPv6) << (int)QHostAddress::TolerantConversion << false; + QTest::newRow("localhostv4-anyv6-tolerant") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::AnyIPv6) << (int)QHostAddress::TolerantConversion << false; + QTest::newRow("localhostv6-anyv4-tolerant") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::TolerantConversion << false; + QTest::newRow("localhostv4-anyv4-tolerant") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::TolerantConversion << false; } void tst_QHostAddress::isEqual() diff --git a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST index a9a591d5ca..479d0f878f 100644 --- a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST +++ b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST @@ -1,8 +1,7 @@ [udpTest] * [passwordAuth] -ubuntu-18.04 -ubuntu-20.04 +ubuntu # QTBUG-101274 qnx ci # QTBUG-74162 diff --git a/tests/auto/network/socket/qtcpserver/BLACKLIST b/tests/auto/network/socket/qtcpserver/BLACKLIST index ecca156cef..339987046c 100644 --- a/tests/auto/network/socket/qtcpserver/BLACKLIST +++ b/tests/auto/network/socket/qtcpserver/BLACKLIST @@ -15,4 +15,3 @@ windows-10 [linkLocal] macos arm - diff --git a/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp b/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp index 7cb65cd1a3..758a396a35 100644 --- a/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp +++ b/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp @@ -32,6 +32,9 @@ #if defined(Q_OS_WIN) && defined(Q_CC_MSVC) # include <crtdbg.h> #endif +#ifdef Q_OS_UNIX +# include <unistd.h> +#endif int main(int argc, char *argv[]) { @@ -40,10 +43,26 @@ int main(int argc, char *argv[]) _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG); #endif QCoreApplication app(argc, argv); + if (argc < 1) { + fprintf(stderr, "Need a port number\n"); + return 1; + } + int port = QByteArray(argv[1]).toInt(); QTcpServer server; - if (!server.listen(QHostAddress::LocalHost, 49199)) { - qDebug("Failed to listen: %s", server.errorString().toLatin1().constData()); + if (!server.listen(QHostAddress::LocalHost, port)) { + fprintf(stderr, "Failed to listen: %s\n", server.errorString().toLatin1().constData()); + if (server.serverError() == QTcpSocket::AddressInUseError) { + // let's see if we can find the process that would be holding this + // still open +#ifdef Q_OS_LINUX + static const char *ss_args[] = { + "ss", "-nap", "sport", "=", argv[1], nullptr + }; + dup2(STDERR_FILENO, STDOUT_FILENO); + execvp(ss_args[0], const_cast<char **>(ss_args)); +#endif + } return 1; } diff --git a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp index 5c2849249d..2ae629315b 100644 --- a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp +++ b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp @@ -598,9 +598,6 @@ void tst_QTcpServer::addressReusable() #if !QT_CONFIG(process) QSKIP("No qprocess support", SkipAll); #else -#ifdef Q_OS_LINUX - QSKIP("The addressReusable test is unstable on Linux. See QTBUG-39985."); -#endif QFETCH_GLOBAL(bool, setProxy); if (setProxy) { #ifndef QT_NO_NETWORKPROXY @@ -611,16 +608,25 @@ void tst_QTcpServer::addressReusable() QSKIP("No proxy support"); #endif // QT_NO_NETWORKPROXY } + + QTcpServer server; + QVERIFY(server.listen(QHostAddress::LocalHost, 0)); + quint16 serverPort = server.serverPort(); + qDebug() << "Got port" << serverPort; + server.close(); // cleanly close + + QTest::qSleep(10); + // The crashingServer process will crash once it gets a connection. QProcess process; QString processExe = crashingServerDir + "/crashingServer"; - process.start(processExe); + process.start(processExe, { QString::number(serverPort) }); QVERIFY2(process.waitForStarted(), qPrintable( QString::fromLatin1("Could not start %1: %2").arg(processExe, process.errorString()))); - QVERIFY(process.waitForReadyRead(5000)); + QVERIFY2(process.waitForReadyRead(5000), qPrintable(process.readAllStandardError())); QTcpSocket socket; - socket.connectToHost(QHostAddress::LocalHost, 49199); + socket.connectToHost(QHostAddress::LocalHost, serverPort); QVERIFY(socket.waitForConnected(5000)); QVERIFY(process.waitForFinished(30000)); @@ -628,8 +634,9 @@ void tst_QTcpServer::addressReusable() // Give the system some time. QTest::qSleep(10); - QTcpServer server; - QVERIFY(server.listen(QHostAddress::LocalHost, 49199)); + // listen again + QVERIFY2(server.listen(QHostAddress::LocalHost, serverPort), + qPrintable(server.errorString())); #endif } diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index 7e5666decd..f2c6b0871f 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -653,7 +653,7 @@ void tst_QUdpSocket::dualStack() QCOMPARE(dgram.senderAddress(), makeNonAny(v4Sock.localAddress(), QHostAddress::Null)); if (dgram.destinationPort() != -1) { QCOMPARE(dgram.destinationPort(), int(dualSock.localPort())); - QVERIFY(dgram.destinationAddress().isEqual(dualSock.localAddress())); + QVERIFY(dgram.destinationAddress().isEqual(makeNonAny(dualSock.localAddress(), QHostAddress::LocalHost))); } else { qInfo("Getting IPv4 destination address failed."); } diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index bd3816378e..afcf5fe722 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -1455,7 +1455,7 @@ public: config(QSslConfiguration::defaultConfiguration()), ignoreSslErrors(true), peerVerifyMode(QSslSocket::AutoVerifyPeer), - protocol(QSsl::TlsV1_0), + protocol(QSsl::TlsV1_2), m_keyFile(keyFile), m_certFile(certFile), m_interFile(interFile) diff --git a/tests/auto/other/android/CMakeLists.txt b/tests/auto/other/android/CMakeLists.txt deleted file mode 100644 index c2749825ac..0000000000 --- a/tests/auto/other/android/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -# Generated from android.pro. - -##################################################################### -## tst_android Test: -##################################################################### - -qt_internal_add_test(tst_android - SOURCES - tst_android.cpp -) - -if(ANDROID) - set_property(TARGET tst_android APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR - ${CMAKE_CURRENT_SOURCE_DIR}/testdata - ) - # QTBUG-88840 # special case - qt_android_generate_deployment_settings(tst_android) # special case -endif() - -#### Keys ignored in scope 1:.:.:android.pro:<TRUE>: -# DISTFILES = "testdata/assets/test.txt" diff --git a/tests/auto/other/android/testdata/assets/test.txt b/tests/auto/other/android/testdata/assets/test.txt deleted file mode 100644 index 61e2c47c25..0000000000 --- a/tests/auto/other/android/testdata/assets/test.txt +++ /dev/null @@ -1 +0,0 @@ -FooBar
\ No newline at end of file diff --git a/tests/auto/other/android/tst_android.cpp b/tests/auto/other/android/tst_android.cpp deleted file mode 100644 index 3a00d9414b..0000000000 --- a/tests/auto/other/android/tst_android.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** 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 <jni.h> - -#include <QTest> -#include <QtCore/qnativeinterface.h> -#include <QtCore/qjniobject.h> - -class tst_Android : public QObject -{ -Q_OBJECT -private slots: - void assetsRead(); - void assetsNotWritable(); - void testAndroidSdkVersion(); - void testAndroidActivity(); -}; - -void tst_Android::assetsRead() -{ - { - QFile file(QStringLiteral("assets:/test.txt")); - QVERIFY(file.open(QIODevice::ReadOnly)); - QCOMPARE(file.readAll(), QByteArray("FooBar")); - } - - { - QFile file(QStringLiteral("assets:/test.txt")); - QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); - QCOMPARE(file.readAll(), QByteArray("FooBar")); - } -} - -void tst_Android::assetsNotWritable() -{ - QFile file(QStringLiteral("assets:/test.txt")); - QVERIFY(!file.open(QIODevice::WriteOnly)); - QVERIFY(!file.open(QIODevice::ReadWrite)); - QVERIFY(!file.open(QIODevice::Append)); -} - -void tst_Android::testAndroidSdkVersion() -{ - QVERIFY(QNativeInterface::QAndroidApplication::sdkVersion() > 0); -} - -void tst_Android::testAndroidActivity() -{ - QJniObject activity = QNativeInterface::QAndroidApplication::context(); - QVERIFY(activity.isValid()); - QVERIFY(activity.callMethod<jboolean>("isTaskRoot")); -} - -QTEST_MAIN(tst_Android) -#include "tst_android.moc" - diff --git a/tests/auto/other/gestures/BLACKLIST b/tests/auto/other/gestures/BLACKLIST index 5b4f12b80d..494005abf3 100644 --- a/tests/auto/other/gestures/BLACKLIST +++ b/tests/auto/other/gestures/BLACKLIST @@ -1,32 +1,10 @@ -[] -rhel -centos -ubuntu-18.04 -ubuntu-20.04 [customGesture] opensuse-leap # QTBUG-67254 opensuse-42.3 -[graphicsItemGesture] -ubuntu-18.04 -ubuntu-20.04 -rhel -centos -[graphicsItemTreeGesture] -ubuntu-18.04 -ubuntu-20.04 -[graphicsView] -ubuntu-18.04 -ubuntu-20.04 -rhel -centos -[explicitGraphicsObjectTarget] -ubuntu-18.04 +[panelPropagation] ubuntu-20.04 -rhel -centos -[autoCancelGestures2] -ubuntu-18.04 +ubuntu-22.04 ci +[panelStacksBehindParent] ubuntu-20.04 -rhel -centos +ubuntu-22.04 ci diff --git a/tests/auto/other/gestures/tst_gestures.cpp b/tests/auto/other/gestures/tst_gestures.cpp index 48cd355554..1fb7b5c343 100644 --- a/tests/auto/other/gestures/tst_gestures.cpp +++ b/tests/auto/other/gestures/tst_gestures.cpp @@ -342,6 +342,8 @@ private slots: void testQGestureRecognizerCleanup(); void testReuseCanceledGestures(); void bug_13501_gesture_not_accepted(); +private: + QPoint m_availableTopLeft; }; void tst_Gestures::initTestCase() @@ -349,6 +351,8 @@ void tst_Gestures::initTestCase() CustomGesture::GestureType = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer); QVERIFY(CustomGesture::GestureType != Qt::GestureType(0)); QVERIFY(CustomGesture::GestureType != Qt::CustomGesture); + const QScreen *screen = QGuiApplication::primaryScreen(); + m_availableTopLeft = screen->availableGeometry().topLeft(); } void tst_Gestures::cleanupTestCase() @@ -824,6 +828,7 @@ void tst_Gestures::graphicsItemGesture() QGraphicsScene scene; QGraphicsView view(&scene); view.setWindowFlags(Qt::X11BypassWindowManagerHint); + view.move(m_availableTopLeft); GestureItem *item = new GestureItem("item"); scene.addItem(item); @@ -886,6 +891,7 @@ void tst_Gestures::graphicsView() QGraphicsScene scene; QGraphicsView view(&scene); view.setWindowFlags(Qt::X11BypassWindowManagerHint); + view.move(m_availableTopLeft); GestureItem *item = new GestureItem("item"); scene.addItem(item); @@ -951,6 +957,7 @@ void tst_Gestures::graphicsItemTreeGesture() QGraphicsScene scene; QGraphicsView view(&scene); view.setWindowFlags(Qt::X11BypassWindowManagerHint); + view.move(m_availableTopLeft); GestureItem *item1 = new GestureItem("item1"); item1->setPos(100, 100); @@ -1008,6 +1015,7 @@ void tst_Gestures::explicitGraphicsObjectTarget() QGraphicsScene scene; QGraphicsView view(&scene); view.setWindowFlags(Qt::X11BypassWindowManagerHint); + view.move(m_availableTopLeft); GestureItem *item1 = new GestureItem("item1"); scene.addItem(item1); @@ -1557,6 +1565,7 @@ void tst_Gestures::autoCancelGestures2() QGraphicsScene scene; QGraphicsView view(&scene); view.setWindowFlags(Qt::X11BypassWindowManagerHint); + view.move(m_availableTopLeft); MockItem *parent = new MockItem("parent"); GestureItem *child = new GestureItem("child"); @@ -1593,6 +1602,7 @@ void tst_Gestures::graphicsViewParentPropagation() QGraphicsScene scene; QGraphicsView view(&scene); view.setWindowFlags(Qt::X11BypassWindowManagerHint); + view.move(m_availableTopLeft); GestureItem *item0 = new GestureItem("item0"); scene.addItem(item0); @@ -1653,6 +1663,7 @@ void tst_Gestures::panelPropagation() QGraphicsScene scene; QGraphicsView view(&scene); view.setWindowFlags(Qt::X11BypassWindowManagerHint); + view.move(m_availableTopLeft); GestureItem *item0 = new GestureItem("item0"); scene.addItem(item0); @@ -1777,6 +1788,7 @@ void tst_Gestures::panelStacksBehindParent() QGraphicsScene scene; QGraphicsView view(&scene); view.setWindowFlags(Qt::X11BypassWindowManagerHint); + view.move(m_availableTopLeft); GestureItem *item1 = new GestureItem("item1"); item1->grabGesture(CustomGesture::GestureType); @@ -1964,6 +1976,7 @@ void tst_Gestures::partialGesturePropagation() QGraphicsScene scene; QGraphicsView view(&scene); view.setWindowFlags(Qt::X11BypassWindowManagerHint); + view.move(m_availableTopLeft); GestureItem *item1 = new GestureItem("item1"); item1->grabGesture(CustomGesture::GestureType); @@ -2176,6 +2189,7 @@ void tst_Gestures::testReuseCanceledGestures() mw.setWindowFlags(Qt::X11BypassWindowManagerHint); QGraphicsView *gv = new QGraphicsView(&mw); QGraphicsScene *scene = new QGraphicsScene; + mw.move(m_availableTopLeft); gv->setScene(scene); scene->setSceneRect(0,0,100,100); diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index b7b50ccf4f..6f6bbb8ae1 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -4225,6 +4225,47 @@ void tst_QAccessibility::focusChild() QVERIFY(child); QCOMPARE(child->text(QAccessible::Name), QStringLiteral("Klimt")); } + { + QWidget window; + // takes the initial focus + QLineEdit lineEdit; + QComboBox comboBox; + comboBox.addItems({"One", "Two", "Three"}); + QComboBox editableComboBox; + editableComboBox.setEditable(true); + editableComboBox.addItems({"A", "B", "C"}); + QVBoxLayout vbox; + vbox.addWidget(&lineEdit); + vbox.addWidget(&comboBox); + vbox.addWidget(&editableComboBox); + window.setLayout(&vbox); + + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QTestAccessibility::clearEvents(); + QAccessibleInterface *iface = nullptr; + + comboBox.setFocus(); + { + QAccessibleEvent focusEvent(&comboBox, QAccessible::Focus); + QVERIFY(QTestAccessibility::containsEvent(&focusEvent)); + } + iface = QAccessible::queryAccessibleInterface(&comboBox); + QVERIFY(iface); + QCOMPARE(iface->focusChild(), nullptr); + + editableComboBox.setFocus(); + // Qt updates about the editable combobox, not the lineedit, as the + // combobox is the lineedit's focus proxy. + { + QAccessibleEvent focusEvent(&editableComboBox, QAccessible::Focus); + QVERIFY(QTestAccessibility::containsEvent(&focusEvent)); + } + iface = QAccessible::queryAccessibleInterface(&editableComboBox); + QVERIFY(iface); + QVERIFY(iface->focusChild()); + QCOMPARE(iface->focusChild()->role(), QAccessible::EditableText); + } } diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h index 74fa06ab29..642d4af9cf 100644 --- a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h +++ b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h @@ -207,6 +207,14 @@ public: if ( port > 0 ) cName += QLatin1Char(':') + QString::number( port ); + if (driver == "QSQLITE") { + // Since the database for sqlite is generated at runtime it's always + // available, but we use QTempDir so it's always in a different + // location. Thus, let's ignore the path completely. + cName = "SQLite"; + qInfo("SQLite will use the database located at %ls", qUtf16Printable(dbName)); + } + db = QSqlDatabase::addDatabase( driver, cName ); if ( !db.isValid() ) { @@ -275,7 +283,7 @@ public: } QTemporaryDir *sqLiteDir = dbDir(); if (sqLiteDir) { - addDb(QStringLiteral("QSQLITE"), QDir::toNativeSeparators(sqLiteDir->path() + QStringLiteral("/foo.db"))); + addDb(QStringLiteral("QSQLITE"), QDir::toNativeSeparators(sqLiteDir->path() + QStringLiteral("/sqlite.db"))); added = true; } return added; diff --git a/tests/auto/testlib/selftests/catch_p_p.h b/tests/auto/testlib/selftests/catch_p_p.h index 9034ac2204..f22183557d 100644 --- a/tests/auto/testlib/selftests/catch_p_p.h +++ b/tests/auto/testlib/selftests/catch_p_p.h @@ -1,6 +1,6 @@ /* - * Catch v2.13.9 - * Generated: 2022-04-12 22:37:23.260201 + * Catch v2.13.10 + * Generated: 2022-10-16 11:01:23.452308 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved. @@ -15,7 +15,7 @@ #define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MINOR 13 -#define CATCH_VERSION_PATCH 9 +#define CATCH_VERSION_PATCH 10 #ifdef __clang__ # pragma clang system_header @@ -7395,8 +7395,6 @@ namespace Catch { template <typename T, bool Destruct> struct ObjectStorage { - using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type; - ObjectStorage() : data() {} ObjectStorage(const ObjectStorage& other) @@ -7439,7 +7437,7 @@ namespace Catch { return *static_cast<T*>(static_cast<void*>(&data)); } - TStorage data; + struct { alignas(T) unsigned char data[sizeof(T)]; } data; }; } @@ -7949,7 +7947,7 @@ namespace Catch { #if defined(__i386__) || defined(__x86_64__) #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ #elif defined(__aarch64__) - #define CATCH_TRAP() __asm__(".inst 0xd4200000") + #define CATCH_TRAP() __asm__(".inst 0xd43e0000") #endif #elif defined(CATCH_PLATFORM_IPHONE) @@ -13560,7 +13558,7 @@ namespace Catch { // Handle list request if( Option<std::size_t> listed = list( m_config ) ) - return static_cast<int>( *listed ); + return (std::min) (MaxExitCode, static_cast<int>(*listed)); TestGroup tests { m_config }; auto const totals = tests.execute(); @@ -15393,7 +15391,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 13, 9, "", 0 ); + static Version version( 2, 13, 10, "", 0 ); return version; } @@ -17528,12 +17526,20 @@ namespace Catch { #ifndef __OBJC__ +#ifndef CATCH_INTERNAL_CDECL +#ifdef _MSC_VER +#define CATCH_INTERNAL_CDECL __cdecl +#else +#define CATCH_INTERNAL_CDECL +#endif +#endif + #if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) // Standard C/C++ Win32 Unicode wmain entry point -extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { +extern "C" int CATCH_INTERNAL_CDECL wmain (int argc, wchar_t * argv[], wchar_t * []) { #else // Standard C/C++ main entry point -int main (int argc, char * argv[]) { +int CATCH_INTERNAL_CDECL main (int argc, char * argv[]) { #endif return Catch::Session().run( argc, argv ); diff --git a/tests/auto/testlib/selftests/qt_attribution.json b/tests/auto/testlib/selftests/qt_attribution.json index 6c483749a1..3a126f59ed 100644 --- a/tests/auto/testlib/selftests/qt_attribution.json +++ b/tests/auto/testlib/selftests/qt_attribution.json @@ -8,7 +8,7 @@ "Description": "Catch2 is a multi-paradigm test framework for C++.", "Homepage": "https://github.com/catchorg/Catch2", - "Version": "2.13.8", + "Version": "2.13.10", "License": "Boost Software License 1.0", "LicenseId": "BSL-1.0", "LicenseFile": "CATCH_LICENSE.txt", diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp index 69853f3d95..f8461b1b5c 100644 --- a/tests/auto/testlib/selftests/tst_selftests.cpp +++ b/tests/auto/testlib/selftests/tst_selftests.cpp @@ -660,6 +660,11 @@ bool TestLogger::shouldIgnoreTest(const QString &test) const return true; #endif + if (!qEnvironmentVariableIsEmpty("WAYLAND_DISPLAY")) { + qDebug() << "TestLogger::shouldIgnoreTest() ignore" << test << "on wayland/xwayland!"; + return true; + } + if (test == "deleteLater" || test == "deleteLater_noApp" || test == "mouse") return true; // Missing expectation files diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index c9c80f1e3b..9227cc26d3 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -87,6 +87,15 @@ const char *string_hash_hash = STRING_HASH_HASH("baz"); #endif +#if defined(Q_MOC_RUN) || __cplusplus > 202002L +/* Check that nested inline namespaces are at least not causing moc to break. + Check it even outside of C++20 mode as moc gets passed the wrong __cplusplus version + and also to increase coverage, given how few C++20 configurations exist in the CI at the time + of writing this comment. +*/ +namespace A::inline B {} +#endif + Q_DECLARE_METATYPE(const QMetaObject*); namespace TestNonQNamespace { diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp index 6d1e48fd88..1af016e4f0 100644 --- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp +++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp @@ -46,6 +46,7 @@ #include <private/qguiapplication_p.h> #include <qpa/qplatformtheme.h> #include <qpa/qplatformtheme_p.h> +#include <qpa/qplatformintegration.h> QT_FORWARD_DECLARE_CLASS(QDialog) @@ -309,6 +310,10 @@ void tst_QDialog::showAsTool() { if (QStringList{"xcb", "offscreen"}.contains(QGuiApplication::platformName())) QSKIP("activeWindow() is not respected by all Xcb window managers and the offscreen plugin"); + + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + DummyDialog testWidget; testWidget.resize(200, 200); testWidget.setWindowTitle(QTest::currentTestFunction()); diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp index 043e7e6365..aecee0500b 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp @@ -133,6 +133,10 @@ private slots: void dontShowCompleterOnRoot(); void nameFilterParsing_data(); void nameFilterParsing(); +#if QT_CONFIG(settings) + void settingsCompatibility_data(); + void settingsCompatibility(); +#endif private: void cleanupSettingsFile(); @@ -473,6 +477,47 @@ void tst_QFileDialog2::task180459_lastDirectory() delete dlg; } +#if QT_CONFIG(settings) +void tst_QFileDialog2::settingsCompatibility_data() +{ + QTest::addColumn<QString>("qtVersion"); + QTest::addColumn<QDataStream::Version>("dsVersion"); + QTest::newRow("6.2.3") << "6.2.3" << QDataStream::Qt_6_0; + QTest::newRow("6.5") << "6.5" << QDataStream::Qt_5_0; + QTest::newRow("15.5.2") << "5.15.2" << QDataStream::Qt_5_15; + QTest::newRow("15.5.9") << "5.15.9" << QDataStream::Qt_5_15; +} + +void tst_QFileDialog2::settingsCompatibility() +{ + static const QByteArray ba32 = QByteArrayLiteral("\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xF7\x00\x00\x00\x04\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00""d\xFF\xFF\xFF\xFF\x00\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x01\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00""B\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00n\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\xE8\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"); + static const QByteArray ba64 = QByteArrayLiteral("\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xF7\x00\x00\x00\x04\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00""d\xFF\xFF\xFF\xFF\x00\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x01\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00""B\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00n\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\xE8\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"); + QFETCH(QString, qtVersion); + QFETCH(QDataStream::Version, dsVersion); + // Create a header view, convert template to target format and store it in settings + { + QSettings settings(QSettings::UserScope, "QtProject"); + settings.beginGroup("FileDialog"); + settings.setValue("sidebarWidth", 93); // random value + settings.setValue("shortcuts", QStringList({settings.fileName(), "/tmp"})); + settings.setValue("qtVersion", qtVersion); + settings.setValue("treeViewHeader", dsVersion < QDataStream::Qt_6_0 ? ba32 : ba64); + settings.endGroup(); + } + // Create a file dialog, read settings write them back + { + QFileDialog fd; + } + // Read back settings and compare byte array + QSettings settings(QSettings::UserScope, "QtProject"); + settings.beginGroup("FileDialog"); + const QByteArray savedState = settings.value("treeViewHeader").toByteArray(); + if (QT_VERSION_MAJOR == 6 && QT_VERSION_MINOR == 2) + QCOMPARE(savedState, ba64); + else + QCOMPARE(savedState, ba32); +} +#endif class FilterDirModel : public QSortFilterProxyModel diff --git a/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp b/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp index ba8a309674..fe491179d2 100644 --- a/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp @@ -179,11 +179,11 @@ void tst_QGraphicsEffectSource::init() QVERIFY(effect); QVERIFY(item); QVERIFY(effect->source()); - effect->reset(); effect->storeDeviceDependentStuff = false; effect->doNothingInDraw = false; - item->reset(); QCoreApplication::processEvents(); // Process all queued paint events + effect->reset(); + item->reset(); } void tst_QGraphicsEffectSource::graphicsItem() diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index ae94c9bda4..1988a9cca7 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -829,6 +829,9 @@ void tst_QGraphicsProxyWidget::focusProxy_QTBUG_51856() } }; + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QGraphicsScene scene; QGraphicsView view(&scene); SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget; @@ -1346,6 +1349,9 @@ static QList<QRect> rects(const QRegion ®ion) void tst_QGraphicsProxyWidget::scrollUpdate() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + ScrollWidget *widget = new ScrollWidget; QGraphicsScene scene; @@ -3088,6 +3094,9 @@ void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget_data() void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QFETCH(bool, bypass); std::unique_ptr<QWidget> widgetGuard(new QWidget); @@ -3301,6 +3310,9 @@ public: void tst_QGraphicsProxyWidget::inputMethod() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QGraphicsScene scene; // check that the proxy is initialized with the correct input method sensitivity diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index 8e44912d37..817677dfc5 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -3548,6 +3548,9 @@ void tst_QGraphicsView::embeddedViewsWithFocus() void focusOutEvent(QFocusEvent *) override { --focusCount; } }; + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QGraphicsScene innerScene; FocusWidget *innerWidget = new FocusWidget; innerScene.addWidget(innerWidget); diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp index ba0e4b223c..782cb1b2f5 100644 --- a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp @@ -42,6 +42,8 @@ #include <qstylefactory.h> #include <qscreen.h> #include <qsignalspy.h> +#include <private/qguiapplication_p.h> +#include <qpa/qplatformintegration.h> typedef QList<QGraphicsItem *> QGraphicsItemList; @@ -169,8 +171,16 @@ private slots: void QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems(); void QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems(); void QTBUG_45867_send_itemChildAddedChange_to_parent(); + +private: + static bool hasWindowActivation(); }; +bool tst_QGraphicsWidget::hasWindowActivation() +{ + return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)); +} + // Subclass that exposes the protected functions. class SubQGraphicsWidget : public QGraphicsWidget { public: @@ -1074,7 +1084,10 @@ void tst_QGraphicsWidget::initStyleOption() QGraphicsView view(&scene); view.resize(300, 300); view.show(); - QVERIFY(QTest::qWaitForWindowActive(&view)); + if (hasWindowActivation()) + QVERIFY(QTest::qWaitForWindowActive(&view)); + else + QVERIFY(QTest::qWaitForWindowExposed(&view)); view.setAlignment(Qt::AlignTop | Qt::AlignLeft); SubQGraphicsWidget *widget = new SubQGraphicsWidget; @@ -1088,10 +1101,12 @@ void tst_QGraphicsWidget::initStyleOption() QFETCH(bool, enabled); widget->setEnabled(enabled); QFETCH(bool, focus); - if (focus) { - widget->setFlag(QGraphicsItem::ItemIsFocusable, true); - widget->setFocus(); - QVERIFY(widget->hasFocus()); + if (hasWindowActivation()) { + if (focus) { + widget->setFlag(QGraphicsItem::ItemIsFocusable, true); + widget->setFocus(); + QVERIFY(widget->hasFocus()); + } } QFETCH(bool, underMouse); if (underMouse) { @@ -1110,8 +1125,10 @@ void tst_QGraphicsWidget::initStyleOption() bool isEnabled = option.state & QStyle::State_Enabled; QCOMPARE(isEnabled, enabled); - bool hasFocus = option.state & QStyle::State_HasFocus; - QCOMPARE(hasFocus, focus); + if (hasWindowActivation()) { + bool hasFocus = option.state & QStyle::State_HasFocus; + QCOMPARE(hasFocus, focus); + } bool isUnderMouse = option.state & QStyle::State_MouseOver; QCOMPARE(isUnderMouse, underMouse); // if (layoutDirection != Qt::LeftToRight) @@ -1738,6 +1755,9 @@ void tst_QGraphicsWidget::verifyFocusChain() void tst_QGraphicsWidget::updateFocusChainWhenChildDie() { + if (!hasWindowActivation()) + QSKIP("Window activation is not supported"); + const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry(); QGraphicsScene scene; QGraphicsView view(&scene); diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index ec37a53263..47f8ab4be8 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -3103,6 +3103,9 @@ void tst_QAbstractItemView::mouseSelection() */ void tst_QAbstractItemView::scrollerSmoothScroll() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QListWidget view; view.setAutoScroll(true); view.setVerticalScrollMode(QListView::ScrollPerPixel); @@ -3172,6 +3175,9 @@ void tst_QAbstractItemView::inputMethodOpensEditor_data() void tst_QAbstractItemView::inputMethodOpensEditor() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QTableWidget tableWidget(50, 50); tableWidget.setEditTriggers(QAbstractItemView::AnyKeyPressed); for (int r = 0; r < 50; ++r) { diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp index 025cebb15f..2574a89112 100644 --- a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp +++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp @@ -437,6 +437,9 @@ void tst_QAction::disableShortcutInMenuAction_data() void tst_QAction::disableShortcutInMenuAction() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QFETCH(QByteArray, property); QMainWindow mw; diff --git a/tests/auto/widgets/kernel/qapplication/BLACKLIST b/tests/auto/widgets/kernel/qapplication/BLACKLIST index 364a2abe4f..7f4dd88261 100644 --- a/tests/auto/widgets/kernel/qapplication/BLACKLIST +++ b/tests/auto/widgets/kernel/qapplication/BLACKLIST @@ -1,6 +1,7 @@ [sendEventsOnProcessEvents] ubuntu-20.04 ubuntu-22.04 +rhel-9.0 [touchEventPropagation] # QTBUG-66745 opensuse-leap diff --git a/tests/auto/widgets/kernel/qapplication/CMakeLists.txt b/tests/auto/widgets/kernel/qapplication/CMakeLists.txt index 3bb7e31691..ab87a66a8b 100644 --- a/tests/auto/widgets/kernel/qapplication/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qapplication/CMakeLists.txt @@ -3,3 +3,8 @@ add_subdirectory(desktopsettingsaware) add_subdirectory(modal) add_subdirectory(test) + +add_dependencies(tst_qapplication + desktopsettingsaware_helper + modal_helper +) diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index d5f107a5fa..ee7475ae37 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -1602,6 +1602,9 @@ void tst_QApplication::activateDeactivateEvent() int argc = 0; QApplication app(argc, nullptr); + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + Window w1; Window w2; diff --git a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp index 2cf2462fd5..cd57c90f29 100644 --- a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp +++ b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp @@ -235,6 +235,9 @@ void tst_QGridLayout::badDistributionBug() void tst_QGridLayout::setMinAndMaxSize() { + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("This test crashes on Wayland, see also QTBUG-107184"); + QWidget widget; setFrameless(&widget); QGridLayout layout(&widget); diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST index 24387635b4..7bd4c0a304 100644 --- a/tests/auto/widgets/kernel/qwidget/BLACKLIST +++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST @@ -3,11 +3,6 @@ ubuntu-16.04 [restoreVersion1Geometry] ubuntu-16.04 -[focusProxyAndInputMethods] -rhel-7.6 -centos -opensuse-leap -ubuntu [raise] opensuse-leap # QTBUG-68175 diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index e36f6334c9..67a671ed41 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -189,6 +189,7 @@ private slots: void reverseTabOrder(); void tabOrderWithProxy(); void tabOrderWithProxyDisabled(); + void tabOrderWithProxyOutOfOrder(); void tabOrderWithCompoundWidgets(); void tabOrderWithCompoundWidgetsNoFocusPolicy(); void tabOrderNoChange(); @@ -387,7 +388,6 @@ private slots: void openModal_taskQTBUG_5804(); void focusProxy(); - void focusProxyAndInputMethods(); #ifdef QT_BUILD_INTERNAL void scrollWithoutBackingStore(); #endif @@ -1848,8 +1848,11 @@ public: setObjectName(name); lineEdit1 = new QLineEdit; + lineEdit1->setObjectName(name + "/lineEdit1"); lineEdit2 = new QLineEdit; + lineEdit2->setObjectName(name + "/lineEdit2"); lineEdit3 = new QLineEdit; + lineEdit3->setObjectName(name + "/lineEdit3"); lineEdit3->setEnabled(false); QHBoxLayout* hbox = new QHBoxLayout(this); @@ -2095,6 +2098,24 @@ void tst_QWidget::tabOrderWithProxyDisabled() qPrintable(QApplication::focusWidget()->objectName())); } +//#define DEBUG_FOCUS_CHAIN +static void dumpFocusChain(QWidget *start, bool bForward, const char *desc = nullptr) +{ +#ifdef DEBUG_FOCUS_CHAIN + qDebug() << "Dump focus chain, start:" << start << "isForward:" << bForward << desc; + QWidget *cur = start; + do { + qDebug() << "-" << cur; + auto widgetPrivate = static_cast<QWidgetPrivate *>(qt_widget_private(cur)); + cur = bForward ? widgetPrivate->focus_next : widgetPrivate->focus_prev; + } while (cur != start); +#else + Q_UNUSED(start); + Q_UNUSED(bForward); + Q_UNUSED(desc); +#endif +} + void tst_QWidget::tabOrderWithCompoundWidgets() { if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) @@ -2198,22 +2219,65 @@ static QList<QWidget *> getFocusChain(QWidget *start, bool bForward) return ret; } -//#define DEBUG_FOCUS_CHAIN -static void dumpFocusChain(QWidget *start, bool bForward, const char *desc = nullptr) +void tst_QWidget::tabOrderWithProxyOutOfOrder() { -#ifdef DEBUG_FOCUS_CHAIN - qDebug() << "Dump focus chain, start:" << start << "isForward:" << bForward << desc; - QWidget *cur = start; - do { - qDebug() << cur; - auto widgetPrivate = static_cast<QWidgetPrivate *>(qt_widget_private(cur)); - cur = bForward ? widgetPrivate->focus_next : widgetPrivate->focus_prev; - } while (cur != start); -#else - Q_UNUSED(start); - Q_UNUSED(bForward); - Q_UNUSED(desc); -#endif + Container container; + container.setWindowTitle(QLatin1String(QTest::currentTestFunction())); + + // important to create the widgets with parent so that they are + // added to the focus chain already now, and with the buttonBox + // before the outsideButton. + QWidget buttonBox(&container); + buttonBox.setObjectName("buttonBox"); + QPushButton outsideButton(&container); + outsideButton.setObjectName("outsideButton"); + + container.box->addWidget(&outsideButton); + container.box->addWidget(&buttonBox); + QCOMPARE(getFocusChain(&container, true), + QList<QWidget*>({&container, &buttonBox, &outsideButton})); + + // this now adds okButon and cancelButton to the focus chain, + // after the outsideButton - so the outsideButton is in between + // the buttonBox and the children of the buttonBox! + QPushButton okButton(&buttonBox); + okButton.setObjectName("okButton"); + QPushButton cancelButton(&buttonBox); + cancelButton.setObjectName("cancelButton"); + QCOMPARE(getFocusChain(&container, true), + QList<QWidget*>({&container, &buttonBox, &outsideButton, &okButton, &cancelButton})); + + // by setting the okButton as the focusProxy, the outsideButton becomes + // unreachable when navigating the focus chain as the buttonBox is in front + // of, and proxies to the okButton behind the outsideButton. setFocusProxy + // must fix that by moving the buttonBox in front of the first sibling of + // the proxy. + buttonBox.setFocusProxy(&okButton); + QCOMPARE(getFocusChain(&container, true), + QList<QWidget*>({&container, &outsideButton, &buttonBox, &okButton, &cancelButton})); + + container.show(); + container.activateWindow(); + QApplication::setActiveWindow(&container); + if (!QTest::qWaitForWindowActive(&container)) + QSKIP("Window failed to activate, skipping test"); + + QCOMPARE(QApplication::focusWidget(), &outsideButton); + container.tab(); + QCOMPARE(QApplication::focusWidget(), &okButton); + container.tab(); + QCOMPARE(QApplication::focusWidget(), &cancelButton); + container.tab(); + QCOMPARE(QApplication::focusWidget(), &outsideButton); + + container.backTab(); + QCOMPARE(QApplication::focusWidget(), &cancelButton); + container.backTab(); + QCOMPARE(QApplication::focusWidget(), &okButton); + container.backTab(); + QCOMPARE(QApplication::focusWidget(), &outsideButton); + container.backTab(); + QCOMPARE(QApplication::focusWidget(), &cancelButton); } void tst_QWidget::tabOrderWithCompoundWidgetsNoFocusPolicy() @@ -3494,7 +3558,8 @@ void tst_QWidget::raise() for (int i = 0; i < 5; ++i) child2->raise(); - QTest::qWait(50); + QVERIFY(QTest::qWaitForWindowExposed(child2)); + QApplication::processEvents(); // process events that could be triggered by raise(); for (UpdateWidget *child : qAsConst(allChildren)) { int expectedPaintEvents = child == child2 ? 1 : 0; @@ -3523,6 +3588,7 @@ void tst_QWidget::raise() onTop->show(); QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); QTRY_VERIFY(onTop->numPaintEvents > 0); + QApplication::processEvents(); // process remaining paint events if there's more than one onTop->reset(); // Reset all the children. @@ -3531,7 +3597,8 @@ void tst_QWidget::raise() for (int i = 0; i < 5; ++i) child3->raise(); - QTest::qWait(50); + QVERIFY(QTest::qWaitForWindowExposed(child3)); + QApplication::processEvents(); // process events that could be triggered by raise(); QCOMPARE(onTop->numPaintEvents, 0); QCOMPARE(onTop->numZOrderChangeEvents, 0); @@ -3797,6 +3864,13 @@ void tst_QWidget::saveRestoreGeometry() QVERIFY(QTest::qWaitForWindowExposed(&widget)); QApplication::processEvents(); + + /* --------------------------------------------------------------------- + * This test function is likely to flake when debugged with Qt Creator. + * (29px offset making the following QTRY_VERIFY2 fail) + * --------------------------------------------------------------------- + */ + QTRY_VERIFY2(HighDpi::fuzzyCompare(widget.pos(), position, m_fuzz), qPrintable(HighDpi::msgPointMismatch(widget.pos(), position))); QCOMPARE(widget.size(), size); @@ -5373,8 +5447,8 @@ void tst_QWidget::setWindowGeometry_data() void tst_QWidget::setWindowGeometry() { - if (m_platform == QStringLiteral("xcb")) - QSKIP("X11: Skip this test due to Window manager positioning issues."); + if (m_platform == QStringLiteral("xcb") || m_platform.startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("X11/Wayland: Skip this test due to Window manager positioning issues."); QFETCH(Rects, rects); QFETCH(int, windowFlags); @@ -7296,6 +7370,9 @@ void tst_QWidget::renderInvisible() if (m_platform == QStringLiteral("xcb")) QSKIP("QTBUG-26424"); + if (m_platform.startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Wayland: Skip this test, see also QTBUG-107157"); + QScopedPointer<QCalendarWidget> calendar(new QCalendarWidget); calendar->move(m_availableTopLeft + QPoint(100, 100)); calendar->setWindowTitle(QLatin1String(QTest::currentTestFunction())); @@ -9909,6 +9986,9 @@ void tst_QWidget::enterLeaveOnWindowShowHide_data() */ void tst_QWidget::enterLeaveOnWindowShowHide() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QFETCH(Qt::WindowType, windowType); class Widget : public QWidget { @@ -10683,34 +10763,6 @@ void tst_QWidget::focusProxy() QCOMPARE(container2->focusOutCount, 1); } -void tst_QWidget::focusProxyAndInputMethods() -{ - if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) - QSKIP("Window activation is not supported."); - QScopedPointer<QWidget> toplevel(new QWidget(nullptr, Qt::X11BypassWindowManagerHint)); - toplevel->setWindowTitle(QLatin1String(QTest::currentTestFunction())); - toplevel->resize(200, 200); - toplevel->setAttribute(Qt::WA_InputMethodEnabled, true); - - QWidget *child = new QWidget(toplevel.data()); - child->setFocusProxy(toplevel.data()); - child->setAttribute(Qt::WA_InputMethodEnabled, true); - - toplevel->setFocusPolicy(Qt::WheelFocus); - child->setFocusPolicy(Qt::WheelFocus); - - QVERIFY(!child->hasFocus()); - QVERIFY(!toplevel->hasFocus()); - - toplevel->show(); - QVERIFY(QTest::qWaitForWindowExposed(toplevel.data())); - QApplication::setActiveWindow(toplevel.data()); - QVERIFY(QTest::qWaitForWindowActive(toplevel.data())); - QVERIFY(toplevel->hasFocus()); - QVERIFY(child->hasFocus()); - QCOMPARE(qApp->focusObject(), toplevel.data()); -} - #ifdef QT_BUILD_INTERNAL class scrollWidgetWBS : public QWidget { @@ -11198,6 +11250,9 @@ public: void tst_QWidget::touchEventSynthesizedMouseEvent() { + if (m_platform.startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("This test failed on Wayland. See also QTBUG-107157."); + { // Simple case, we ignore the touch events, we get mouse events instead TouchMouseWidget widget; @@ -12450,6 +12505,9 @@ void tst_QWidget::setParentChangesFocus() void tst_QWidget::activateWhileModalHidden() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QDialog dialog; dialog.setWindowModality(Qt::ApplicationModal); dialog.show(); diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp index f4a6380caa..498bd5c268 100644 --- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp +++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp @@ -1475,6 +1475,9 @@ void tst_QWidget_window::mouseMoveWithPopup_data() void tst_QWidget_window::mouseMoveWithPopup() { + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Wayland: Skip this test, see also QTBUG-107154"); + QFETCH(Qt::WindowType, windowType); class Window : public QWidget @@ -1652,6 +1655,9 @@ void tst_QWidget_window::mouseMoveWithPopup() void tst_QWidget_window::resetFocusObjectOnDestruction() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QSignalSpy focusObjectChangedSpy(qApp, &QGuiApplication::focusObjectChanged); // single top level widget that has focus diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp index f355ea6e2c..0585d03983 100644 --- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp @@ -2350,11 +2350,19 @@ void tst_QStyleSheetStyle::placeholderColor() QLineEdit le2; le2.setEnabled(false); le1.ensurePolished(); - QCOMPARE(le1.palette().placeholderText(), red); + QColor phColor = le1.palette().placeholderText().color(); + QCOMPARE(phColor.rgb(), red.rgb()); + QVERIFY(phColor.alpha() < red.alpha()); + le2.ensurePolished(); - QCOMPARE(le2.palette().placeholderText(), red); + phColor = le2.palette().placeholderText().color(); + QCOMPARE(phColor.rgb(), red.rgb()); + QVERIFY(phColor.alpha() < red.alpha()); + le2.setEnabled(true); - QCOMPARE(le2.palette().placeholderText(), red); + phColor = le2.palette().placeholderText().color(); + QCOMPARE(phColor.rgb(), red.rgb()); + QVERIFY(phColor.alpha() < red.alpha()); } void tst_QStyleSheetStyle::enumPropertySelector_data() diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp index 3dad8968fb..575847db91 100644 --- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp +++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp @@ -1250,21 +1250,33 @@ void tst_QDockWidget::unplugAndResize(QMainWindow* mainWindow, QDockWidget* dw, return; } + // Remember size for comparison with unplugged object +#ifdef Q_OS_LINUX + const int pluggedWidth = dw->width(); + const int pluggedHeight = dw->height(); +#endif + // unplug and resize a dock Widget qCDebug(lcTestDockWidget) << "*** unplug and resize" << dw->objectName(); QPoint pos1 = dw->mapToGlobal(dw->rect().center()); pos1.rx() += mx; pos1.ry() += my; moveDockWidget(dw, pos1, dw->mapToGlobal(dw->rect().center())); - //QTest::mousePress(dw, Qt::LeftButton, Qt::KeyboardModifiers(), dw->mapFromGlobal(pos1)); QTRY_VERIFY(dw->isFloating()); + // Unplugged object's size may differ max. by 2x frame size +#ifdef Q_OS_LINUX + const int xMargin = 2 * dw->frameSize().width(); + const int yMargin = 2 * dw->frameSize().height(); + QVERIFY(dw->height() - pluggedHeight <= xMargin); + QVERIFY(dw->width() - pluggedWidth <= yMargin); +#endif + qCDebug(lcTestDockWidget) << "Resizing" << dw->objectName() << "to" << size; dw->setFixedSize(size); QTest::qWait(waitingTime); qCDebug(lcTestDockWidget) << "Move" << dw->objectName() << "to its home" << dw->mapFromGlobal(home); dw->move(home); - //moveDockWidget(dw, home); } bool tst_QDockWidget::checkFloatingTabs(QMainWindow* mainWindow, QPointer<QDockWidgetGroupWindow> &ftabs, const QList<QDockWidget*> &dwList) const @@ -1330,6 +1342,8 @@ void tst_QDockWidget::xcbMessageHandler(QtMsgType type, const QMessageLogContext // test floating tabs and item_tree consistency void tst_QDockWidget::floatingTabs() { + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Test skipped on Wayland."); #ifdef Q_OS_WIN QSKIP("Test skipped on Windows platforms"); #endif // Q_OS_WIN diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp index 4942c52b95..e9aa9205c6 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp +++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp @@ -635,7 +635,7 @@ void tst_QOpenGLWidget::stackWidgetOpaqueChildIsVisible() // Switch to the QOpenGLWidget. stack.setCurrentIndex(1); - QTRY_COMPARE(clearWidget->m_paintCalled, true); + QTRY_VERIFY(clearWidget->m_paintCalled); // Resize the tested region to be half size in the middle, because some OSes make the widget // have rounded corners (e.g. OSX), and the grabbed window pixmap will not coincide perfectly @@ -743,10 +743,10 @@ void tst_QOpenGLWidget::paintWhileHidden() // on-screen at the point when update() is called. w->setVisible(false); - w->m_paintCalled = 0; + w->m_paintCalled = false; w->update(); w->setVisible(true); - QTRY_VERIFY(w->m_paintCalled > 0); + QTRY_VERIFY(w->m_paintCalled); } class StaticTextPainterWidget : public QOpenGLWidget diff --git a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp index 9438ea5322..37a80ee281 100644 --- a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp +++ b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp @@ -933,55 +933,56 @@ void tst_QSplitter::rubberBandNotInSplitter() void tst_QSplitter::task187373_addAbstractScrollAreas_data() { - QTest::addColumn<QString>("className"); + QTest::addColumn<QByteArray>("className"); QTest::addColumn<bool>("addInConstructor"); QTest::addColumn<bool>("addOutsideConstructor"); - QStringList classNames; - classNames << QLatin1String("QGraphicsView"); - classNames << QLatin1String("QMdiArea"); - classNames << QLatin1String("QScrollArea"); - classNames << QLatin1String("QTextEdit"); - classNames << QLatin1String("QTreeView"); - - foreach (QString className, classNames) { - QTest::newRow(qPrintable(className + QLatin1String(" 1"))) << className << false << true; - QTest::newRow(qPrintable(className + QLatin1String(" 2"))) << className << true << false; - QTest::newRow(qPrintable(className + QLatin1String(" 3"))) << className << true << true; + QList<QByteArray> classNames{ + "QGraphicsView", + "QMdiArea", + "QScrollArea", + "QTextEdit", + "QTreeView" + }; + + for (const auto &className : qAsConst(classNames)) { + QTest::newRow(qPrintable(className + " 1")) << className << false << true; + QTest::newRow(qPrintable(className + " 2")) << className << true << false; + QTest::newRow(qPrintable(className + " 3")) << className << true << true; } } static QAbstractScrollArea *task187373_createScrollArea( - QSplitter *splitter, const QString &className, bool addInConstructor) + QSplitter *splitter, const QByteArray &className, bool addInConstructor) { - if (className == QLatin1String("QGraphicsView")) + if (className == "QGraphicsView") return new QGraphicsView(addInConstructor ? splitter : 0); - if (className == QLatin1String("QMdiArea")) + if (className == "QMdiArea") return new QMdiArea(addInConstructor ? splitter : 0); - if (className == QLatin1String("QScrollArea")) + if (className == "QScrollArea") return new QScrollArea(addInConstructor ? splitter : 0); - if (className == QLatin1String("QTextEdit")) + if (className == "QTextEdit") return new QTextEdit(addInConstructor ? splitter : 0); - if (className == QLatin1String("QTreeView")) + if (className == "QTreeView") return new QTreeView(addInConstructor ? splitter : 0); return 0; } void tst_QSplitter::task187373_addAbstractScrollAreas() { - QFETCH(QString, className); + QFETCH(QByteArray, className); QFETCH(bool, addInConstructor); QFETCH(bool, addOutsideConstructor); QVERIFY(addInConstructor || addOutsideConstructor); - QSplitter *splitter = new QSplitter; - splitter->show(); - QVERIFY(splitter->isVisible()); + QSplitter splitter; + splitter.show(); + QVERIFY(splitter.isVisible()); - QAbstractScrollArea *w = task187373_createScrollArea(splitter, className, addInConstructor); + QAbstractScrollArea *w = task187373_createScrollArea(&splitter, className, addInConstructor); QVERIFY(w); if (addOutsideConstructor) - splitter->addWidget(w); + splitter.addWidget(w); QTRY_VERIFY(w->isVisible()); QVERIFY(!w->isHidden()); diff --git a/tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss b/tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss new file mode 100644 index 0000000000..7d54a74fe5 --- /dev/null +++ b/tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss @@ -0,0 +1,10 @@ +QTreeView { + alternate-background-color: yellow; + show-decoration-selected: 1; +} +QTreeView::item:selected:active { + background: qlineargradient(x1:0, y1:0 x2: 0, y2: 1, stop: 0 #fea1f1 stop: 1 #567dbc) +} +QTreeView::branch { + border: 2px +} diff --git a/tests/benchmarks/CMakeLists.txt b/tests/benchmarks/CMakeLists.txt index a59ba35e50..b6f45aab4f 100644 --- a/tests/benchmarks/CMakeLists.txt +++ b/tests/benchmarks/CMakeLists.txt @@ -1,7 +1,6 @@ # Generated from benchmarks.pro. add_subdirectory(corelib) -add_subdirectory(sql) if(TARGET Qt::DBus) add_subdirectory(dbus) endif() @@ -11,6 +10,9 @@ endif() if(TARGET Qt::Network) add_subdirectory(network) endif() +if(TARGET Qt::Sql) + add_subdirectory(sql) +endif() if(TARGET Qt::Test) add_subdirectory(testlib) endif() diff --git a/tests/benchmarks/corelib/text/qlocale/main.cpp b/tests/benchmarks/corelib/text/qlocale/main.cpp index 887053ae4a..b9a6ec0a19 100644 --- a/tests/benchmarks/corelib/text/qlocale/main.cpp +++ b/tests/benchmarks/corelib/text/qlocale/main.cpp @@ -28,6 +28,7 @@ #include <QLocale> #include <QTest> +#include <limits> class tst_QLocale : public QObject { @@ -54,6 +55,12 @@ private Q_SLOTS: void toUpper_QLocale_2(); void toUpper_QString(); void number_QString(); + void toLongLong_data(); + void toLongLong(); + void toULongLong_data(); + void toULongLong(); + void toDouble_data(); + void toDouble(); }; static QString data() @@ -392,6 +399,270 @@ void tst_QLocale::number_QString() } } +template <typename Integer> +void toWholeCommon_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<QString>("locale"); + QTest::addColumn<bool>("good"); + QTest::addColumn<Integer>("expected"); + + QTest::newRow("C: empty") + << QStringLiteral("") << QStringLiteral("C") << false << Integer(0ull); + QTest::newRow("C: 0") << QStringLiteral("0") << QStringLiteral("C") << true << Integer(0ull); + QTest::newRow("C: 1234") + << QStringLiteral("1234") << QStringLiteral("C") << true << Integer(1234ull); + // C locale omits grouping, but doesn't reject it. + QTest::newRow("C: 1,234") + << QStringLiteral("1,234") << QStringLiteral("C") << true << Integer(1234ull); + QTest::newRow("C: 123456789") + << QStringLiteral("123456789") << QStringLiteral("C") << true << Integer(123456789ull); + QTest::newRow("C: 123,456,789") + << QStringLiteral("123,456,789") + << QStringLiteral("C") << true << Integer(123456789ull); + + QTest::newRow("en: empty") + << QStringLiteral("") << QStringLiteral("en") << false << Integer(0ull); + QTest::newRow("en: 0") << QStringLiteral("0") << QStringLiteral("en") << true << Integer(0ull); + QTest::newRow("en: 1234") + << QStringLiteral("1234") << QStringLiteral("en") << true << Integer(1234ull); + QTest::newRow("en: 1,234") + << QStringLiteral("1,234") << QStringLiteral("en") << true << Integer(1234ull); + QTest::newRow("en: 123,456,789") + << QStringLiteral("123,456,789") + << QStringLiteral("en") << true << Integer(123456789ull); + QTest::newRow("en: 123456789") + << QStringLiteral("123456789") + << QStringLiteral("en") << true << Integer(123456789ull); + + QTest::newRow("de: empty") + << QStringLiteral("") << QStringLiteral("de") << false << Integer(0ull); + QTest::newRow("de: 0") << QStringLiteral("0") << QStringLiteral("de") << true << Integer(0ull); + QTest::newRow("de: 1234") + << QStringLiteral("1234") << QStringLiteral("de") << true << Integer(1234ull); + QTest::newRow("de: 1.234") + << QStringLiteral("1.234") << QStringLiteral("de") << true << Integer(1234ull); + QTest::newRow("de: 123.456.789") + << QStringLiteral("123.456.789") + << QStringLiteral("de") << true << Integer(123456789ull); + QTest::newRow("de: 123456789") + << QStringLiteral("123456789") << QStringLiteral("de") << true << Integer(123456789ull); + + // Locales with non-single-character signs: + QTest::newRow("ar_EG: +403") // Arabic, Egypt + << QStringLiteral("\u061c+\u0664\u0660\u0663") + << QStringLiteral("ar_EG") << true << Integer(403ull); + QTest::newRow("ar_EG: !403") // Only first character of the sign + << QStringLiteral("\u061c\u0664\u0660\u0663") + << QStringLiteral("ar_EG") << false << Integer(0ull); + QTest::newRow("fa_IR: +403") // Farsi, Iran + << QStringLiteral("\u200e+\u06f4\u06f0\u06f3") + << QStringLiteral("fa_IR") << true << Integer(403ull); + QTest::newRow("fa_IR: !403") // Only first character of sign + << QStringLiteral("\u200e\u06f4\u06f0\u06f3") + << QStringLiteral("fa_IR") << false << Integer(0ull); +} + +void tst_QLocale::toLongLong_data() +{ + toWholeCommon_data<qlonglong>(); + + QTest::newRow("C: -1234") << QStringLiteral("-1234") << QStringLiteral("C") << true << -1234ll; + QTest::newRow("C: -123456789") + << QStringLiteral("-123456789") << QStringLiteral("C") << true << -123456789ll; + QTest::newRow("C: qlonglong-max") + << QStringLiteral("9223372036854775807") << QStringLiteral("C") << true + << std::numeric_limits<qlonglong>::max(); + QTest::newRow("C: qlonglong-min") + << QStringLiteral("-9223372036854775808") << QStringLiteral("C") << true + << std::numeric_limits<qlonglong>::min(); + + // Locales with multi-character signs: + QTest::newRow("ar_EG: -403") // Arabic, Egypt + << QStringLiteral("\u061c-\u0664\u0660\u0663") + << QStringLiteral("ar_EG") << true << -403ll; + QTest::newRow("fa_IR: -403") // Farsi, Iran + << QStringLiteral("\u200e\u2212\u06f4\u06f0\u06f3") + << QStringLiteral("fa_IR") << true << -403ll; +} + +void tst_QLocale::toLongLong() +{ + QFETCH(QString, text); + QFETCH(QString, locale); + QFETCH(bool, good); + QFETCH(qlonglong, expected); + + const QLocale loc(locale); + qlonglong actual = expected; + bool ok = false; + QBENCHMARK { + actual = loc.toLongLong(text, &ok); + } + QEXPECT_FAIL("ar_EG: +403", "Code wrongly assumes single character, QTBUG-107801", Abort); + QEXPECT_FAIL("ar_EG: -403", "Code wrongly assumes single character, QTBUG-107801", Abort); + QEXPECT_FAIL("fa_IR: +403", "Code wrongly assumes single character, QTBUG-107801", Abort); + QEXPECT_FAIL("fa_IR: -403", "Code wrongly assumes single character, QTBUG-107801", Abort); + QCOMPARE(ok, good); + QCOMPARE(actual, expected); +} + +void tst_QLocale::toULongLong_data() +{ + toWholeCommon_data<qulonglong>(); + + QTest::newRow("C: qlonglong-max + 1") + << QStringLiteral("9223372036854775808") << QStringLiteral("C") << true + << (qulonglong(std::numeric_limits<qlonglong>::max()) + 1); + QTest::newRow("C: qulonglong-max") + << QStringLiteral("18446744073709551615") << QStringLiteral("C") << true + << std::numeric_limits<qulonglong>::max(); +} + +void tst_QLocale::toULongLong() +{ + QFETCH(QString, text); + QFETCH(QString, locale); + QFETCH(bool, good); + QFETCH(qulonglong, expected); + + const QLocale loc(locale); + qulonglong actual = expected; + bool ok = false; + QBENCHMARK { + actual = loc.toULongLong(text, &ok); + } + QEXPECT_FAIL("ar_EG: +403", "Code wrongly assumes single character, QTBUG-107801", Abort); + QEXPECT_FAIL("fa_IR: +403", "Code wrongly assumes single character, QTBUG-107801", Abort); + QCOMPARE(ok, good); + QCOMPARE(actual, expected); +} + + +void tst_QLocale::toDouble_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<QString>("locale"); + QTest::addColumn<bool>("good"); + QTest::addColumn<double>("expected"); + + QTest::newRow("C: empty") << QStringLiteral("") << QStringLiteral("C") << false << 0.0; + QTest::newRow("C: 0") << QStringLiteral("0") << QStringLiteral("C") << true << 0.0; + QTest::newRow("C: 0.12340") + << QStringLiteral("0.12340") << QStringLiteral("C") << true << 0.12340; + QTest::newRow("C: -0.12340") + << QStringLiteral("-0.12340") << QStringLiteral("C") << true << -0.12340; + QTest::newRow("C: −0.12340") + << QStringLiteral("\u2212" "0.12340") << QStringLiteral("C") << true << -0.12340; + QTest::newRow("C: 1.0e-4") << QStringLiteral("1.0e-4") << QStringLiteral("C") << true << 1.0e-4; + QTest::newRow("C: 1.0e−4") + << QStringLiteral("1.0e\u2212" "4") << QStringLiteral("C") << true << 1.0e-4; + QTest::newRow("C: 1.0e+4") << QStringLiteral("1.0e+4") << QStringLiteral("C") << true << 1.0e+4; + QTest::newRow("C: 10.e+3") << QStringLiteral("10.e+3") << QStringLiteral("C") << true << 1.0e+4; + QTest::newRow("C: 10e+3.") + << QStringLiteral("10e+3.") << QStringLiteral("C") << false << 0.0; // exp...dot + QTest::newRow("C: 1e4") << QStringLiteral("1e4") << QStringLiteral("C") << true << 1.0e+4; + + // NaN and infinity: + QTest::newRow("C: nan") << QStringLiteral("nan") << QStringLiteral("C") << true << qQNaN(); + QTest::newRow("C: NaN") << QStringLiteral("NaN") << QStringLiteral("C") << true << qQNaN(); + QTest::newRow("C: -nan") << QStringLiteral("-nan") << QStringLiteral("C") << false << 0.0; + QTest::newRow("C: +nan") << QStringLiteral("+nan") << QStringLiteral("C") << false << 0.0; + QTest::newRow("C: inf") << QStringLiteral("inf") << QStringLiteral("C") << true << qInf(); + QTest::newRow("C: Inf") << QStringLiteral("Inf") << QStringLiteral("C") << true << qInf(); + QTest::newRow("C: +inf") << QStringLiteral("+inf") << QStringLiteral("C") << true << qInf(); + QTest::newRow("C: -inf") << QStringLiteral("-inf") << QStringLiteral("C") << true << -qInf(); + + // Wantonly long-form representations, with trailing and leading zeros: + QTest::newRow("C: 1e-64 long-form") + << (QStringLiteral("0.") + QString(63, u'0') + u'1' + QString(962, u'0')) + << QStringLiteral("C") << true << 1e-64; + QTest::newRow("C: 1e+64 long-form") + << (QString(961, u'0') + u'1' + QString(64, u'0') + QStringLiteral(".0")) + << QStringLiteral("C") << true << 1e+64; + QTest::newRow("C: long-form 1 via e+64") + << (QStringLiteral("0.") + QString(63, u'0') + u'1' + QString(962, u'0') + + QStringLiteral("e+64")) + << QStringLiteral("C") << true << 1.0; + QTest::newRow("C: long-form 1 via e-64") + << (QString(961, u'0') + u'1' + QString(64, u'0') + QStringLiteral(".0e-64")) + << QStringLiteral("C") << true << 1.0; + QTest::newRow("C: 12345678.9") + << QStringLiteral("12345678.9") << QStringLiteral("C") << true << 12345678.9; + + // With and without grouping, en vs de for flipped separators: + QTest::newRow("en: 12345678.9") + << QStringLiteral("12345678.9") << QStringLiteral("en") << true << 12345678.9; + QTest::newRow("en: 12,345,678.9") + << QStringLiteral("12,345,678.9") << QStringLiteral("en") << true << 12'345'678.9; + QTest::newRow("de: 12345678,9") + << QStringLiteral("12345678,9") << QStringLiteral("de") << true << 12345678.9; + QTest::newRow("de: 12.345.678,9") + << QStringLiteral("12.345.678,9") << QStringLiteral("de") << true << 12'345'678.9; + + // NaN and infinity are locale-independent (for now - QTBUG-95460) + QTest::newRow("cy: nan") << QStringLiteral("nan") << QStringLiteral("cy") << true << qQNaN(); + QTest::newRow("cy: NaN") << QStringLiteral("NaN") << QStringLiteral("cy") << true << qQNaN(); + QTest::newRow("cy: -nan") << QStringLiteral("-nan") << QStringLiteral("cy") << false << 0.0; + QTest::newRow("cy: +nan") << QStringLiteral("+nan") << QStringLiteral("cy") << false << 0.0; + QTest::newRow("cy: inf") << QStringLiteral("inf") << QStringLiteral("cy") << true << qInf(); + QTest::newRow("cy: Inf") << QStringLiteral("Inf") << QStringLiteral("cy") << true << qInf(); + QTest::newRow("cy: +inf") << QStringLiteral("+inf") << QStringLiteral("cy") << true << qInf(); + QTest::newRow("cy: -inf") << QStringLiteral("-inf") << QStringLiteral("cy") << true << -qInf(); + // Samples ready for QTBUG-95460: + QTest::newRow("en: ∞") + << QStringLiteral("\u221e") << QStringLiteral("en") << true << qInf(); + QTest::newRow("ga: Nuimh") + << QStringLiteral("Nuimh") << QStringLiteral("ga") << true << qQNaN(); + + // Locales with multi-character exponents: + QTest::newRow("sv_SE: 4e-3") // Swedish, Sweden + << QStringLiteral("4\u00d7" "10^\u2212" "03") + << QStringLiteral("sv_SE") << true << 4e-3; + QTest::newRow("sv_SE: 4x-3") // Only first character of exponent + << QStringLiteral("4\u00d7\u2212" "03") << QStringLiteral("sv_SE") << false << 0.0; + QTest::newRow("se_NO: 4e-3") // Northern Sami, Norway + << QStringLiteral("4\u00b7" "10^\u2212" "03") + << QStringLiteral("se_NO") << true << 4e-3; + QTest::newRow("se_NO: 4x-3") // Only first character of exponent + << QStringLiteral("4\u00b7\u2212" "03") + << QStringLiteral("se_NO") << false << 0.0; + QTest::newRow("ar_EG: 4e-3") // Arabic, Egypt + << QStringLiteral("\u0664\u0627\u0633\u061c-\u0660\u0663") + << QStringLiteral("ar_EG") << true << 4e-3; + QTest::newRow("ar_EG: 4x-3") // Only first character of exponent + << QStringLiteral("\u0664\u0627\u061c-\u0660\u0663") + << QStringLiteral("ar_EG") << false << 0.0; + QTest::newRow("ar_EG: 4e!3") // Only first character of sign + << QStringLiteral("\u0664\u0627\u0633\u061c\u0660\u0663") + << QStringLiteral("ar_EG") << false << 0.0; + QTest::newRow("ar_EG: 4x!3") // Only first character of sign and exponent + << QStringLiteral("\u0664\u0627\u061c\u0660\u0663") + << QStringLiteral("ar_EG") << false << 0.0; +} + +void tst_QLocale::toDouble() +{ + QFETCH(QString, text); + QFETCH(QString, locale); + QFETCH(bool, good); + QFETCH(double, expected); + + const QLocale loc(locale); + double actual = expected; + bool ok = false; + QBENCHMARK { + actual = loc.toDouble(text, &ok); + } + QEXPECT_FAIL("sv_SE: 4e-3", "Code wrongly assumes single character, QTBUG-107801", Abort); + QEXPECT_FAIL("se_NO: 4e-3", "Code wrongly assumes single character, QTBUG-107801", Abort); + QEXPECT_FAIL("ar_EG: 4e-3", "Code wrongly assumes single character, QTBUG-107801", Abort); + QEXPECT_FAIL("en: ∞", "Localized infinity support missing: QTBUG-95460", Abort); + QEXPECT_FAIL("ga: Nuimh", "Localized NaN support missing: QTBUG-95460", Abort); + QCOMPARE(ok, good); + QCOMPARE(actual, expected); +} + QTEST_MAIN(tst_QLocale) #include "main.moc" diff --git a/tests/benchmarks/corelib/text/qstring/main.cpp b/tests/benchmarks/corelib/text/qstring/main.cpp index 0214931b71..ff47ee1a2a 100644 --- a/tests/benchmarks/corelib/text/qstring/main.cpp +++ b/tests/benchmarks/corelib/text/qstring/main.cpp @@ -28,6 +28,7 @@ #include <QStringList> #include <QFile> #include <QTest> +#include <limits> class tst_QString: public QObject { @@ -48,6 +49,14 @@ private slots: void toCaseFolded_data(); void toCaseFolded(); + // Parsing: + void toLongLong_data(); + void toLongLong(); + void toULongLong_data(); + void toULongLong(); + void toDouble_data(); + void toDouble(); + private: void section_data_impl(bool includeRegExOnly = true); template <typename RX> void section_impl(); @@ -187,6 +196,155 @@ void tst_QString::toCaseFolded() } } +template <typename Integer> +void toWholeCommon_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<int>("base"); + QTest::addColumn<bool>("good"); + QTest::addColumn<Integer>("expected"); + + QTest::newRow("empty") << QStringLiteral("") << 10 << false << Integer(0ull); + QTest::newRow("0") << QStringLiteral("0") << 10 << true << Integer(0ull); + QTest::newRow("1234") << QStringLiteral("1234") << 10 << true << Integer(1234ull); + QTest::newRow("1,234") << QStringLiteral("1,234") << 10 << false << Integer(0ull); + QTest::newRow("123456789") + << QStringLiteral("123456789") << 10 << true << Integer(123456789ull); + QTest::newRow("bad1dea, base 16") + << QStringLiteral("bad1dea") << 16 << true << Integer(0xBAD1DEAull); + QTest::newRow("bad1dea, base 10") << QStringLiteral("bad1dea") << 10 << false << Integer(0ull); + QTest::newRow("42, base 13") << QStringLiteral("42") << 13 << true << Integer(6ull * 9ull); + QTest::newRow("242, base 8") << QStringLiteral("242") << 8 << true << Integer(0242ull); + QTest::newRow("495, base 8") << QStringLiteral("495") << 8 << false << Integer(0ull); + QTest::newRow("101101, base 2") + << QStringLiteral("101101") << 2 << true << Integer(0b101101ull); + QTest::newRow("ad, base 30") << QStringLiteral("ad") << 30 << true << Integer(313ull); +} + +void tst_QString::toLongLong_data() +{ + toWholeCommon_data<qlonglong>(); + + QTest::newRow("-1234") << QStringLiteral("-1234") << 10 << true << -1234ll; + QTest::newRow("-123456789") << QStringLiteral("-123456789") << 10 << true << -123456789ll; + QTest::newRow("-bad1dea, base 16") << QStringLiteral("-bad1dea") << 16 << true << -0xBAD1DEAll; + QTest::newRow("-242, base 8") << QStringLiteral("-242") << 8 << true << -0242ll; + QTest::newRow("-101101, base 2") << QStringLiteral("-101101") << 2 << true << -0b101101ll; + QTest::newRow("-ad, base 30") << QStringLiteral("-ad") << 30 << true << -313ll; + + QTest::newRow("qlonglong-max") + << QStringLiteral("9223372036854775807") << 10 << true + << std::numeric_limits<qlonglong>::max(); + QTest::newRow("qlonglong-min") + << QStringLiteral("-9223372036854775808") << 10 << true + << std::numeric_limits<qlonglong>::min(); + QTest::newRow("qlonglong-max, base 2") + << QString(63, u'1') << 2 << true << std::numeric_limits<qlonglong>::max(); + QTest::newRow("qlonglong-min, base 2") + << (QStringLiteral("-1") + QString(63, u'0')) << 2 << true + << std::numeric_limits<qlonglong>::min(); + QTest::newRow("qlonglong-max, base 16") + << (QChar(u'7') + QString(15, u'f')) << 16 << true + << std::numeric_limits<qlonglong>::max(); + QTest::newRow("qlonglong-min, base 16") + << (QStringLiteral("-8") + QString(15, u'0')) << 16 << true + << std::numeric_limits<qlonglong>::min(); +} + +void tst_QString::toLongLong() +{ + QFETCH(QString, text); + QFETCH(int, base); + QFETCH(bool, good); + QFETCH(qlonglong, expected); + + qlonglong actual = expected; + bool ok = false; + QBENCHMARK { + actual = text.toLongLong(&ok, base); + } + QCOMPARE(ok, good); + QCOMPARE(actual, expected); +} + +void tst_QString::toULongLong_data() +{ + toWholeCommon_data<qulonglong>(); + + QTest::newRow("qlonglong-max + 1") + << QStringLiteral("9223372036854775808") << 10 << true + << (qulonglong(std::numeric_limits<qlonglong>::max()) + 1); + QTest::newRow("qulonglong-max") + << QStringLiteral("18446744073709551615") << 10 << true + << std::numeric_limits<qulonglong>::max(); + QTest::newRow("qulonglong-max, base 2") + << QString(64, u'1') << 2 << true << std::numeric_limits<qulonglong>::max(); + QTest::newRow("qulonglong-max, base 16") + << QString(16, u'f') << 16 << true << std::numeric_limits<qulonglong>::max(); +} + +void tst_QString::toULongLong() +{ + QFETCH(QString, text); + QFETCH(int, base); + QFETCH(bool, good); + QFETCH(qulonglong, expected); + + qulonglong actual = expected; + bool ok = false; + QBENCHMARK { + actual = text.toULongLong(&ok, base); + } + QCOMPARE(ok, good); + QCOMPARE(actual, expected); +} + +void tst_QString::toDouble_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<bool>("good"); + QTest::addColumn<double>("expected"); + + QTest::newRow("empty") << QStringLiteral("") << false << 0.0; + QTest::newRow("0") << QStringLiteral("0") << true << 0.0; + QTest::newRow("0.12340") << QStringLiteral("0.12340") << true << 0.12340; + QTest::newRow("-0.12340") << QStringLiteral("-0.12340") << true << -0.12340; + QTest::newRow("epsilon") + << QStringLiteral("2.220446049e-16") << true << std::numeric_limits<double>::epsilon(); + QTest::newRow("1.0e-4") << QStringLiteral("1.0e-4") << true << 1.0e-4; + QTest::newRow("1.0e+4") << QStringLiteral("1.0e+4") << true << 1.0e+4; + QTest::newRow("10.e+3") << QStringLiteral("10.e+3") << true << 1.0e+4; + QTest::newRow("10e+3.") << QStringLiteral("10e+3.") << false << 0.0; + QTest::newRow("1e4") << QStringLiteral("1e4") << true << 1.0e+4; + QTest::newRow("1.0e-8") << QStringLiteral("1.0e-8") << true << 1.0e-8; + QTest::newRow("1.0e+8") << QStringLiteral("1.0e+8") << true << 1.0e+8; + + // NaN and infinity: + QTest::newRow("nan") << QStringLiteral("nan") << true << qQNaN(); + QTest::newRow("NaN") << QStringLiteral("NaN") << true << qQNaN(); + QTest::newRow("-nan") << QStringLiteral("-nan") << false << 0.0; + QTest::newRow("+nan") << QStringLiteral("+nan") << false << 0.0; + QTest::newRow("inf") << QStringLiteral("inf") << true << qInf(); + QTest::newRow("Inf") << QStringLiteral("Inf") << true << qInf(); + QTest::newRow("+inf") << QStringLiteral("+inf") << true << qInf(); + QTest::newRow("-inf") << QStringLiteral("-inf") << true << -qInf(); +} + +void tst_QString::toDouble() +{ + QFETCH(QString, text); + QFETCH(bool, good); + QFETCH(double, expected); + + double actual = expected; + bool ok = false; + QBENCHMARK { + actual = text.toDouble(&ok); + } + QCOMPARE(ok, good); + QCOMPARE(actual, expected); +} + QTEST_APPLESS_MAIN(tst_QString) #include "main.moc" diff --git a/tests/benchmarks/corelib/tools/qhash/main.h b/tests/benchmarks/corelib/tools/qhash/main.h index eca4b61d58..9ba0bcce34 100644 --- a/tests/benchmarks/corelib/tools/qhash/main.h +++ b/tests/benchmarks/corelib/tools/qhash/main.h @@ -35,7 +35,7 @@ struct Qt4String : QString }; QT_BEGIN_NAMESPACE -uint qHash(const Qt4String &); +size_t qHash(const Qt4String &); QT_END_NAMESPACE struct Qt50String : QString @@ -45,7 +45,7 @@ struct Qt50String : QString }; QT_BEGIN_NAMESPACE -uint qHash(const Qt50String &, uint seed = 0); +size_t qHash(const Qt50String &, size_t seed = 0); QT_END_NAMESPACE @@ -56,6 +56,6 @@ struct JavaString : QString }; QT_BEGIN_NAMESPACE -uint qHash(const JavaString &); +size_t qHash(const JavaString &); QT_END_NAMESPACE diff --git a/tests/benchmarks/corelib/tools/qhash/outofline.cpp b/tests/benchmarks/corelib/tools/qhash/outofline.cpp index 4e449e76b4..b23774fc07 100644 --- a/tests/benchmarks/corelib/tools/qhash/outofline.cpp +++ b/tests/benchmarks/corelib/tools/qhash/outofline.cpp @@ -30,9 +30,9 @@ QT_BEGIN_NAMESPACE -uint qHash(const Qt4String &str) +size_t qHash(const Qt4String &str) { - int n = str.length(); + qsizetype n = str.length(); const QChar *p = str.unicode(); uint h = 0; @@ -44,11 +44,11 @@ uint qHash(const Qt4String &str) return h; } -uint qHash(const Qt50String &key, uint seed) +size_t qHash(const Qt50String &key, size_t seed) { const QChar *p = key.unicode(); - int len = key.size(); - uint h = seed; + qsizetype len = key.size(); + size_t h = seed; for (int i = 0; i < len; ++i) h = 31 * h + p[i].unicode(); return h; @@ -65,10 +65,10 @@ uint qHash(const Qt50String &key, uint seed) // Still, we can avoid writing the multiplication as "(h << 5) - h" // -- the compiler will turn it into a shift and an addition anyway // (for instance, gcc 4.4 does that even at -O0). -uint qHash(const JavaString &str) +size_t qHash(const JavaString &str) { const unsigned short *p = (unsigned short *)str.constData(); - const int len = str.size(); + const qsizetype len = str.size(); uint h = 0; |