summaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp22
-rw-r--r--tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp122
-rw-r--r--tests/auto/corelib/io/qsettings/tst_qsettings.cpp4
-rw-r--r--tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp65
-rw-r--r--tests/auto/corelib/text/qchar/tst_qchar.cpp19
-rw-r--r--tests/auto/corelib/text/qlocale/tst_qlocale.cpp30
-rw-r--r--tests/auto/corelib/text/qstring/tst_qstring.cpp32
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp79
-rw-r--r--tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp16
-rw-r--r--tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp36
-rw-r--r--tests/auto/gui/painting/qpainter/tst_qpainter.cpp31
-rw-r--r--tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp14
-rw-r--r--tests/auto/network/access/http2/tst_http2.cpp9
-rw-r--r--tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp48
-rw-r--r--tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp1
-rw-r--r--tests/auto/tools/moc/enum_with_include.h5
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp95
-rw-r--r--tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp76
-rw-r--r--tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp23
-rw-r--r--tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp28
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp66
-rw-r--r--tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp69
22 files changed, 715 insertions, 175 deletions
diff --git a/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp b/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
index 3c77b1ba0b..212c0a2e13 100644
--- a/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
+++ b/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
@@ -126,7 +126,8 @@ public:
void tst_QtConcurrentIterateKernel::instantiate()
{
- startThreadEngine(new PrintFor(0, 40)).startBlocking();
+ auto future = startThreadEngine(new PrintFor(0, 40)).startAsynchronously();
+ future.waitForFinished();
QCOMPARE(iterations.loadRelaxed(), 40);
}
@@ -165,8 +166,10 @@ void tst_QtConcurrentIterateKernel::stresstest()
const int times = 50;
for (int i = 0; i < times; ++i) {
counter.storeRelaxed(0);
- CountFor f(0, iterations);
- f.startBlocking();
+ // ThreadEngine will delete f when it finishes
+ auto f = new CountFor(0, iterations);
+ auto future = f->startAsynchronously();
+ future.waitForFinished();
QCOMPARE(counter.loadRelaxed(), iterations);
}
}
@@ -174,8 +177,11 @@ void tst_QtConcurrentIterateKernel::stresstest()
void tst_QtConcurrentIterateKernel::noIterations()
{
const int times = 20000;
- for (int i = 0; i < times; ++i)
- startThreadEngine(new IterateKernel<TestIterator, void>(0, 0)).startBlocking();
+ for (int i = 0; i < times; ++i) {
+ auto future = startThreadEngine(new IterateKernel<TestIterator, void>(0, 0))
+ .startAsynchronously();
+ future.waitForFinished();
+ }
}
QMutex threadsMutex;
@@ -230,8 +236,10 @@ void tst_QtConcurrentIterateKernel::throttling()
threads.clear();
- ThrottleFor f(0, totalIterations);
- f.startBlocking();
+ // ThreadEngine will delete f when it finishes
+ auto f = new ThrottleFor(0, totalIterations);
+ auto future = f->startAsynchronously();
+ future.waitForFinished();
QCOMPARE(iterations.loadRelaxed(), totalIterations);
diff --git a/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp b/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
index d4c669cddc..ac7be7acdd 100644
--- a/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
+++ b/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
@@ -65,16 +65,9 @@ public:
void tst_QtConcurrentThreadEngine::runDirectly()
{
- {
- PrintUser engine;
- engine.startSingleThreaded();
- engine.startBlocking();
- }
- {
- PrintUser *engine = new PrintUser();
- QFuture<void> f = engine->startAsynchronously();
- f.waitForFinished();
- }
+ PrintUser *engine = new PrintUser();
+ QFuture<void> f = engine->startAsynchronously();
+ f.waitForFinished();
}
class StringResultUser : public ThreadEngine<QString>
@@ -106,8 +99,10 @@ public:
void tst_QtConcurrentThreadEngine::result()
{
- StringResultUser engine;
- QCOMPARE(*engine.startBlocking(), QString("Foo"));
+ // ThreadEngine will delete 'engine' when it finishes
+ auto engine = new StringResultUser();
+ auto future = engine->startAsynchronously();
+ QCOMPARE(future.result(), QString("Foo"));
}
class VoidResultUser : public ThreadEngine<void>
@@ -133,17 +128,9 @@ public:
void tst_QtConcurrentThreadEngine::runThroughStarter()
{
- {
- ThreadEngineStarter<QString> starter = startThreadEngine(new StringResultUser());
- QFuture<QString> f = starter.startAsynchronously();
- QCOMPARE(f.result(), QString("Foo"));
- }
-
- {
- ThreadEngineStarter<QString> starter = startThreadEngine(new StringResultUser());
- QString str = starter.startBlocking();
- QCOMPARE(str, QString("Foo"));
- }
+ ThreadEngineStarter<QString> starter = startThreadEngine(new StringResultUser());
+ QFuture<QString> f = starter.startAsynchronously();
+ QCOMPARE(f.result(), QString("Foo"));
}
class CancelUser : public ThreadEngine<void>
@@ -226,12 +213,6 @@ void tst_QtConcurrentThreadEngine::throttle()
f.waitForFinished();
QCOMPARE(count.loadRelaxed(), 0);
}
-
- for (int i = 0; i < repeats; ++i) {
- ThrottleAlwaysUser t;
- t.startBlocking();
- QCOMPARE(count.loadRelaxed(), 0);
- }
}
QSet<QThread *> threads;
@@ -266,40 +247,21 @@ public:
void tst_QtConcurrentThreadEngine::threadCount()
{
- //QTBUG-23333: This test is unstable
-
const int repeats = 10;
for (int i = 0; i < repeats; ++i) {
- ThreadCountUser t;
- t.startBlocking();
- int count = threads.count();
- int count_expected = QThreadPool::globalInstance()->maxThreadCount() + 1; // +1 for the main thread.
- if (count != count_expected)
- QEXPECT_FAIL("", "QTBUG-23333", Abort);
- QCOMPARE(count, count_expected);
-
(new ThreadCountUser())->startAsynchronously().waitForFinished();
- count = threads.count();
- count_expected = QThreadPool::globalInstance()->maxThreadCount();
- if (count != count_expected)
- QEXPECT_FAIL("", "QTBUG-23333", Abort);
- QCOMPARE(count, count_expected);
+ const auto count = threads.count();
+ const auto maxThreadCount = QThreadPool::globalInstance()->maxThreadCount();
+ QVERIFY(count <= maxThreadCount);
+ QVERIFY(!threads.contains(QThread::currentThread()));
}
// Set the finish flag immediately, this should give us one thread only.
for (int i = 0; i < repeats; ++i) {
- ThreadCountUser t(true /*finishImmediately*/);
- t.startBlocking();
- int count = threads.count();
- if (count != 1)
- QEXPECT_FAIL("", "QTBUG-23333", Abort);
- QCOMPARE(count, 1);
-
(new ThreadCountUser(true /*finishImmediately*/))->startAsynchronously().waitForFinished();
- count = threads.count();
- if (count != 1)
- QEXPECT_FAIL("", "QTBUG-23333", Abort);
+ const auto count = threads.count();
QCOMPARE(count, 1);
+ QVERIFY(!threads.contains(QThread::currentThread()));
}
}
@@ -438,7 +400,6 @@ public:
void tst_QtConcurrentThreadEngine::exceptions()
{
- // Asynchronous mode:
{
bool caught = false;
try {
@@ -451,32 +412,6 @@ void tst_QtConcurrentThreadEngine::exceptions()
QVERIFY2(caught, "did not get exception");
}
- // Blocking mode:
- // test throwing the exception from a worker thread.
- {
- bool caught = false;
- try {
- QtConcurrentExceptionThrower e(QThread::currentThread());
- e.startBlocking();
- } catch (const QException &) {
- caught = true;
- }
- QVERIFY2(caught, "did not get exception");
- }
-
- // test throwing the exception from the main thread (different code path)
- {
- bool caught = false;
- try {
- QtConcurrentExceptionThrower e(0);
- e.startBlocking();
- } catch (const QException &) {
- caught = true;
- }
- QVERIFY2(caught, "did not get exception");
- }
-
- // Asynchronous mode:
{
bool caught = false;
try {
@@ -488,31 +423,6 @@ void tst_QtConcurrentThreadEngine::exceptions()
}
QVERIFY2(caught, "did not get exception");
}
-
- // Blocking mode:
- // test throwing the exception from a worker thread.
- {
- bool caught = false;
- try {
- UnrelatedExceptionThrower e(QThread::currentThread());
- e.startBlocking();
- } catch (const QUnhandledException &) {
- caught = true;
- }
- QVERIFY2(caught, "did not get exception");
- }
-
- // test throwing the exception from the main thread (different code path)
- {
- bool caught = false;
- try {
- UnrelatedExceptionThrower e(0);
- e.startBlocking();
- } catch (const QUnhandledException &) {
- caught = true;
- }
- QVERIFY2(caught, "did not get exception");
- }
}
#endif
diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
index 84f4a47585..7c69f5f4b5 100644
--- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
+++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
@@ -742,6 +742,10 @@ void tst_QSettings::embeddedZeroByte_data()
QTest::newRow("@bytearray\\0") << QVariant(bytes);
QTest::newRow("@string\\0") << QVariant(QString::fromLatin1(bytes.data(), bytes.size()));
+
+ bytes = QByteArray("@\xdd\x7d", 3);
+ QTest::newRow("@-prefixed data") << QVariant(bytes);
+ QTest::newRow("@-prefixed data as string") << QVariant(QString::fromLatin1(bytes.data(), bytes.size()));
}
void tst_QSettings::embeddedZeroByte()
diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
index 1bd27cd0ce..3c0adda5de 100644
--- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
+++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
@@ -135,24 +135,53 @@ void tst_QTimer::timeout()
void tst_QTimer::remainingTime()
{
- QTimer timer;
- QSignalSpy timeoutSpy(&timer, &QTimer::timeout);
- timer.setTimerType(Qt::PreciseTimer);
- timer.start(200);
-
- QCOMPARE(timeoutSpy.count(), 0);
- QTest::qWait(50);
- QCOMPARE(timeoutSpy.count(), 0);
-
- int remainingTime = timer.remainingTime();
- QVERIFY2(remainingTime >= 50 && remainingTime <= 200, qPrintable(QString::number(remainingTime)));
-
- QVERIFY(timeoutSpy.wait());
- QCOMPARE(timeoutSpy.count(), 1);
-
- // the timer is still active, so it should have a non-zero remaining time
- remainingTime = timer.remainingTime();
- QVERIFY2(remainingTime >= 50, qPrintable(QString::number(remainingTime)));
+ QTimer tested;
+ tested.setTimerType(Qt::PreciseTimer);
+
+ QTimer tester;
+ tester.setTimerType(Qt::PreciseTimer);
+ tester.setSingleShot(true);
+
+ const int testedInterval = 200;
+ const int testerInterval = 50;
+ const int expectedRemainingTime = testedInterval - testerInterval;
+
+ int testIteration = 0;
+ const int desiredTestCount = 2;
+
+ auto connection = QObject::connect(&tested, &QTimer::timeout, [&tester]() {
+ // We let tested (which isn't a single-shot) run repeatedly, to verify
+ // it *does* repeat, and check that the single-shot tester, starting
+ // at the same time, does finish first each time, by about the right duration.
+ tester.start(); // Start tester again.
+ });
+
+ QObject::connect(&tester, &QTimer::timeout, [&]() {
+ const int remainingTime = tested.remainingTime();
+ // We expect that remainingTime is at most 150 and not overdue.
+ const bool remainingTimeInRange = remainingTime > 0
+ && remainingTime <= expectedRemainingTime;
+ if (remainingTimeInRange)
+ ++testIteration;
+ else
+ testIteration = desiredTestCount; // We are going to fail on QVERIFY2()
+ // below, so we don't want to iterate
+ // anymore and quickly exit the QTRY_...()
+ // with this failure.
+ if (testIteration == desiredTestCount)
+ QObject::disconnect(connection); // Last iteration, don't start tester again.
+ QVERIFY2(remainingTimeInRange, qPrintable("Remaining time "
+ + QByteArray::number(remainingTime) + "ms outside expected range (0ms, "
+ + QByteArray::number(expectedRemainingTime) + "ms]"));
+ });
+
+ tested.start(testedInterval);
+ tester.start(testerInterval); // Start tester for the 1st time.
+
+ // Test it desiredTestCount times, give it reasonable amount of time
+ // (twice as much as needed).
+ QTRY_COMPARE_WITH_TIMEOUT(testIteration, desiredTestCount,
+ testedInterval * desiredTestCount * 2);
}
void tst_QTimer::remainingTimeInitial_data()
diff --git a/tests/auto/corelib/text/qchar/tst_qchar.cpp b/tests/auto/corelib/text/qchar/tst_qchar.cpp
index cf4f6d21e2..1f6f36e972 100644
--- a/tests/auto/corelib/text/qchar/tst_qchar.cpp
+++ b/tests/auto/corelib/text/qchar/tst_qchar.cpp
@@ -980,6 +980,25 @@ void tst_QChar::normalization_manual()
QVERIFY(decomposed.normalized(QString::NormalizationForm_KD) == decomposed);
QVERIFY(decomposed.normalized(QString::NormalizationForm_KC) == composed);
}
+ // QTBUG-71894 - erratum fixed in Unicode 4.1.0; SCount bounds are < not <=
+ {
+ // Hangul compose, test 0x11a7:
+ const QChar c[] = { QChar(0xae30), QChar(0x11a7), {} };
+ const QChar d[] = { QChar(0x1100), QChar(0x1175), QChar(0x11a7), {} };
+ const QString composed(c, 2);
+ const QString decomposed(d, 3);
+
+ QCOMPARE(decomposed.normalized(QString::NormalizationForm_C), composed);
+ }
+ {
+ // Hangul compose, test 0x11c3:
+ const QChar c[] = { QChar(0xae30), QChar(0x11c3), {} };
+ const QChar d[] = { QChar(0x1100), QChar(0x1175), QChar(0x11c3), {} };
+ const QString composed(c, 2);
+ const QString decomposed(d, 3);
+
+ QCOMPARE(decomposed.normalized(QString::NormalizationForm_C), composed);
+ }
}
void tst_QChar::normalizationCorrections()
diff --git a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
index f924bd1560..43698e5a19 100644
--- a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
@@ -2983,13 +2983,13 @@ void tst_QLocale::bcp47Name()
class MySystemLocale : public QSystemLocale
{
public:
- MySystemLocale(const QLocale &locale) : m_locale(locale)
+ MySystemLocale(const QString &locale) : m_name(locale), m_locale(locale)
{
}
- QVariant query(QueryType /*type*/, QVariant /*in*/) const override
+ QVariant query(QueryType type, QVariant /*in*/) const override
{
- return QVariant();
+ return type == UILanguages ? QVariant(QStringList{m_name}) : QVariant();
}
QLocale fallbackUiLocale() const override
@@ -2998,16 +2998,32 @@ public:
}
private:
+ const QString m_name;
const QLocale m_locale;
};
void tst_QLocale::systemLocale_data()
{
+ // Test uses MySystemLocale, so is platform-independent.
QTest::addColumn<QString>("name");
QTest::addColumn<QLocale::Language>("language");
- QTest::addRow("catalan") << QString("ca") << QLocale::Catalan;
- QTest::addRow("ukrainian") << QString("uk") << QLocale::Ukrainian;
- QTest::addRow("german") << QString("de") << QLocale::German;
+ QTest::addColumn<QStringList>("uiLanguages");
+
+ QTest::addRow("catalan")
+ << QString("ca") << QLocale::Catalan
+ << QStringList{QStringLiteral("ca"), QStringLiteral("ca-ES"), QStringLiteral("ca-Latn-ES")};
+ QTest::addRow("ukrainian")
+ << QString("uk") << QLocale::Ukrainian
+ << QStringList{QStringLiteral("uk"), QStringLiteral("uk-UA"), QStringLiteral("uk-Cyrl-UA")};
+ QTest::addRow("german")
+ << QString("de") << QLocale::German
+ << QStringList{QStringLiteral("de"), QStringLiteral("de-DE"), QStringLiteral("de-Latn-DE")};
+ QTest::addRow("chinese-min")
+ << QString("zh") << QLocale::Chinese
+ << QStringList{QStringLiteral("zh"), QStringLiteral("zh-CN"), QStringLiteral("zh-Hans-CN")};
+ QTest::addRow("chinese-full")
+ << QString("zh-Hans-CN") << QLocale::Chinese
+ << QStringList{QStringLiteral("zh-Hans-CN"), QStringLiteral("zh"), QStringLiteral("zh-CN")};
}
void tst_QLocale::systemLocale()
@@ -3017,11 +3033,13 @@ void tst_QLocale::systemLocale()
QFETCH(QString, name);
QFETCH(QLocale::Language, language);
+ QFETCH(QStringList, uiLanguages);
{
MySystemLocale sLocale(name);
QCOMPARE(QLocale().language(), language);
QCOMPARE(QLocale::system().language(), language);
+ QCOMPARE(QLocale::system().uiLanguages(), uiLanguages);
}
QCOMPARE(QLocale(), originalLocale);
diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp
index 8f53824050..696b8159ac 100644
--- a/tests/auto/corelib/text/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp
@@ -600,6 +600,7 @@ private slots:
void isValidUtf16_data();
void isValidUtf16();
void unicodeStrings();
+ void vasprintfWithPrecision();
};
template <class T> const T &verifyZeroTermination(const T &t) { return t; }
@@ -1674,7 +1675,7 @@ void tst_QString::lastIndexOf()
QCOMPARE(haystack.lastIndexOf(needle.toLatin1(), from, cs), expected);
QCOMPARE(haystack.lastIndexOf(needle.toLatin1().data(), from, cs), expected);
- if (from >= -1 && from < haystack.size() && needle.size() > 0) {
+ if (from >= -1 && from < haystack.size()) {
// unfortunately, QString and QRegExp don't have the same out of bound semantics
// I think QString is wrong -- See file log for contact information.
{
@@ -7148,6 +7149,35 @@ void tst_QString::isValidUtf16()
QTEST(string.isValidUtf16(), "valid");
}
+static QString doVasprintf(const char *msg, ...) {
+ va_list args;
+ va_start(args, msg);
+ const QString result = QString::vasprintf(msg, args);
+ va_end(args);
+ return result;
+}
+
+void tst_QString::vasprintfWithPrecision()
+{
+ {
+ const char *msg = "Endpoint %.*s with";
+ static const char arg0[3] = { 'a', 'b', 'c' };
+ static const char arg1[4] = { 'a', 'b', 'c', '\0' };
+ QCOMPARE(doVasprintf(msg, 3, arg0), QStringLiteral("Endpoint abc with"));
+ QCOMPARE(doVasprintf(msg, 9, arg1), QStringLiteral("Endpoint abc with"));
+ QCOMPARE(doVasprintf(msg, 0, nullptr), QStringLiteral("Endpoint with"));
+ }
+
+ {
+ const char *msg = "Endpoint %.*ls with";
+ static const ushort arg0[3] = { 'a', 'b', 'c' };
+ static const ushort arg1[4] = { 'a', 'b', 'c', '\0' };
+ QCOMPARE(doVasprintf(msg, 3, arg0), QStringLiteral("Endpoint abc with"));
+ QCOMPARE(doVasprintf(msg, 9, arg1), QStringLiteral("Endpoint abc with"));
+ QCOMPARE(doVasprintf(msg, 0, nullptr), QStringLiteral("Endpoint with"));
+ }
+}
+
QTEST_APPLESS_MAIN(tst_QString)
#include "tst_qstring.moc"
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index 0bdadedfac..49c8ec2113 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -94,6 +94,7 @@ private slots:
void nestedExceptions();
#endif
void nonGlobalThreadPool();
+ void resultsReadyAt();
};
void tst_QFuture::resultStore()
@@ -627,6 +628,26 @@ void tst_QFuture::futureInterface()
VoidResult a;
a.run().waitForFinished();
}
+
+ {
+ QFutureInterface<int> fi;
+ fi.reportStarted();
+ fi.reportResults(QVector<int> {});
+ fi.reportFinished();
+
+ QVERIFY(fi.results().empty());
+ }
+
+ {
+ QFutureInterface<int> fi;
+ fi.reportStarted();
+ QVector<int> values = { 1, 2, 3 };
+ fi.reportResults(values);
+ fi.reportResults(QVector<int> {});
+ fi.reportFinished();
+
+ QCOMPARE(fi.results(), values.toList());
+ }
}
template <typename T>
@@ -1557,5 +1578,63 @@ void tst_QFuture::nonGlobalThreadPool()
}
}
+void tst_QFuture::resultsReadyAt()
+{
+ QFutureInterface<int> iface;
+ QFutureWatcher<int> watcher;
+ watcher.setFuture(iface.future());
+
+ QTestEventLoop eventProcessor;
+ connect(&watcher, &QFutureWatcher<int>::finished, &eventProcessor, &QTestEventLoop::exitLoop);
+
+ const int nExpectedResults = 4;
+ int reported = 0;
+ int taken = 0;
+ connect(&watcher, &QFutureWatcher<int>::resultsReadyAt,
+ [&iface, &reported, &taken](int begin, int end)
+ {
+ auto future = iface.future();
+ QVERIFY(end - begin > 0);
+ for (int i = begin; i < end; ++i, ++reported) {
+ QVERIFY(future.isResultReadyAt(i));
+ taken |= 1 << i;
+ }
+ });
+
+ auto report = [&iface](int index)
+ {
+ int dummyResult = 0b101010;
+ iface.reportResult(&dummyResult, index);
+ };
+
+ const QSignalSpy readyCounter(&watcher, &QFutureWatcher<int>::resultsReadyAt);
+ QTimer::singleShot(0, [&iface, &report]{
+ // With filter mode == true, the result may go into the pending results.
+ // Reporting it as ready will allow an application to try and access the
+ // result, crashing on invalid (store.end()) iterator dereferenced.
+ iface.setFilterMode(true);
+ iface.reportStarted();
+ report(0);
+ report(1);
+ // This one - should not be reported (it goes into pending):
+ report(3);
+ // Let's close the 'gap' and make them all ready:
+ report(-1);
+ iface.reportFinished();
+ });
+
+ // Run event loop, QCoreApplication::postEvent is in use
+ // in QFutureInterface:
+ eventProcessor.enterLoopMSecs(2000);
+ QVERIFY(!eventProcessor.timeout());
+ if (QTest::currentTestFailed()) // Failed in our lambda observing 'ready at'
+ return;
+
+ QCOMPARE(reported, nExpectedResults);
+ QCOMPARE(nExpectedResults, iface.future().resultCount());
+ QCOMPARE(readyCounter.count(), 3);
+ QCOMPARE(taken, 0b1111);
+}
+
QTEST_MAIN(tst_QFuture)
#include "tst_qfuture.moc"
diff --git a/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp b/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp
index fba617e34d..a1742b3182 100644
--- a/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp
+++ b/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp
@@ -175,6 +175,14 @@ void tst_QtConcurrentResultStore::addResults()
++it;
QCOMPARE(it, store.end());
+
+ QVector<int> empty;
+ const auto countBefore = store.count();
+ QCOMPARE(store.addResults(countBefore, &empty), -1);
+ QCOMPARE(store.count(), countBefore);
+
+ QCOMPARE(store.addResults(countBefore, &vec1), countBefore);
+ QCOMPARE(store.count(), countBefore + vec1.size());
}
void tst_QtConcurrentResultStore::resultIndex()
@@ -338,6 +346,14 @@ void tst_QtConcurrentResultStore::filterMode()
QCOMPARE(store.contains(6), true);
QCOMPARE(store.contains(7), true);
QCOMPARE(store.contains(8), false);
+
+ QVector<int> empty;
+ const auto countBefore = store.count();
+ QCOMPARE(store.addResults(countBefore, &empty), -1);
+ QCOMPARE(store.count(), countBefore);
+
+ QCOMPARE(store.addResult(countBefore, &int2), countBefore);
+ QCOMPARE(store.count(), countBefore + 1);
}
void tst_QtConcurrentResultStore::addCanceledResult()
diff --git a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
index 8041fb5439..7dbd587451 100644
--- a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
+++ b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
@@ -1088,35 +1088,38 @@ void tst_QQuaternion::fromEulerAngles_data()
QTest::addColumn<float>("yaw");
QTest::addColumn<float>("roll");
+ QTest::addColumn<QQuaternion>("quaternion");
+
QTest::newRow("null")
- << 0.0f << 0.0f << 0.0f;
+ << 0.0f << 0.0f << 0.0f << QQuaternion(1.0f, 0.0f, 0.0f, 0.0f);
QTest::newRow("xonly")
- << 90.0f << 0.0f << 0.0f;
+ << 90.0f << 0.0f << 0.0f << QQuaternion(0.707107f, 0.707107f, 0.0f, 0.0f);
QTest::newRow("yonly")
- << 0.0f << 180.0f << 0.0f;
+ << 0.0f << 180.0f << 0.0f << QQuaternion(0.0f, 0.0f, 1.0f, 0.0f);
QTest::newRow("zonly")
- << 0.0f << 0.0f << 270.0f;
+ << 0.0f << 0.0f << 270.0f << QQuaternion(-0.707107f, 0.0f, 0.0f, 0.707107f);
QTest::newRow("x+z")
- << 30.0f << 0.0f << 45.0f;
+ << 30.0f << 0.0f << 45.0f << QQuaternion(0.892399f, 0.239118f, -0.099046f, 0.369644f);
QTest::newRow("x+y")
- << 30.0f << 90.0f << 0.0f;
+ << 30.0f << 90.0f << 0.0f << QQuaternion(0.683013f, 0.183013f, 0.683013f, -0.183013f);
QTest::newRow("y+z")
- << 0.0f << 45.0f << 30.0f;
+ << 0.0f << 45.0f << 30.0f << QQuaternion(0.892399f, 0.099046f, 0.369644f, 0.239118f);
QTest::newRow("complex")
- << 30.0f << 240.0f << -45.0f;
+ << 30.0f << 240.0f << -45.0f << QQuaternion(-0.531976f, -0.43968f, 0.723317f, -0.02226f);
}
void tst_QQuaternion::fromEulerAngles()
{
QFETCH(float, pitch);
QFETCH(float, yaw);
QFETCH(float, roll);
+ QFETCH(QQuaternion, quaternion);
// Use a straight-forward implementation of the algorithm at:
// http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q60
@@ -1132,11 +1135,22 @@ void tst_QQuaternion::fromEulerAngles()
QVERIFY(myFuzzyCompare(answer.z(), result.z()));
QVERIFY(myFuzzyCompare(answer.scalar(), result.scalar()));
+ // quaternion should be the same as the result
+ QVERIFY(myFuzzyCompare(answer.x(), quaternion.x()));
+ QVERIFY(myFuzzyCompare(answer.y(), quaternion.y()));
+ QVERIFY(myFuzzyCompare(answer.z(), quaternion.z()));
+ QVERIFY(myFuzzyCompare(answer.scalar(), quaternion.scalar()));
+
{
QVector3D answerEulerAngles = answer.toEulerAngles();
QVERIFY(myFuzzyCompareDegrees(answerEulerAngles.x(), pitch));
QVERIFY(myFuzzyCompareDegrees(answerEulerAngles.y(), yaw));
QVERIFY(myFuzzyCompareDegrees(answerEulerAngles.z(), roll));
+
+ QVector3D quaternionEulerAngles = quaternion.toEulerAngles();
+ QVERIFY(myFuzzyCompareDegrees(quaternionEulerAngles.x(), pitch));
+ QVERIFY(myFuzzyCompareDegrees(quaternionEulerAngles.y(), yaw));
+ QVERIFY(myFuzzyCompareDegrees(quaternionEulerAngles.z(), roll));
}
answer = QQuaternion::fromEulerAngles(pitch, yaw, roll);
@@ -1151,6 +1165,12 @@ void tst_QQuaternion::fromEulerAngles()
QVERIFY(myFuzzyCompareDegrees(answerPitch, pitch));
QVERIFY(myFuzzyCompareDegrees(answerYaw, yaw));
QVERIFY(myFuzzyCompareDegrees(answerRoll, roll));
+
+ float quaternionPitch, quaternionYaw, quaternionRoll;
+ quaternion.getEulerAngles(&quaternionPitch, &quaternionYaw, &quaternionRoll);
+ QVERIFY(myFuzzyCompareDegrees(quaternionPitch, pitch));
+ QVERIFY(myFuzzyCompareDegrees(quaternionYaw, yaw));
+ QVERIFY(myFuzzyCompareDegrees(quaternionRoll, roll));
}
}
diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
index 42e98ce363..d7c3f95f1d 100644
--- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
+++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
@@ -308,6 +308,7 @@ private slots:
void fillPolygon();
void drawImageAtPointF();
+ void scaledDashes();
private:
void fillData();
@@ -5468,6 +5469,36 @@ void tst_QPainter::drawImageAtPointF()
paint.end();
}
+void tst_QPainter::scaledDashes()
+{
+ // Test that we do not hit the limit-huge-number-of-dashes path
+ QRgb fore = qRgb(0, 0, 0xff);
+ QRgb back = qRgb(0xff, 0xff, 0);
+ QImage image(5, 32, QImage::Format_RGB32);
+ image.fill(back);
+ QPainter p(&image);
+ QPen pen(QColor(fore), 3, Qt::DotLine);
+ p.setPen(pen);
+ p.scale(1, 2);
+ p.drawLine(2, 0, 2, 16);
+ p.end();
+
+ bool foreFound = false;
+ bool backFound = false;
+ int i = 0;
+ while (i < 32 && (!foreFound || !backFound)) {
+ QRgb pix = image.pixel(3, i);
+ if (pix == fore)
+ foreFound = true;
+ else if (pix == back)
+ backFound = true;
+ i++;
+ }
+
+ QVERIFY(foreFound);
+ QVERIFY(backFound);
+}
+
QTEST_MAIN(tst_QPainter)
#include "tst_qpainter.moc"
diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
index c1dd2d97a1..2feca77f40 100644
--- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
+++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
@@ -1909,6 +1909,20 @@ void tst_QTextLayout::longText()
QFontMetricsF fm(layout.font());
QVERIFY(layout.maximumWidth() - fm.horizontalAdvance(' ') <= QFIXED_MAX);
}
+
+ {
+ QTextLayout layout(QString("AAAAAAAA").repeated(200000));
+ layout.setCacheEnabled(true);
+ layout.beginLayout();
+ forever {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+ }
+ layout.endLayout();
+ QFontMetricsF fm(layout.font());
+ QVERIFY(layout.maximumWidth() - fm.horizontalAdvance('A') <= QFIXED_MAX);
+ }
}
void tst_QTextLayout::widthOfTabs()
diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp
index 0d851cd3df..392419e066 100644
--- a/tests/auto/network/access/http2/tst_http2.cpp
+++ b/tests/auto/network/access/http2/tst_http2.cpp
@@ -271,6 +271,10 @@ void tst_Http2::singleRequest()
request.setAttribute(h2Attribute, QVariant(true));
auto reply = manager->get(request);
+#if QT_CONFIG(ssl)
+ QSignalSpy encSpy(reply, &QNetworkReply::encrypted);
+#endif // QT_CONFIG(ssl)
+
connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished);
// Since we're using self-signed certificates,
// ignore SSL errors:
@@ -285,6 +289,11 @@ void tst_Http2::singleRequest()
QCOMPARE(reply->error(), QNetworkReply::NoError);
QVERIFY(reply->isFinished());
+
+#if QT_CONFIG(ssl)
+ if (connectionType == H2Type::h2Alpn || connectionType == H2Type::h2Direct)
+ QCOMPARE(encSpy.count(), 1);
+#endif // QT_CONFIG(ssl)
}
void tst_Http2::multipleRequests()
diff --git a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp
index 856033fb63..98b2a0d2f7 100644
--- a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp
+++ b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp
@@ -35,6 +35,7 @@
#include <algorithm>
#define EXAMPLE_URL "http://user:pass@localhost:4/#foo"
+#define EXAMPLE_URL2 "http://user:pass@localhost:4/bar"
//cached objects are organized into these many subdirs
#define NUM_SUBDIRECTORIES 16
@@ -141,7 +142,7 @@ class SubQNetworkDiskCache : public QNetworkDiskCache
public:
~SubQNetworkDiskCache()
{
- if (!cacheDirectory().isEmpty())
+ if (!cacheDirectory().isEmpty() && clearOnDestruction)
clear();
}
@@ -170,6 +171,11 @@ public:
d->write("Hello World!");
insert(d);
}
+
+ void setClearCacheOnDestruction(bool value) { clearOnDestruction = value; }
+
+private:
+ bool clearOnDestruction = true;
};
tst_QNetworkDiskCache::tst_QNetworkDiskCache()
@@ -241,17 +247,39 @@ void tst_QNetworkDiskCache::prepare()
// public qint64 cacheSize() const
void tst_QNetworkDiskCache::cacheSize()
{
- SubQNetworkDiskCache cache;
- cache.setCacheDirectory(tempDir.path());
- QCOMPARE(cache.cacheSize(), qint64(0));
+ qint64 cacheSize = 0;
+ {
+ SubQNetworkDiskCache cache;
+ cache.setCacheDirectory(tempDir.path());
+ QCOMPARE(cache.cacheSize(), qint64(0));
- QUrl url(EXAMPLE_URL);
- QNetworkCacheMetaData metaData;
- metaData.setUrl(url);
- QIODevice *d = cache.prepare(metaData);
- cache.insert(d);
- QVERIFY(cache.cacheSize() > qint64(0));
+ {
+ QUrl url(EXAMPLE_URL);
+ QNetworkCacheMetaData metaData;
+ metaData.setUrl(url);
+ QIODevice *d = cache.prepare(metaData);
+ cache.insert(d);
+ cacheSize = cache.cacheSize();
+ QVERIFY(cacheSize > qint64(0));
+ }
+ // Add a second item, some difference in behavior when the cache is not empty
+ {
+ QUrl url(EXAMPLE_URL2);
+ QNetworkCacheMetaData metaData;
+ metaData.setUrl(url);
+ QIODevice *d = cache.prepare(metaData);
+ cache.insert(d);
+ QVERIFY(cache.cacheSize() > cacheSize);
+ cacheSize = cache.cacheSize();
+ }
+ // Don't clear the cache on destruction so we can re-open the cache and test its size.
+ cache.setClearCacheOnDestruction(false);
+ }
+
+ SubQNetworkDiskCache cache;
+ cache.setCacheDirectory(tempDir.path());
+ QCOMPARE(cache.cacheSize(), cacheSize);
cache.clear();
QCOMPARE(cache.cacheSize(), qint64(0));
}
diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
index 115d111974..445e6a2d98 100644
--- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
+++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
@@ -1128,6 +1128,7 @@ void tst_QSslCertificate::verify()
#if QT_CONFIG(securetransport)
QSKIP("Not implemented in SecureTransport");
#endif
+
QList<QSslError> errors;
QList<QSslCertificate> toVerify;
diff --git a/tests/auto/tools/moc/enum_with_include.h b/tests/auto/tools/moc/enum_with_include.h
index b8abf77f12..cd53ba6a28 100644
--- a/tests/auto/tools/moc/enum_with_include.h
+++ b/tests/auto/tools/moc/enum_with_include.h
@@ -34,6 +34,11 @@ class Foo : public QObject {
enum en {
#include <enum_inc.h>
};
+
+ enum class en2 {
+ #include <enum_inc.h>
+ reference = 42
+ };
Q_OBJECT
};
#endif
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
index 0bdf61e1e1..29158faf95 100644
--- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
+++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
@@ -150,6 +150,8 @@ private slots:
void checkFocusAfterActivationChanges_data();
void checkFocusAfterActivationChanges();
void dragSelectAfterNewPress();
+ void dragWithSecondClick_data();
+ void dragWithSecondClick();
private:
static QAbstractItemView *viewFromString(const QByteArray &viewType, QWidget *parent = nullptr)
{
@@ -2511,5 +2513,98 @@ void tst_QAbstractItemView::dragSelectAfterNewPress()
QVERIFY(selected.contains(model.index(i, 0)));
}
+void tst_QAbstractItemView::dragWithSecondClick_data()
+{
+ QTest::addColumn<QString>("viewClass");
+ QTest::addColumn<bool>("doubleClick");
+ for (QString viewClass : {"QListView", "QTreeView"}) {
+ QTest::addRow("DoubleClick") << viewClass << true;
+ QTest::addRow("Two Single Clicks") << viewClass << false;
+ }
+}
+
+// inject the ability to record which indexes get dragged into any QAbstractItemView class
+struct DragRecorder
+{
+ virtual ~DragRecorder() = default;
+ bool dragStarted = false;
+ QModelIndexList draggedIndexes;
+ QAbstractItemView *view;
+};
+
+template<class ViewClass>
+class DragRecorderView : public ViewClass, public DragRecorder
+{
+public:
+ DragRecorderView()
+ { view = this; }
+protected:
+ void startDrag(Qt::DropActions) override
+ {
+ draggedIndexes = ViewClass::selectedIndexes();
+ dragStarted = true;
+ }
+};
+
+void tst_QAbstractItemView::dragWithSecondClick()
+{
+ QFETCH(QString, viewClass);
+ QFETCH(bool, doubleClick);
+
+ QStandardItemModel model;
+ QStandardItem *parentItem = model.invisibleRootItem();
+ for (int i = 0; i < 10; ++i) {
+ QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
+ item->setDragEnabled(true);
+ item->setEditable(false);
+ parentItem->appendRow(item);
+ }
+
+ std::unique_ptr<DragRecorder> dragRecorder;
+ if (viewClass == "QTreeView")
+ dragRecorder.reset(new DragRecorderView<QTreeView>);
+ else if (viewClass == "QListView")
+ dragRecorder.reset(new DragRecorderView<QListView>);
+
+ QAbstractItemView *view = dragRecorder->view;
+ view->setModel(&model);
+ view->setFixedSize(160, 650); // Minimum width for windows with frame on Windows 8
+ view->setSelectionMode(QAbstractItemView::MultiSelection);
+ view->setDragDropMode(QAbstractItemView::InternalMove);
+ centerOnScreen(view);
+ moveCursorAway(view);
+ view->show();
+ QVERIFY(QTest::qWaitForWindowExposed(view));
+
+ QModelIndex index0 = model.index(0, 0);
+ QModelIndex index1 = model.index(1, 0);
+ // Select item 0 using a single click
+ QTest::mouseClick(view->viewport(), Qt::LeftButton, Qt::NoModifier,
+ view->visualRect(index0).center());
+ QCOMPARE(view->currentIndex(), index0);
+
+ if (doubleClick) {
+ // press on same item within the double click interval
+ QTest::mouseDClick(view->viewport(), Qt::LeftButton, Qt::NoModifier,
+ view->visualRect(index0).center());
+ } else {
+ // or on different item with a slow second press
+ QTest::mousePress(view->viewport(), Qt::LeftButton, Qt::NoModifier,
+ view->visualRect(index1).center());
+ }
+ // then drag far enough with left button held
+ const QPoint dragTo = view->visualRect(index1).center()
+ + QPoint(2 * QApplication::startDragDistance(),
+ 2 * QApplication::startDragDistance());
+ QMouseEvent mouseMoveEvent(QEvent::MouseMove, dragTo,
+ Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
+ QVERIFY(QApplication::sendEvent(view->viewport(), &mouseMoveEvent));
+ // twice since the view will first enter dragging state, then start the drag
+ // (not necessary to actually move the mouse)
+ QVERIFY(QApplication::sendEvent(view->viewport(), &mouseMoveEvent));
+ QVERIFY(dragRecorder->dragStarted);
+ QTest::mouseRelease(view->viewport(), Qt::LeftButton, Qt::NoModifier, dragTo);
+}
+
QTEST_MAIN(tst_QAbstractItemView)
#include "tst_qabstractitemview.moc"
diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
index dadb9f836c..875b2c08e5 100644
--- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
+++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
@@ -169,6 +169,8 @@ private slots:
void itemAlignment();
void internalDragDropMove_data();
void internalDragDropMove();
+ void scrollOnRemove_data();
+ void scrollOnRemove();
};
// Testing get/set functions
@@ -2550,6 +2552,7 @@ void tst_QListView::internalDragDropMove_data()
| Qt::ItemIsEditable
| Qt::ItemIsDragEnabled;
+ const QStringList unchanged = QStringList{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
const QStringList reordered = QStringList{"0", "2", "3", "4", "5", "6", "7", "8", "9", "1"};
const QStringList replaced = QStringList{"0", "2", "3", "4", "1", "6", "7", "8", "9"};
@@ -2564,7 +2567,8 @@ void tst_QListView::internalDragDropMove_data()
<< Qt::MoveAction
<< defaultFlags
<< modelMoves
- << reordered;
+ // listview in IconMode doesn't change the model
+ << ((viewMode == QListView::IconMode && !modelMoves) ? unchanged : reordered);
QTest::newRow((rowName + ", only move").constData())
<< viewMode
@@ -2573,7 +2577,8 @@ void tst_QListView::internalDragDropMove_data()
<< Qt::MoveAction
<< defaultFlags
<< modelMoves
- << reordered;
+ // listview in IconMode doesn't change the model
+ << ((viewMode == QListView::IconMode && !modelMoves) ? unchanged : reordered);
QTest::newRow((rowName + ", replace item").constData())
<< viewMode
@@ -2719,5 +2724,72 @@ void tst_QListView::internalDragDropMove()
}
+void tst_QListView::scrollOnRemove_data()
+{
+ QTest::addColumn<QListView::ViewMode>("viewMode");
+ QTest::addColumn<QAbstractItemView::SelectionMode>("selectionMode");
+
+ const QMetaObject &mo = QListView::staticMetaObject;
+ const auto viewModeEnum = mo.enumerator(mo.indexOfEnumerator("ViewMode"));
+ const auto selectionModeEnum = mo.enumerator(mo.indexOfEnumerator("SelectionMode"));
+ for (auto viewMode : { QListView::ListMode, QListView::IconMode }) {
+ const char *viewModeName = viewModeEnum.valueToKey(viewMode);
+ for (int index = 0; index < selectionModeEnum.keyCount(); ++index) {
+ const auto selectionMode = QAbstractItemView::SelectionMode(selectionModeEnum.value(index));
+ const char *selectionModeName = selectionModeEnum.valueToKey(selectionMode);
+ QTest::addRow("%s, %s", viewModeName, selectionModeName) << viewMode << selectionMode;
+ }
+ }
+}
+
+void tst_QListView::scrollOnRemove()
+{
+ QFETCH(QListView::ViewMode, viewMode);
+ QFETCH(QAbstractItemView::SelectionMode, selectionMode);
+
+ QPixmap pixmap;
+ if (viewMode == QListView::IconMode) {
+ pixmap = QPixmap(25, 25);
+ pixmap.fill(Qt::red);
+ }
+
+ QStandardItemModel model;
+ for (int i = 0; i < 50; ++i) {
+ QStandardItem *item = new QStandardItem(QString::number(i));
+ item->setIcon(pixmap);
+ model.appendRow(item);
+ }
+
+ QWidget widget;
+ QListView view(&widget);
+ view.setFixedSize(100, 100);
+ view.setAutoScroll(true);
+ if (viewMode == QListView::IconMode)
+ view.setWrapping(true);
+ view.setModel(&model);
+ view.setSelectionMode(selectionMode);
+ view.setViewMode(viewMode);
+
+ widget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&widget));
+
+ QCOMPARE(view.verticalScrollBar()->value(), 0);
+ const QModelIndex item25 = model.index(25, 0);
+ view.scrollTo(item25);
+ QTRY_VERIFY(view.verticalScrollBar()->value() > 0); // layout and scrolling are delayed
+ const int item25Position = view.verticalScrollBar()->value();
+ // selecting a fully visible item shouldn't scroll
+ view.selectionModel()->setCurrentIndex(item25, QItemSelectionModel::SelectCurrent);
+ QTRY_COMPARE(view.verticalScrollBar()->value(), item25Position);
+
+ // removing the selected item might scroll if another item is selected
+ model.removeRow(25);
+
+ // if nothing is selected now, then the view should not have scrolled
+ if (!view.selectionModel()->selectedIndexes().count())
+ QTRY_COMPARE(view.verticalScrollBar()->value(), item25Position);
+}
+
+
QTEST_MAIN(tst_QListView)
#include "tst_qlistview.moc"
diff --git a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
index 89c4a74739..364bc36dff 100644
--- a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
+++ b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
@@ -113,6 +113,8 @@ private slots:
#endif
void fileSystemModel_data();
void fileSystemModel();
+ void fileDialog_data();
+ void fileDialog();
void changingModel_data();
void changingModel();
@@ -695,7 +697,26 @@ void tst_QCompleter::fileSystemModel()
#ifdef Q_OS_WINRT
QSKIP("WinRT cannot access directories outside of the application's sandbox");
#endif
- //QFileSystemModel is assync.
+ //QFileSystemModel is async.
+ filter(true);
+}
+
+/*!
+ In the file dialog, the completer uses the EditRole.
+ See QTBUG-94799
+*/
+void tst_QCompleter::fileDialog_data()
+{
+ fileSystemModel_data();
+ completer->setCompletionRole(Qt::EditRole);
+}
+
+void tst_QCompleter::fileDialog()
+{
+#ifdef Q_OS_WINRT
+ QSKIP("WinRT cannot access directories outside of the application's sandbox");
+#endif
+ //QFileSystemModel is async.
filter(true);
}
diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
index 456d0d55e0..c670147920 100644
--- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
+++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -1370,19 +1370,19 @@ void tst_QDateTimeEdit::editingRanged()
QFETCH(QString, userInput);
QFETCH(QDateTime, expected);
- QDateTimeEdit *edit;
+ QScopedPointer<QDateTimeEdit> edit;
if (minTime.isValid()) {
- edit = new QDateTimeEdit;
+ edit.reset(new QDateTimeEdit);
edit->setDisplayFormat("dd.MM.yyyy hh:mm");
edit->setDateTimeRange(QDateTime(minDate, minTime), QDateTime(maxDate, maxTime));
} else {
- edit = new QDateEdit;
+ edit.reset(new QDateEdit);
edit->setDisplayFormat("dd.MM.yyyy");
edit->setDateRange(minDate, maxDate);
}
int callCount = 0;
- connect(edit, &QDateTimeEdit::dateTimeChanged, [&](const QDateTime &dateTime) {
+ connect(edit.get(), &QDateTimeEdit::dateTimeChanged, [&](const QDateTime &dateTime) {
++callCount;
if (minTime.isValid()) {
QVERIFY(dateTime >= QDateTime(minDate, minTime));
@@ -1394,15 +1394,15 @@ void tst_QDateTimeEdit::editingRanged()
});
edit->show();
- QApplication::setActiveWindow(edit);
- if (!QTest::qWaitForWindowActive(edit))
+ QApplication::setActiveWindow(edit.get());
+ if (!QTest::qWaitForWindowActive(edit.get()))
QSKIP("Failed to make window active, aborting");
edit->setFocus();
// with keyboard tracking, never get a signal with an out-of-range value
edit->setKeyboardTracking(true);
- QTest::keyClicks(edit, userInput);
- QTest::keyClick(edit, Qt::Key_Return);
+ QTest::keyClicks(edit.get(), userInput);
+ QTest::keyClick(edit.get(), Qt::Key_Return);
QVERIFY(callCount > 0);
// QDateTimeEdit blocks these dates from being entered - see QTBUG-65
@@ -1418,12 +1418,10 @@ void tst_QDateTimeEdit::editingRanged()
callCount = 0;
edit->setKeyboardTracking(false);
- QTest::keyClicks(edit, userInput);
- QTest::keyClick(edit, Qt::Key_Return);
+ QTest::keyClicks(edit.get(), userInput);
+ QTest::keyClick(edit.get(), Qt::Key_Return);
QCOMPARE(edit->dateTime(), expected);
QCOMPARE(callCount, 1);
-
- delete edit;
}
void tst_QDateTimeEdit::wrappingTime_data()
@@ -3807,7 +3805,6 @@ void tst_QDateTimeEdit::deleteCalendarWidget()
{
{
// setup
- QCalendarWidget *cw = 0;
QDateEdit edit;
QVERIFY(!edit.calendarWidget());
edit.setCalendarPopup(true);
@@ -3815,8 +3812,7 @@ void tst_QDateTimeEdit::deleteCalendarWidget()
edit.calendarWidget()->setObjectName("cw1");;
// delete
- cw = edit.calendarWidget();
- delete cw;
+ delete edit.calendarWidget();
// it should create a new widget
QVERIFY(edit.calendarWidget());
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index 6408df3f11..7c2203deb4 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -292,6 +292,7 @@ private slots:
void clearButtonVisibleAfterSettingText_QTBUG_45518();
void sideWidgets();
void sideWidgetsActionEvents();
+ void sideWidgetsEffectiveMargins();
void shouldShowPlaceholderText_data();
void shouldShowPlaceholderText();
@@ -4646,6 +4647,71 @@ void tst_QLineEdit::sideWidgetsActionEvents()
QCOMPARE(toolButton2->x(), toolButton1X);
}
+/*!
+ Verify that side widgets are positioned correctly and result in
+ correct effective text margins.
+*/
+void tst_QLineEdit::sideWidgetsEffectiveMargins()
+{
+#ifndef QT_BUILD_INTERNAL
+ QSKIP("This test requires a developer build.");
+#else
+ QLineEdit edit;
+ edit.setPlaceholderText("placeholder");
+ edit.setClearButtonEnabled(true);
+ edit.show();
+ QLineEditPrivate *priv = QLineEditPrivate::get(&edit);
+ const auto sideWidgetParameters = priv->sideWidgetParameters();
+ const int sideWidgetWidth = sideWidgetParameters.widgetWidth + sideWidgetParameters.margin;
+ QVERIFY(QTest::qWaitForWindowExposed(&edit));
+
+ QCOMPARE(priv->effectiveTextMargins().left(), 0);
+ QCOMPARE(priv->effectiveTextMargins().right(), 0);
+
+ edit.setText("Left to right"); // clear button fades in on the right
+ QCOMPARE(priv->effectiveTextMargins().left(), 0);
+ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+ edit.clear();
+ QCOMPARE(priv->effectiveTextMargins().left(), 0);
+ QCOMPARE(priv->effectiveTextMargins().right(), 0);
+
+ edit.setLayoutDirection(Qt::RightToLeft);
+ edit.setText("ئۇيغۇر تىلى"); // clear button fades in on the left
+ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), 0);
+ edit.clear();
+ QCOMPARE(priv->effectiveTextMargins().left(), 0);
+ QCOMPARE(priv->effectiveTextMargins().right(), 0);
+
+ edit.setLayoutDirection(Qt::LeftToRight);
+
+ const QIcon leftIcon = edit.style()->standardIcon(QStyle::SP_FileIcon);
+ const QIcon rightIcon = edit.style()->standardIcon(QStyle::SP_DirIcon);
+ edit.addAction(leftIcon, QLineEdit::ActionPosition::LeadingPosition);
+ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), 0);
+
+ edit.addAction(rightIcon, QLineEdit::ActionPosition::TrailingPosition);
+ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+
+ edit.setText("Left to right"); // clear button on the right
+ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), 2 * sideWidgetWidth);
+ edit.clear();
+ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+
+ edit.setLayoutDirection(Qt::RightToLeft);
+ edit.setText("ئۇيغۇر تىلى"); // clear button fades in on the left
+ QCOMPARE(priv->effectiveTextMargins().left(), 2 * sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+ edit.clear();
+ QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth);
+ QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth);
+#endif
+}
+
Q_DECLARE_METATYPE(Qt::AlignmentFlag)
void tst_QLineEdit::shouldShowPlaceholderText_data()
{
diff --git a/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp b/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp
index 79a963f532..f04f803ecf 100644
--- a/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp
+++ b/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp
@@ -98,6 +98,9 @@ private slots:
void mouseReleaseOutsideTabBar();
+ void scrollButtons_data();
+ void scrollButtons();
+
private:
void checkPositions(const TabBar &tabbar, const QList<int> &positions);
};
@@ -869,5 +872,71 @@ void tst_QTabBar::checkPositions(const TabBar &tabbar, const QList<int> &positio
}
}
+void tst_QTabBar::scrollButtons_data()
+{
+ QTest::addColumn<QTabWidget::TabPosition>("tabPosition");
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+
+ for (auto ld : {Qt::LeftToRight, Qt::RightToLeft}) {
+ const char *ldStr = ld == Qt::LeftToRight ? "LTR" : "RTL";
+ QTest::addRow("North, %s", ldStr) << QTabWidget::North << ld;
+ QTest::addRow("South, %s", ldStr) << QTabWidget::South << ld;
+ QTest::addRow("West, %s", ldStr) << QTabWidget::West << ld;
+ QTest::addRow("East, %s", ldStr) << QTabWidget::East << ld;
+ }
+}
+
+void tst_QTabBar::scrollButtons()
+{
+ QFETCH(QTabWidget::TabPosition, tabPosition);
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+
+ QWidget window;
+ QTabWidget tabWidget(&window);
+ tabWidget.setLayoutDirection(layoutDirection);
+ tabWidget.setTabPosition(tabPosition);
+ tabWidget.setElideMode(Qt::ElideNone);
+ tabWidget.setUsesScrollButtons(true);
+
+ const int tabCount = 5;
+ for (int i = 0; i < tabCount; ++i)
+ {
+ const QString num = QString::number(i);
+ tabWidget.addTab(new QPushButton(num), num + " - Really long tab name to force arrows");
+ }
+ tabWidget.move(0, 0);
+ tabWidget.resize(tabWidget.minimumSizeHint());
+ window.show();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+
+ auto *leftB = tabWidget.tabBar()->findChild<QAbstractButton*>(QStringLiteral("ScrollLeftButton"));
+ auto *rightB = tabWidget.tabBar()->findChild<QAbstractButton*>(QStringLiteral("ScrollRightButton"));
+
+ QVERIFY(leftB->isVisible());
+ QVERIFY(!leftB->isEnabled());
+ QVERIFY(rightB->isVisible());
+ QVERIFY(rightB->isEnabled());
+ QVERIFY(!tabWidget.tabBar()->tabRect(1).intersects(tabWidget.tabBar()->rect()));
+
+ int index = 0;
+ for (; index < tabWidget.count(); ++index) {
+ QCOMPARE(leftB->isEnabled(), index > 0);
+ QCOMPARE(rightB->isEnabled(), index < tabWidget.count() - 1);
+ QVERIFY(tabWidget.tabBar()->tabRect(index).intersects(tabWidget.tabBar()->rect()));
+ QCOMPARE(tabWidget.tabBar()->tabAt(tabWidget.tabBar()->rect().center()), index);
+ if (rightB->isEnabled())
+ rightB->click();
+ }
+ for (--index; index >= 0; --index) {
+ QCOMPARE(leftB->isEnabled(), index >= 0);
+ QCOMPARE(rightB->isEnabled(), index < tabWidget.count() - 1);
+
+ QVERIFY(tabWidget.tabBar()->tabRect(index).intersects(tabWidget.tabBar()->rect()));
+ if (leftB->isEnabled())
+ leftB->click();
+ }
+ QVERIFY(!leftB->isEnabled());
+}
+
QTEST_MAIN(tst_QTabBar)
#include "tst_qtabbar.moc"