summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib')
-rw-r--r--tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST1
-rw-r--r--tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST1
-rw-r--r--tests/auto/corelib/codecs/qtextcodec/echo/echo.pro4
-rw-r--r--tests/auto/corelib/codecs/qtextcodec/qtextcodec.pro3
-rw-r--r--tests/auto/corelib/codecs/qtextcodec/test.pro6
-rw-r--r--tests/auto/corelib/codecs/qtextcodec/test/test.pro13
-rw-r--r--tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp9
-rw-r--r--tests/auto/corelib/codecs/utf8/tst_utf8.cpp15
-rw-r--r--tests/auto/corelib/codecs/utf8/utf8data.cpp30
-rw-r--r--tests/auto/corelib/global/qflags/tst_qflags.cpp24
-rw-r--r--tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp6
-rw-r--r--tests/auto/corelib/global/qlogging/app/app.pro11
-rw-r--r--tests/auto/corelib/global/qlogging/test/test.pro16
-rw-r--r--tests/auto/corelib/global/qlogging/tst_qlogging.cpp27
-rw-r--r--tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp2
-rw-r--r--tests/auto/corelib/global/qtendian/tst_qtendian.cpp176
-rw-r--r--tests/auto/corelib/io/qdebug/tst_qdebug.cpp16
-rw-r--r--tests/auto/corelib/io/qdir/tst_qdir.cpp1
-rw-r--r--tests/auto/corelib/io/qfile/.gitignore8
-rw-r--r--tests/auto/corelib/io/qfile/qfile.pro3
-rw-r--r--tests/auto/corelib/io/qfile/stdinprocess/main.cpp2
-rw-r--r--tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro6
-rw-r--r--tests/auto/corelib/io/qfile/test.pro26
-rw-r--r--tests/auto/corelib/io/qfile/test/test.pro25
-rw-r--r--tests/auto/corelib/io/qfile/tst_qfile.cpp49
-rw-r--r--tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp42
-rw-r--r--tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp3
-rw-r--r--tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp7
-rw-r--r--tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp2
-rw-r--r--tests/auto/corelib/io/qresourceengine/.gitattributes1
-rw-r--r--tests/auto/corelib/io/qresourceengine/qresourceengine.pro27
-rw-r--r--tests/auto/corelib/io/qresourceengine/qresourceengine_test.pro33
-rw-r--r--tests/auto/corelib/io/qresourceengine/staticplugin/.gitignore1
-rw-r--r--tests/auto/corelib/io/qresourceengine/staticplugin/main.cpp9
-rw-r--r--tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.json1
-rw-r--r--tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.pro8
-rw-r--r--tests/auto/corelib/io/qresourceengine/testqrc/aliasdir/aliasdir.txt2
-rw-r--r--tests/auto/corelib/io/qresourceengine/testqrc/blahblah.txt2
-rw-r--r--tests/auto/corelib/io/qresourceengine/testqrc/currentdir.txt2
-rw-r--r--tests/auto/corelib/io/qresourceengine/testqrc/currentdir2.txt2
-rw-r--r--tests/auto/corelib/io/qresourceengine/testqrc/otherdir/otherdir.txt2
-rw-r--r--tests/auto/corelib/io/qresourceengine/testqrc/subdir/subdir.txt2
-rw-r--r--tests/auto/corelib/io/qresourceengine/testqrc/test/test/test1.txt2
-rw-r--r--tests/auto/corelib/io/qresourceengine/testqrc/test/test/test2.txt2
-rw-r--r--tests/auto/corelib/io/qresourceengine/testqrc/test/testdir.txt2
-rw-r--r--tests/auto/corelib/io/qresourceengine/testqrc/test/testdir2.txt2
-rw-r--r--tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp129
-rw-r--r--tests/auto/corelib/io/qsettings/BLACKLIST2
-rw-r--r--tests/auto/corelib/io/qsettings/qsettings.pro2
-rw-r--r--tests/auto/corelib/io/qsettings/tst_qsettings.cpp6
-rw-r--r--tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp2
-rw-r--r--tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp2
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp52
-rw-r--r--tests/auto/corelib/itemmodels/itemmodels.pro7
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel/.gitignore1
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel/qsortfilterproxymodel.pro9
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp (renamed from tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp)511
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h189
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/.gitignore1
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/qsortfilterproxymodel_regexp.pro16
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/tst_qsortfilterproxymodel_regexp.cpp (renamed from tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp)40
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/.gitignore1
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/qsortfilterproxymodel_regularexpression.pro16
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp (renamed from tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp)34
-rw-r--r--tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp4
-rw-r--r--tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h2
-rw-r--r--tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST1
-rw-r--r--tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST2
-rw-r--r--tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp179
-rw-r--r--tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp23
-rw-r--r--tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp42
-rw-r--r--tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp2
-rw-r--r--tests/auto/corelib/kernel/qmetatype/qmetatype.pro2
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp247
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h18
-rw-r--r--tests/auto/corelib/kernel/qobject/.gitignore8
-rw-r--r--tests/auto/corelib/kernel/qobject/qobject.pro8
-rw-r--r--tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro7
-rw-r--r--tests/auto/corelib/kernel/qobject/test.pro (renamed from tests/auto/corelib/kernel/qobject/test/test.pro)6
-rw-r--r--tests/auto/corelib/kernel/qobject/tst_qobject.cpp85
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/producerconsumer/main.cpp (renamed from tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/main.cpp)0
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/producerconsumer/producerconsumer.pro5
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro4
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/sharedmemoryhelper.pro17
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/test.pro8
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/test/test.pro18
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp (renamed from tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp)20
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/acquirerelease.pro5
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/main.cpp (renamed from tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/main.cpp)0
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro2
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/systemsemaphorehelper.pro17
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/test.pro7
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/test/test.pro17
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp (renamed from tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp)17
-rw-r--r--tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp29
-rw-r--r--tests/auto/corelib/kernel/qtranslator/android_testdata.qrc1
-rw-r--r--tests/auto/corelib/kernel/qtranslator/hellotr_empty.qm1
-rw-r--r--tests/auto/corelib/kernel/qtranslator/hellotr_empty.ts3
-rw-r--r--tests/auto/corelib/kernel/qtranslator/qtranslator.pro2
-rw-r--r--tests/auto/corelib/kernel/qtranslator/qtranslator.qrc1
-rw-r--r--tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp58
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp8
-rw-r--r--tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp21
-rw-r--r--tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.foo3
-rw-r--r--tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.xml21
-rw-r--r--tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy2.foo3
-rw-r--r--tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc3
-rw-r--r--tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp21
-rw-r--r--tests/auto/corelib/plugin/plugin.pro3
-rw-r--r--tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp64
-rw-r--r--tests/auto/corelib/plugin/qplugin/tst_qplugin.pro2
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h2
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp39
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/utf8_data.json17
-rw-r--r--tests/auto/corelib/serialization/qcborstreamreader/qcborstreamreader.pro11
-rw-r--r--tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp1091
-rw-r--r--tests/auto/corelib/serialization/qcborstreamwriter/qcborstreamwriter.pro8
-rw-r--r--tests/auto/corelib/serialization/qcborstreamwriter/tst_qcborstreamwriter.cpp313
-rw-r--r--tests/auto/corelib/serialization/qcborvalue/qcborvalue.pro11
-rw-r--r--tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp1695
-rw-r--r--tests/auto/corelib/serialization/qcborvalue_json/qcborvalue_json.pro7
-rw-r--r--tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp348
-rw-r--r--tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp63
-rw-r--r--tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp12
-rw-r--r--tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp32
-rw-r--r--tests/auto/corelib/serialization/serialization.pro4
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp4
-rw-r--r--tests/auto/corelib/thread/qsemaphore/BLACKLIST2
-rw-r--r--tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp3
-rw-r--r--tests/auto/corelib/thread/qthreadonce/qthreadonce.h4
-rw-r--r--tests/auto/corelib/thread/qthreadstorage/crashonexit/crashonexit.pro10
-rw-r--r--tests/auto/corelib/thread/qthreadstorage/test/test.pro17
-rw-r--r--tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp22
-rw-r--r--tests/auto/corelib/thread/thread.pro39
-rw-r--r--tests/auto/corelib/tools/collections/tst_collections.cpp4
-rw-r--r--tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp129
-rw-r--r--tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp24
-rw-r--r--tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp11
-rw-r--r--tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp5
-rw-r--r--tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp5
-rw-r--r--tests/auto/corelib/tools/qlocale/tst_qlocale.cpp695
-rw-r--r--tests/auto/corelib/tools/qmacautoreleasepool/qmacautoreleasepool.pro1
-rw-r--r--tests/auto/corelib/tools/qmakearray/qmakearray.pro4
-rw-r--r--tests/auto/corelib/tools/qmakearray/tst_qmakearray.cpp103
-rw-r--r--tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro7
-rw-r--r--tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro7
-rw-r--r--tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro8
-rw-r--r--tests/auto/corelib/tools/qregularexpression/qregularexpression.pro7
-rw-r--r--tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp294
-rw-r--r--tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h74
-rw-r--r--tests/auto/corelib/tools/qscopeguard/qscopeguard.pro4
-rw-r--r--tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp (renamed from tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp)56
-rw-r--r--tests/auto/corelib/tools/qsharedpointer/externaltests.cpp20
-rw-r--r--tests/auto/corelib/tools/qstring/tst_qstring.cpp99
-rw-r--r--tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp9
-rw-r--r--tests/auto/corelib/tools/qstringview/tst_qstringview.cpp20
-rw-r--r--tests/auto/corelib/tools/qtimeline/BLACKLIST2
-rw-r--r--tests/auto/corelib/tools/qtimezone/qtimezone.pro2
-rw-r--r--tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp25
-rw-r--r--tests/auto/corelib/tools/tools.pro1
160 files changed, 6780 insertions, 1261 deletions
diff --git a/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST b/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST
index fe1d5bd968..b5b37b4498 100644
--- a/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST
+++ b/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST
@@ -1,2 +1,3 @@
[deleteChildrenWithRunningGroup]
osx-10.12
+osx-10.13
diff --git a/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST b/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST
index 2a31afd735..4c999ff88f 100644
--- a/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST
+++ b/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST
@@ -3,5 +3,6 @@ windows
[finishWithUncontrolledAnimation]
windows
osx-10.12
+osx-10.13
[groupWithZeroDurationAnimations]
osx
diff --git a/tests/auto/corelib/codecs/qtextcodec/echo/echo.pro b/tests/auto/corelib/codecs/qtextcodec/echo/echo.pro
index bf791ffc61..512da8939b 100644
--- a/tests/auto/corelib/codecs/qtextcodec/echo/echo.pro
+++ b/tests/auto/corelib/codecs/qtextcodec/echo/echo.pro
@@ -1,6 +1,4 @@
SOURCES += main.cpp
QT = core
-CONFIG -= app_bundle debug_and_release_target
-CONFIG += console
-
+load(qt_test_helper)
diff --git a/tests/auto/corelib/codecs/qtextcodec/qtextcodec.pro b/tests/auto/corelib/codecs/qtextcodec/qtextcodec.pro
index 302d887fc7..15de02a42d 100644
--- a/tests/auto/corelib/codecs/qtextcodec/qtextcodec.pro
+++ b/tests/auto/corelib/codecs/qtextcodec/qtextcodec.pro
@@ -1,2 +1,3 @@
TEMPLATE = subdirs
-SUBDIRS = test echo
+SUBDIRS = test.pro
+unix: SUBDIRS += echo
diff --git a/tests/auto/corelib/codecs/qtextcodec/test.pro b/tests/auto/corelib/codecs/qtextcodec/test.pro
new file mode 100644
index 0000000000..7505c5ad51
--- /dev/null
+++ b/tests/auto/corelib/codecs/qtextcodec/test.pro
@@ -0,0 +1,6 @@
+CONFIG += testcase
+QT = core testlib
+SOURCES = tst_qtextcodec.cpp
+
+TARGET = tst_qtextcodec
+TESTDATA += *.txt
diff --git a/tests/auto/corelib/codecs/qtextcodec/test/test.pro b/tests/auto/corelib/codecs/qtextcodec/test/test.pro
deleted file mode 100644
index e0a1bbd88e..0000000000
--- a/tests/auto/corelib/codecs/qtextcodec/test/test.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG += testcase
-QT = core testlib
-SOURCES = ../tst_qtextcodec.cpp
-
-TARGET = ../tst_qtextcodec
-win32 {
- CONFIG(debug, debug|release) {
- TARGET = ../../debug/tst_qtextcodec
- } else {
- TARGET = ../../release/tst_qtextcodec
- }
-}
-TESTDATA += ../*.txt
diff --git a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp
index f8f9387abb..6cadebfd7f 100644
--- a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp
+++ b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp
@@ -2092,7 +2092,7 @@ void tst_QTextCodec::toLocal8Bit()
QSKIP("No qprocess support", SkipAll);
#else
QProcess process;
- process.start("echo/echo");
+ process.start("echo_helper");
QString string(QChar(0x410));
process.write((const char*)string.utf16(), string.length()*2);
@@ -2429,7 +2429,7 @@ void tst_QTextCodec::userCodec()
QVERIFY(!QTextCodec::availableCodecs().contains("UserCodec"));
QVERIFY(!QTextCodec::codecForName("UserCodec"));
- QTextCodec *codec = new UserCodec;
+ UserCodec *codec = new UserCodec;
executedOnce = true;
QList<QByteArray> availableCodecs = QTextCodec::availableCodecs();
@@ -2448,6 +2448,11 @@ void tst_QTextCodec::userCodec()
pcodec = QTextCodec::codecForMib(5000);
QCOMPARE(pcodec, codec);
+
+ delete codec;
+
+ pcodec = QTextCodec::codecForName("UserCodec");
+ QCOMPARE(pcodec, nullptr);
}
struct DontCrashAtExit {
diff --git a/tests/auto/corelib/codecs/utf8/tst_utf8.cpp b/tests/auto/corelib/codecs/utf8/tst_utf8.cpp
index 8f78aa937c..9ce1748e72 100644
--- a/tests/auto/corelib/codecs/utf8/tst_utf8.cpp
+++ b/tests/auto/corelib/codecs/utf8/tst_utf8.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -71,7 +71,7 @@ void tst_Utf8::initTestCase()
// is the locale UTF-8?
if (QString(QChar(QChar::ReplacementCharacter)).toLocal8Bit() == "\xEF\xBF\xBD") {
QTest::newRow("localecodec") << true;
- qDebug() << "locale is utf8";
+ qInfo() << "locale is utf8";
}
}
@@ -227,6 +227,15 @@ void tst_Utf8::invalidUtf8()
// GNU libc's iconv is known to accept U+FFFF and U+FFFE encoded as UTF-8
// OS X's iconv is known to accept those, plus surrogates and codepoints above U+10FFFF
if (!useLocale)
+ QVERIFY(decoder->hasFailure() || decoder->needsMoreData());
+ else if (!decoder->hasFailure() && !decoder->needsMoreData())
+ qWarning("System codec does not report failure when it should. Should report bug upstream.");
+
+ // add a continuation character and test that we don't accidentally use it
+ // (buffer overrun)
+ utf8 += char(0x80 | 0x3f);
+ decoder->toUnicode(utf8.constData(), utf8.size() - 1);
+ if (!useLocale)
QVERIFY(decoder->hasFailure());
else if (!decoder->hasFailure())
qWarning("System codec does not report failure when it should. Should report bug upstream.");
diff --git a/tests/auto/corelib/codecs/utf8/utf8data.cpp b/tests/auto/corelib/codecs/utf8/utf8data.cpp
index 2267dc8514..221e1d5579 100644
--- a/tests/auto/corelib/codecs/utf8/utf8data.cpp
+++ b/tests/auto/corelib/codecs/utf8/utf8data.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -29,15 +30,24 @@
void loadInvalidUtf8Rows()
{
- QTest::newRow("1char") << QByteArray("\x80");
- QTest::newRow("2chars-1") << QByteArray("\xC2\xC0");
- QTest::newRow("2chars-2") << QByteArray("\xC3\xDF");
- QTest::newRow("2chars-3") << QByteArray("\xC7\xF0");
- QTest::newRow("3chars-1") << QByteArray("\xE0\xA0\xC0");
- QTest::newRow("3chars-2") << QByteArray("\xE0\xC0\xA0");
- QTest::newRow("4chars-1") << QByteArray("\xF0\x90\x80\xC0");
- QTest::newRow("4chars-2") << QByteArray("\xF0\x90\xC0\x80");
- QTest::newRow("4chars-3") << QByteArray("\xF0\xC0\x80\x80");
+ // Wrong continuations
+ QTest::newRow("bad-continuation-1char") << QByteArray("\x80");
+ QTest::newRow("bad-continuation-2chars-1") << QByteArray("\xC2\xC0");
+ QTest::newRow("bad-continuation-2chars-2") << QByteArray("\xC3\xDF");
+ QTest::newRow("bad-continuation-2chars-3") << QByteArray("\xC7\xF0");
+ QTest::newRow("bad-continuation-3chars-1") << QByteArray("\xE0\xA0\xC0");
+ QTest::newRow("bad-continuation-3chars-2") << QByteArray("\xE0\xC0\xA0");
+ QTest::newRow("bad-continuation-4chars-1") << QByteArray("\xF0\x90\x80\xC0");
+ QTest::newRow("bad-continuation-4chars-2") << QByteArray("\xF0\x90\xC0\x80");
+ QTest::newRow("bad-continuation-4chars-3") << QByteArray("\xF0\xC0\x80\x80");
+
+ // Too short
+ QTest::newRow("too-short-2chars") << QByteArray("\xC2");
+ QTest::newRow("too-short-3chars-1") << QByteArray("\xE0");
+ QTest::newRow("too-short-3chars-2") << QByteArray("\xE0\xA0");
+ QTest::newRow("too-short-4chars-1") << QByteArray("\xF0");
+ QTest::newRow("too-short-4chars-2") << QByteArray("\xF0\x90");
+ QTest::newRow("too-short-4chars-3") << QByteArray("\xF0\x90\x80");
// Surrogate pairs must now be present either
// U+D800: 1101 10 0000 00 0000
diff --git a/tests/auto/corelib/global/qflags/tst_qflags.cpp b/tests/auto/corelib/global/qflags/tst_qflags.cpp
index 2f1b56629a..72b086350e 100644
--- a/tests/auto/corelib/global/qflags/tst_qflags.cpp
+++ b/tests/auto/corelib/global/qflags/tst_qflags.cpp
@@ -39,6 +39,7 @@ private slots:
void classEnum();
void initializerLists();
void testSetFlags();
+ void adl();
};
void tst_QFlags::testFlag() const
@@ -120,7 +121,7 @@ void tst_QFlags::constExpr()
QVERIFY(verifyConstExpr<uint(Qt::MouseButtons(Qt::RightButton) & 0xff)>(Qt::RightButton));
QVERIFY(verifyConstExpr<uint(Qt::MouseButtons(Qt::RightButton) | 0xff)>(0xff));
- QVERIFY(!verifyConstExpr<Qt::RightButton>(!Qt::MouseButtons(Qt::LeftButton)));
+ QVERIFY(!verifyConstExpr<Qt::RightButton>(~Qt::MouseButtons(Qt::LeftButton)));
#if defined(__cpp_constexpr) && __cpp_constexpr-0 >= 201304
QVERIFY(verifyConstExpr<uint(testRelaxedConstExpr())>(Qt::MiddleButton));
@@ -304,6 +305,27 @@ void tst_QFlags::testSetFlags()
QVERIFY(!flags.testFlag(MyStrictEnum::StrictFour));
}
+namespace SomeNS {
+enum Foo { Foo_A = 1 << 0, Foo_B = 1 << 1, Foo_C = 1 << 2 };
+
+Q_DECLARE_FLAGS(Foos, Foo)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Foos);
+
+Qt::Alignment alignment()
+{
+ // Checks that the operator| works, despite there is another operator| in this namespace.
+ return Qt::AlignLeft | Qt::AlignTop;
+}
+}
+
+void tst_QFlags::adl()
+{
+ SomeNS::Foos fl = SomeNS::Foo_B | SomeNS::Foo_C;
+ QVERIFY(fl & SomeNS::Foo_B);
+ QVERIFY(!(fl & SomeNS::Foo_A));
+ QCOMPARE(SomeNS::alignment(), Qt::AlignLeft | Qt::AlignTop);
+}
+
// (statically) check QTypeInfo for QFlags instantiations:
enum MyEnum { Zero, One, Two, Four=4 };
Q_DECLARE_FLAGS( MyFlags, MyEnum )
diff --git a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
index f02e902468..544cb1bf07 100644
--- a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
+++ b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
@@ -160,8 +160,10 @@ void tst_QGetPutEnv::intValue_data()
// some repetition from what is tested in getSetCheck()
QTest::newRow("empty") << QByteArray() << 0 << false;
- QTest::newRow("spaces-heading") << QByteArray(" 1") << 1 << true;
- QTest::newRow("spaces-trailing") << QByteArray("1 ") << 0 << false;
+ QTest::newRow("spaces-heading") << QByteArray(" \n\r\t1") << 1 << true;
+ QTest::newRow("spaces-trailing") << QByteArray("1 \n\r\t") << 1 << true;
+ QTest::newRow("junk-heading") << QByteArray("x1") << 0 << false;
+ QTest::newRow("junk-trailing") << QByteArray("1x") << 0 << false;
#define ROW(x, i, b) \
QTest::newRow(#x) << QByteArray(#x) << (i) << (b)
diff --git a/tests/auto/corelib/global/qlogging/app/app.pro b/tests/auto/corelib/global/qlogging/app/app.pro
index 30751d89ec..b90b685749 100644
--- a/tests/auto/corelib/global/qlogging/app/app.pro
+++ b/tests/auto/corelib/global/qlogging/app/app.pro
@@ -1,6 +1,15 @@
TEMPLATE = app
-TARGET = app
+debug_and_release {
+ CONFIG(debug, debug|release) {
+ TARGET = ../debug/helper
+ } else {
+ TARGET = ../release/helper
+ }
+} else {
+ TARGET = ../helper
+}
+
QT = core
DESTDIR = ./
diff --git a/tests/auto/corelib/global/qlogging/test/test.pro b/tests/auto/corelib/global/qlogging/test/test.pro
index b48bf82cf9..91896d4494 100644
--- a/tests/auto/corelib/global/qlogging/test/test.pro
+++ b/tests/auto/corelib/global/qlogging/test/test.pro
@@ -1,11 +1,21 @@
CONFIG += testcase
-CONFIG -= debug_and_release_target
qtConfig(c++11): CONFIG += c++11
qtConfig(c++14): CONFIG += c++14
-TARGET = ../tst_qlogging
+debug_and_release {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/tst_qlogging
+ !android:!winrt: TEST_HELPER_INSTALLS = ../debug/helper
+ } else {
+ TARGET = ../../release/tst_qlogging
+ !android:!winrt: TEST_HELPER_INSTALLS = ../release/helper
+ }
+} else {
+ TARGET = ../tst_qlogging
+ !android:!winrt: TEST_HELPER_INSTALLS = ../helper
+}
+
QT = core testlib
SOURCES = ../tst_qlogging.cpp
DEFINES += QT_MESSAGELOGCONTEXT
-!android:!winrt: TEST_HELPER_INSTALLS = ../app/app
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
index e7a3748c30..d3ed1a6d0d 100644
--- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
+++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
@@ -64,7 +64,6 @@ private slots:
void formatLogMessage();
private:
- QString m_appDir;
QStringList m_baseEnvironment;
};
@@ -101,14 +100,6 @@ tst_qmessagehandler::tst_qmessagehandler()
void tst_qmessagehandler::initTestCase()
{
#if QT_CONFIG(process)
-# ifdef Q_OS_ANDROID
- m_appDir = QCoreApplication::applicationDirPath();
-# else // !android
- m_appDir = QFINDTESTDATA("app");
-# endif
- QVERIFY2(!m_appDir.isEmpty(), qPrintable(
- QString::fromLatin1("Couldn't find helper app dir starting from %1.").arg(QDir::currentPath())));
-
m_baseEnvironment = QProcess::systemEnvironment();
for (int i = 0; i < m_baseEnvironment.count(); ++i) {
if (m_baseEnvironment.at(i).startsWith("QT_MESSAGE_PATTERN=")) {
@@ -806,7 +797,7 @@ void tst_qmessagehandler::qMessagePattern_data()
#ifndef QT_NO_DEBUG
QTest::newRow("backtrace") << "[%{backtrace}] %{message}" << true << (QList<QByteArray>()
// MyClass::qt_static_metacall is explicitly marked as hidden in the Q_OBJECT macro
- << "[MyClass::myFunction|MyClass::mySlot1|?app?|" QT_NAMESPACE_STR "QMetaMethod::invoke|" QT_NAMESPACE_STR "QMetaObject::invokeMethod] from_a_function 34");
+ << "[MyClass::myFunction|MyClass::mySlot1|?helper?|" QT_NAMESPACE_STR "QMetaMethod::invoke|" QT_NAMESPACE_STR "QMetaObject::invokeMethod] from_a_function 34");
#endif
QTest::newRow("backtrace depth,separator") << "[%{backtrace depth=2 separator=\"\n\"}] %{message}" << true << (QList<QByteArray>()
@@ -830,10 +821,10 @@ void tst_qmessagehandler::qMessagePattern()
QFETCH(QList<QByteArray>, expected);
QProcess process;
-#ifdef Q_OS_ANDROID
- const QString appExe = m_appDir + "/libapp.so";
-#else // !android
- const QString appExe = m_appDir + "/app";
+#ifndef Q_OS_ANDROID
+ const QString appExe(QLatin1String("helper"));
+#else
+ const QString appExe(QCoreApplication::applicationDirPath() + QLatin1String("/libhelper.so"));
#endif
//
@@ -880,10 +871,10 @@ void tst_qmessagehandler::setMessagePattern()
//
QProcess process;
-#ifdef Q_OS_ANDROID
- const QString appExe = m_appDir + "/libapp.so";
-#else // !android
- const QString appExe = m_appDir + "/app";
+#ifndef Q_OS_ANDROID
+ const QString appExe(QLatin1String("helper"));
+#else
+ const QString appExe(QCoreApplication::applicationDirPath() + QLatin1String("/libhelper.so"));
#endif
// make sure there is no QT_MESSAGE_PATTERN in the environment
diff --git a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
index 7a6842d144..7c04611823 100644
--- a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
+++ b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
@@ -52,7 +52,7 @@
// values chosen at random
static const quint32 RandomValue32 = 0x4d1169f1U;
static const quint64 RandomValue64 = Q_UINT64_C(0x3ce63161b998aa91);
-static const double RandomValueFP = double(0.3010463714599609f);
+static const double RandomValueFP = double(0.3010463714599609);
static void setRNGControl(uint v)
{
diff --git a/tests/auto/corelib/global/qtendian/tst_qtendian.cpp b/tests/auto/corelib/global/qtendian/tst_qtendian.cpp
index 6934818dcf..2345bb39c1 100644
--- a/tests/auto/corelib/global/qtendian/tst_qtendian.cpp
+++ b/tests/auto/corelib/global/qtendian/tst_qtendian.cpp
@@ -39,9 +39,17 @@ class tst_QtEndian: public QObject
private slots:
void fromBigEndian();
void fromLittleEndian();
+ void fromBigEndianRegion_data();
+ void fromBigEndianRegion();
+ void fromLittleEndianRegion_data() { fromBigEndianRegion_data(); }
+ void fromLittleEndianRegion();
void toBigEndian();
void toLittleEndian();
+ void toBigEndianRegion_data() { fromBigEndianRegion_data(); }
+ void toBigEndianRegion();
+ void toLittleEndianRegion_data() { fromBigEndianRegion_data(); }
+ void toLittleEndianRegion();
void endianIntegers_data();
void endianIntegers();
@@ -56,18 +64,58 @@ struct TestData
quint16 data16;
quint8 data8;
+ float dataFloat;
+ double dataDouble;
+
quint8 reserved;
};
+template <typename T> T getData(const TestData &d);
+template <> quint8 getData(const TestData &d) { return d.data8; }
+template <> quint16 getData(const TestData &d) { return d.data16; }
+template <> quint32 getData(const TestData &d) { return d.data32; }
+template <> quint64 getData(const TestData &d) { return d.data64; }
+template <> float getData(const TestData &d) { return d.dataFloat; }
+
union RawTestData
{
uchar rawData[sizeof(TestData)];
TestData data;
};
-static const TestData inNativeEndian = { Q_UINT64_C(0x0123456789abcdef), 0x00c0ffee, 0xcafe, 0xcf, '\0' };
-static const RawTestData inBigEndian = { "\x01\x23\x45\x67\x89\xab\xcd\xef" "\x00\xc0\xff\xee" "\xca\xfe" "\xcf" };
-static const RawTestData inLittleEndian = { "\xef\xcd\xab\x89\x67\x45\x23\x01" "\xee\xff\xc0\x00" "\xfe\xca" "\xcf" };
+template <typename Float>
+Float int2Float(typename QIntegerForSizeof<Float>::Unsigned i)
+{
+ Float result = 0;
+ memcpy(reinterpret_cast<char *>(&result), reinterpret_cast<const char *>(&i), sizeof (Float));
+ return result;
+}
+
+static const TestData inNativeEndian = {
+ Q_UINT64_C(0x0123456789abcdef),
+ 0x00c0ffee,
+ 0xcafe,
+ 0xcf,
+ int2Float<float>(0x00c0ffeeU),
+ int2Float<double>(Q_UINT64_C(0x0123456789abcdef)),
+ '\0'
+};
+static const RawTestData inBigEndian = {
+ "\x01\x23\x45\x67\x89\xab\xcd\xef"
+ "\x00\xc0\xff\xee"
+ "\xca\xfe"
+ "\xcf"
+ "\x00\xc0\xff\xee"
+ "\x01\x23\x45\x67\x89\xab\xcd\xef"
+};
+static const RawTestData inLittleEndian = {
+ "\xef\xcd\xab\x89\x67\x45\x23\x01"
+ "\xee\xff\xc0\x00"
+ "\xfe\xca"
+ "\xcf"
+ "\xee\xff\xc0\x00"
+ "\xef\xcd\xab\x89\x67\x45\x23\x01"
+};
#define EXPAND_ENDIAN_TEST(endian) \
do { \
@@ -108,6 +156,106 @@ void tst_QtEndian::fromLittleEndian()
#undef ENDIAN_TEST
+template <typename T>
+void transformRegion_template(T (*transformOne)(T), void (*transformRegion)(const void *, qsizetype, void *))
+{
+ enum { Size = 64 };
+ T source[Size];
+ T dest[Size];
+ T expected = transformOne(getData<T>(inNativeEndian));
+ std::fill_n(source, +Size, getData<T>(inNativeEndian));
+ memset(dest, 0, sizeof(dest));
+
+ auto checkBounds = [&](int from) {
+ for ( ; from < Size; ++from)
+ QCOMPARE(dest[from], T(0));
+ };
+
+ transformRegion(source, 1, dest);
+ QCOMPARE(dest[0], expected);
+ checkBounds(1);
+ memset(dest, 0, sizeof(T));
+
+ transformRegion(source, 2, dest);
+ QCOMPARE(dest[0], expected);
+ QCOMPARE(dest[1], expected);
+ checkBounds(2);
+ memset(dest, 0, sizeof(T) * 2);
+
+ transformRegion(source, 3, dest);
+ QCOMPARE(dest[0], expected);
+ QCOMPARE(dest[1], expected);
+ QCOMPARE(dest[2], expected);
+ checkBounds(3);
+ memset(dest, 0, sizeof(T) * 3);
+
+ transformRegion(source, 4, dest);
+ QCOMPARE(dest[0], expected);
+ QCOMPARE(dest[1], expected);
+ QCOMPARE(dest[2], expected);
+ QCOMPARE(dest[3], expected);
+ checkBounds(4);
+ memset(dest, 0, sizeof(T) * 4);
+
+ transformRegion(source, 8, dest);
+ for (int i = 0; i < 8; ++i)
+ QCOMPARE(dest[i], expected);
+ checkBounds(8);
+ memset(dest, 0, sizeof(T) * 8);
+
+ transformRegion(source, 16, dest);
+ for (int i = 0; i < 16; ++i)
+ QCOMPARE(dest[i], expected);
+ checkBounds(16);
+ memset(dest, 0, sizeof(T) * 16);
+
+ transformRegion(source, 32, dest);
+ for (int i = 0; i < 32; ++i)
+ QCOMPARE(dest[i], expected);
+ checkBounds(32);
+ memset(dest, 0, sizeof(T) * 32);
+
+ transformRegion(source, 64, dest);
+ for (int i = 0; i < 64; ++i)
+ QCOMPARE(dest[i], expected);
+
+ // check transforming in-place
+ memcpy(dest, source, sizeof(dest));
+ transformRegion(dest, 64, dest);
+ for (int i = 0; i < 64; ++i)
+ QCOMPARE(dest[i], expected);
+}
+
+void tst_QtEndian::fromBigEndianRegion_data()
+{
+ QTest::addColumn<int>("size");
+ QTest::newRow("1") << 1;
+ QTest::newRow("2") << 2;
+ QTest::newRow("4") << 4;
+ QTest::newRow("8") << 8;
+}
+
+void tst_QtEndian::fromBigEndianRegion()
+{
+ QFETCH(int, size);
+ switch (size) {
+ case 1: return transformRegion_template<quint8>(qFromBigEndian<quint8>, qFromBigEndian<quint8>);
+ case 2: return transformRegion_template<quint16>(qFromBigEndian<quint16>, qFromBigEndian<quint16>);
+ case 4: return transformRegion_template<quint32>(qFromBigEndian<quint32>, qFromBigEndian<quint32>);
+ case 8: return transformRegion_template<quint64>(qFromBigEndian<quint64>, qFromBigEndian<quint64>);
+ }
+}
+
+void tst_QtEndian::fromLittleEndianRegion()
+{
+ QFETCH(int, size);
+ switch (size) {
+ case 1: return transformRegion_template<quint8>(qFromLittleEndian<quint8>, qFromLittleEndian<quint8>);
+ case 2: return transformRegion_template<quint16>(qFromLittleEndian<quint16>, qFromLittleEndian<quint16>);
+ case 4: return transformRegion_template<quint32>(qFromLittleEndian<quint32>, qFromLittleEndian<quint32>);
+ case 8: return transformRegion_template<quint64>(qFromLittleEndian<quint64>, qFromLittleEndian<quint64>);
+ }
+}
#define ENDIAN_TEST(endian, type, size) \
do { \
@@ -135,6 +283,28 @@ void tst_QtEndian::toLittleEndian()
#undef ENDIAN_TEST
+void tst_QtEndian::toBigEndianRegion()
+{
+ QFETCH(int, size);
+ switch (size) {
+ case 1: return transformRegion_template<quint8>(qToBigEndian<quint8>, qToBigEndian<quint8>);
+ case 2: return transformRegion_template<quint16>(qToBigEndian<quint16>, qToBigEndian<quint16>);
+ case 4: return transformRegion_template<quint32>(qToBigEndian<quint32>, qToBigEndian<quint32>);
+ case 8: return transformRegion_template<quint64>(qToBigEndian<quint64>, qToBigEndian<quint64>);
+ }
+}
+
+void tst_QtEndian::toLittleEndianRegion()
+{
+ QFETCH(int, size);
+ switch (size) {
+ case 1: return transformRegion_template<quint8>(qToLittleEndian<quint8>, qToLittleEndian<quint8>);
+ case 2: return transformRegion_template<quint16>(qToLittleEndian<quint16>, qToLittleEndian<quint16>);
+ case 4: return transformRegion_template<quint32>(qToLittleEndian<quint32>, qToLittleEndian<quint32>);
+ case 8: return transformRegion_template<quint64>(qToLittleEndian<quint64>, qToLittleEndian<quint64>);
+ }
+}
+
void tst_QtEndian::endianIntegers_data()
{
QTest::addColumn<int>("val");
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
index b43ea7cfa5..7b8b1df166 100644
--- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
+++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
@@ -38,6 +38,13 @@
class tst_QDebug: public QObject
{
Q_OBJECT
+public:
+ enum EnumType { EnumValue1 = 1, EnumValue2 = 2 };
+ enum FlagType { EnumFlag1 = 1, EnumFlag2 = 2 };
+ Q_ENUM(EnumType)
+ Q_DECLARE_FLAGS(Flags, FlagType)
+ Q_FLAG(Flags)
+
private slots:
void assignment() const;
void warningWithoutDebug() const;
@@ -637,6 +644,15 @@ void tst_QDebug::qDebugQFlags() const
QCOMPARE(s_line, line);
QCOMPARE(QString::fromLatin1(s_function), function);
+ // Test the output of QFlags with an enum not declared with Q_DECLARE_FLAGS and Q_FLAGS
+ QFlags<EnumType> flags2(EnumValue2);
+ qDebug() << flags2;
+ QCOMPARE(s_msg, QString::fromLatin1("QFlags<tst_QDebug::EnumType>(EnumValue2)"));
+
+ // A now for one that was fully declared
+ tst_QDebug::Flags flags3(EnumFlag1);
+ qDebug() << flags3;
+ QCOMPARE(s_msg, QString::fromLatin1("QFlags<tst_QDebug::FlagType>(EnumFlag1)"));
}
void tst_QDebug::textStreamModifiers() const
diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp
index afa15fe895..30f0e447ad 100644
--- a/tests/auto/corelib/io/qdir/tst_qdir.cpp
+++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp
@@ -33,7 +33,6 @@
#include <qdebug.h>
#include <qdir.h>
#include <qfileinfo.h>
-#include <qregexp.h>
#include <qstringlist.h>
#if defined(Q_OS_WIN)
diff --git a/tests/auto/corelib/io/qfile/.gitignore b/tests/auto/corelib/io/qfile/.gitignore
index c508239722..615264e4d4 100644
--- a/tests/auto/corelib/io/qfile/.gitignore
+++ b/tests/auto/corelib/io/qfile/.gitignore
@@ -1,6 +1,10 @@
tst_qfile
-stdinprocess/stdinprocess
-stdinprocess/stdinprocess.exe
+stdinprocess_helper
+stdinprocess_helper.exe
+debug/stdinprocess_helper
+debug/stdinprocess_helper.exe
+release/stdinprocess_helper
+release/stdinprocess_helper.exe
readonlyfile
newfile.txt
appendfile.txt
diff --git a/tests/auto/corelib/io/qfile/qfile.pro b/tests/auto/corelib/io/qfile/qfile.pro
index 0735daedb3..91c5c15f66 100644
--- a/tests/auto/corelib/io/qfile/qfile.pro
+++ b/tests/auto/corelib/io/qfile/qfile.pro
@@ -1,2 +1,3 @@
TEMPLATE = subdirs
-SUBDIRS = test stdinprocess
+SUBDIRS = test.pro
+!winrt: SUBDIRS += stdinprocess
diff --git a/tests/auto/corelib/io/qfile/stdinprocess/main.cpp b/tests/auto/corelib/io/qfile/stdinprocess/main.cpp
index 6ff42c2485..77a1932bd5 100644
--- a/tests/auto/corelib/io/qfile/stdinprocess/main.cpp
+++ b/tests/auto/corelib/io/qfile/stdinprocess/main.cpp
@@ -33,7 +33,7 @@
int main(int argc, char *argv[])
{
if (argc < 2) {
- printf("usage: stdinprocess <all|line <0|1>>\n");
+ printf("usage: stdinprocess_helper <all|line <0|1>>\n");
printf("echos all its input to its output.\n");
return 1;
}
diff --git a/tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro b/tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro
index 8e463e4cef..512da8939b 100644
--- a/tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro
+++ b/tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro
@@ -1,8 +1,4 @@
SOURCES += main.cpp
QT = core
-CONFIG -= app_bundle debug_and_release_target
-CONFIG += console
-# This app is testdata for tst_qfile
-target.path = $$[QT_INSTALL_TESTS]/tst_qfile/$$TARGET
-INSTALLS += target
+load(qt_test_helper)
diff --git a/tests/auto/corelib/io/qfile/test.pro b/tests/auto/corelib/io/qfile/test.pro
new file mode 100644
index 0000000000..95389ab3e2
--- /dev/null
+++ b/tests/auto/corelib/io/qfile/test.pro
@@ -0,0 +1,26 @@
+CONFIG += testcase
+QT = core-private testlib
+qtHaveModule(network): QT += network
+else: DEFINES += QT_NO_NETWORK
+
+contains(CONFIG, builtin_testdata) {
+ DEFINES += BUILTIN_TESTDATA
+}
+
+TESTDATA += BLACKLIST
+
+TARGET = tst_qfile
+
+SOURCES = tst_qfile.cpp
+INCLUDEPATH += ../../../../shared/
+HEADERS += ../../../../shared/emulationdetector.h
+
+RESOURCES += qfile.qrc rename-fallback.qrc copy-fallback.qrc
+
+TESTDATA += \
+ dosfile.txt noendofline.txt testfile.txt \
+ testlog.txt two.dots.file tst_qfile.cpp \
+ Makefile forCopying.txt forRenaming.txt \
+ resources/file1.ext1
+
+win32:!winrt: LIBS += -lole32 -luuid
diff --git a/tests/auto/corelib/io/qfile/test/test.pro b/tests/auto/corelib/io/qfile/test/test.pro
deleted file mode 100644
index 1472ddbb83..0000000000
--- a/tests/auto/corelib/io/qfile/test/test.pro
+++ /dev/null
@@ -1,25 +0,0 @@
-CONFIG += testcase
-CONFIG -= debug_and_release_target
-QT = core-private core testlib
-qtHaveModule(network): QT += network
-else: DEFINES += QT_NO_NETWORK
-
-contains(CONFIG, builtin_testdata) {
- DEFINES += BUILTIN_TESTDATA
-}
-
-TESTDATA += ../BLACKLIST
-
-TARGET = ../tst_qfile
-SOURCES = ../tst_qfile.cpp
-INCLUDEPATH += ../../../../../shared/
-HEADERS += ../../../../../shared/emulationdetector.h
-
-RESOURCES += ../qfile.qrc ../rename-fallback.qrc ../copy-fallback.qrc
-
-TESTDATA += ../dosfile.txt ../noendofline.txt ../testfile.txt \
- ../testlog.txt ../two.dots.file ../tst_qfile.cpp \
- ../Makefile ../forCopying.txt ../forRenaming.txt \
- ../resources/file1.ext1
-
-win32:!winrt: LIBS+=-lole32 -luuid
diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp
index 6665200585..678a80c3f7 100644
--- a/tests/auto/corelib/io/qfile/tst_qfile.cpp
+++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp
@@ -367,7 +367,7 @@ private:
QTemporaryDir m_temporaryDir;
const QString m_oldDir;
- QString m_stdinProcessDir;
+ QString m_stdinProcess;
QString m_testSourceFile;
QString m_testLogFile;
QString m_dosFile;
@@ -379,12 +379,6 @@ private:
QString m_noEndOfLineFile;
};
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
- #define STDINPROCESS_NAME "libstdinprocess.so"
-#else // !android || android_embedded
- #define STDINPROCESS_NAME "stdinprocess"
-#endif // android && !android_embededd
-
static const char noReadFile[] = "noreadfile";
static const char readOnlyFile[] = "readonlyfile";
@@ -455,11 +449,13 @@ void tst_QFile::initTestCase()
QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString()));
#if QT_CONFIG(process)
#if defined(Q_OS_ANDROID)
- m_stdinProcessDir = QCoreApplication::applicationDirPath();
+ m_stdinProcess = QCoreApplication::applicationDirPath() + QLatin1String("/libstdinprocess_helper.so");
+#elif defined(Q_OS_WIN)
+ m_stdinProcess = QFINDTESTDATA("stdinprocess_helper.exe");
#else
- m_stdinProcessDir = QFINDTESTDATA("stdinprocess");
+ m_stdinProcess = QFINDTESTDATA("stdinprocess_helper");
#endif
- QVERIFY(!m_stdinProcessDir.isEmpty());
+ QVERIFY(!m_stdinProcess.isEmpty());
#endif
m_testLogFile = QFINDTESTDATA("testlog.txt");
QVERIFY(!m_testLogFile.isEmpty());
@@ -981,7 +977,7 @@ void tst_QFile::readAllStdin()
QProcess process;
StdinReaderProcessGuard processGuard(&process);
- process.start(m_stdinProcessDir + QStringLiteral("/" STDINPROCESS_NAME), QStringList(QStringLiteral("all")));
+ process.start(m_stdinProcess, QStringList(QStringLiteral("all")));
QVERIFY2(process.waitForStarted(), qPrintable(process.errorString()));
for (int i = 0; i < 5; ++i) {
QTest::qWait(1000);
@@ -1014,7 +1010,7 @@ void tst_QFile::readLineStdin()
for (int i = 0; i < 2; ++i) {
QProcess process;
StdinReaderProcessGuard processGuard(&process);
- process.start(m_stdinProcessDir + QStringLiteral("/" STDINPROCESS_NAME),
+ process.start(m_stdinProcess,
QStringList() << QStringLiteral("line") << QString::number(i),
QIODevice::Text | QIODevice::ReadWrite);
QVERIFY2(process.waitForStarted(), qPrintable(process.errorString()));
@@ -1050,7 +1046,7 @@ void tst_QFile::readLineStdin_lineByLine()
for (int i = 0; i < 2; ++i) {
QProcess process;
StdinReaderProcessGuard processGuard(&process);
- process.start(m_stdinProcessDir + QStringLiteral("/" STDINPROCESS_NAME),
+ process.start(m_stdinProcess,
QStringList() << QStringLiteral("line") << QString::number(i),
QIODevice::Text | QIODevice::ReadWrite);
QVERIFY2(process.waitForStarted(), qPrintable(process.errorString()));
@@ -1297,6 +1293,12 @@ void tst_QFile::append()
f.putChar('a');
f.close();
QCOMPARE(int(f.size()), 2);
+
+ QVERIFY2(f.open(QIODevice::Append | QIODevice::Truncate), msgOpenFailed(f).constData());
+ QCOMPARE(f.pos(), 0);
+ f.putChar('a');
+ f.close();
+ QCOMPARE(int(f.size()), 1);
}
void tst_QFile::permissions_data()
@@ -1833,13 +1835,14 @@ void tst_QFile::encodeName()
void tst_QFile::truncate()
{
- for (int i = 0; i < 2; ++i) {
+ const QIODevice::OpenModeFlag modes[] = { QFile::ReadWrite, QIODevice::WriteOnly, QIODevice::Append };
+ for (auto mode : modes) {
QFile file("truncate.txt");
QVERIFY2(file.open(QFile::WriteOnly), msgOpenFailed(file).constData());
file.write(QByteArray(200, '@'));
file.close();
- QVERIFY2(file.open((i ? QFile::WriteOnly : QFile::ReadWrite) | QFile::Truncate), msgOpenFailed(file).constData());
+ QVERIFY2(file.open(mode | QFile::Truncate), msgOpenFailed(file).constData());
file.write(QByteArray(100, '$'));
file.close();
@@ -2210,7 +2213,8 @@ public:
uint ownerId(FileOwner) const { return 0; }
QString owner(FileOwner) const { return QString(); }
QDateTime fileTime(FileTime) const { return QDateTime(); }
- bool setFileTime(const QDateTime &newDate, FileTime time) { return false; }
+ bool setFileTime(const QDateTime &newDate, FileTime time)
+ { Q_UNUSED(newDate) Q_UNUSED(time) return false; }
private:
int number;
@@ -2755,19 +2759,20 @@ void tst_QFile::renameMultiple()
void tst_QFile::appendAndRead()
{
- QFile writeFile(QLatin1String("appendfile.txt"));
- QVERIFY2(writeFile.open(QIODevice::WriteOnly | QIODevice::Truncate), msgOpenFailed(writeFile).constData());
+ const QString fileName(QStringLiteral("appendfile.txt"));
+ QFile writeFile(fileName);
+ QVERIFY2(writeFile.open(QIODevice::Append | QIODevice::Truncate), msgOpenFailed(writeFile).constData());
- QFile readFile(QLatin1String("appendfile.txt"));
+ QFile readFile(fileName);
QVERIFY2(readFile.open(QIODevice::ReadOnly), msgOpenFailed(readFile).constData());
// Write to the end of the file, then read that character back, and so on.
for (int i = 0; i < 100; ++i) {
char c = '\0';
- writeFile.putChar(char(i % 256));
+ writeFile.putChar(char(i));
writeFile.flush();
QVERIFY(readFile.getChar(&c));
- QCOMPARE(c, char(i % 256));
+ QCOMPARE(c, char(i));
QCOMPARE(readFile.pos(), writeFile.pos());
}
@@ -2778,8 +2783,6 @@ void tst_QFile::appendAndRead()
writeFile.flush();
QCOMPARE(readFile.read(size).size(), size);
}
-
- readFile.close();
}
void tst_QFile::miscWithUncPathAsCurrentDir()
diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
index 87d5675e7a..017eebe153 100644
--- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
@@ -199,7 +199,8 @@ private slots:
void fileTimes_data();
void fileTimes();
- void fileTimes_oldFile();
+ void fakeFileTimes_data();
+ void fakeFileTimes();
void isSymLink_data();
void isSymLink();
@@ -629,6 +630,16 @@ void tst_QFileInfo::canonicalFilePath()
info.canonicalFilePath();
#if defined(Q_OS_UNIX)
+ // If this file exists, you can't log in to run this test ...
+ const QString notExtantPath(QStringLiteral("/etc/nologin"));
+ QFileInfo notExtant(notExtantPath);
+ QCOMPARE(notExtant.canonicalFilePath(), QString());
+
+ // A path with a non-directory as a directory component also doesn't exist:
+ const QString badDirPath(QStringLiteral("/dev/null/sub/dir/n'existe.pas"));
+ QFileInfo badDir(badDirPath);
+ QCOMPARE(badDir.canonicalFilePath(), QString());
+
// This used to crash on Mac
QFileInfo dontCrash(QLatin1String("/"));
QCOMPARE(dontCrash.canonicalFilePath(), QLatin1String("/"));
@@ -1212,12 +1223,23 @@ void tst_QFileInfo::fileTimes()
QVERIFY(writeTime < beforeRead);
}
-void tst_QFileInfo::fileTimes_oldFile()
+void tst_QFileInfo::fakeFileTimes_data()
{
+ QTest::addColumn<QDateTime>("when");
+
// This is 2^{31} seconds before 1970-01-01 15:14:8,
// i.e. shortly after the start of time_t, in any time-zone:
- const QDateTime early(QDate(1901, 12, 14), QTime(12, 0));
- QFile file("ancientfile.txt");
+ QTest::newRow("early") << QDateTime(QDate(1901, 12, 14), QTime(12, 0));
+
+ // QTBUG-12006 claims XP handled this (2010-Mar-26 8:46:10) wrong due to an MS API bug:
+ QTest::newRow("XP-bug") << QDateTime::fromTime_t(1269593170);
+}
+
+void tst_QFileInfo::fakeFileTimes()
+{
+ QFETCH(QDateTime, when);
+
+ QFile file("faketimefile.txt");
file.open(QIODevice::WriteOnly);
file.write("\n", 1);
file.close();
@@ -1228,15 +1250,13 @@ void tst_QFileInfo::fileTimes_oldFile()
modification time, so need to re-open for read in order to setFileTime().
*/
file.open(QIODevice::ReadOnly);
- bool ok = file.setFileTime(early, QFileDevice::FileModificationTime);
+ bool ok = file.setFileTime(when, QFileDevice::FileModificationTime);
file.close();
- if (ok) {
- QFileInfo info(file.fileName());
- QCOMPARE(info.lastModified(), early);
- } else {
- QSKIP("Unable to set file metadata to ancient values");
- }
+ if (ok)
+ QCOMPARE(QFileInfo(file.fileName()).lastModified(), when);
+ else
+ QSKIP("Unable to set file metadata to contrived values");
}
void tst_QFileInfo::isSymLink_data()
diff --git a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
index fed05698fd..da5327594c 100644
--- a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
+++ b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
@@ -209,9 +209,6 @@ void tst_QIODevice::read_QByteArray()
//--------------------------------------------------------------------
void tst_QIODevice::unget()
{
-#if defined(Q_OS_MAC)
- QSKIP("The unget network test is unstable on Mac. See QTBUG-39983.");
-#endif
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
buffer.write("ZXCV");
diff --git a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
index 5b61a6007d..a10e706ed7 100644
--- a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
+++ b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
@@ -187,6 +187,13 @@ private slots:
"default=false");
QCOMPARE(parser.rules().size(), 1);
+ // QSettings escapes * to %2A when writing.
+ parser.setContent("[Rules]\n"
+ "module.%2A=false");
+ QCOMPARE(parser.rules().size(), 1);
+ QCOMPARE(parser.rules().first().category, QString("module."));
+ QCOMPARE(parser.rules().first().flags, QLoggingRule::LeftFilter);
+
parser.setContent("[OtherSection]\n"
"default=false");
QCOMPARE(parser.rules().size(), 0);
diff --git a/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp b/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp
index b78fa29fb6..17c51eaaf4 100644
--- a/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp
+++ b/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp
@@ -65,7 +65,7 @@ void tst_QNoDebug::streaming() const
{
QDateTime dt(QDate(1,2,3),QTime(4,5,6));
const QByteArray debugString = dt.toString(QStringViewLiteral("yyyy-MM-dd HH:mm:ss.zzz t")).toLatin1();
- const QByteArray message = "QDateTime(" + debugString + " Qt::TimeSpec(LocalTime))";
+ const QByteArray message = "QDateTime(" + debugString + " Qt::LocalTime)";
QTest::ignoreMessage(QtWarningMsg, message.constData());
qWarning() << dt;
}
diff --git a/tests/auto/corelib/io/qresourceengine/.gitattributes b/tests/auto/corelib/io/qresourceengine/.gitattributes
index add3716d81..88edd3681a 100644
--- a/tests/auto/corelib/io/qresourceengine/.gitattributes
+++ b/tests/auto/corelib/io/qresourceengine/.gitattributes
@@ -1 +1,2 @@
testqrc/test.qrc -crlf
+*.txt -crlf
diff --git a/tests/auto/corelib/io/qresourceengine/qresourceengine.pro b/tests/auto/corelib/io/qresourceengine/qresourceengine.pro
index e8071297b1..1e12a41dea 100644
--- a/tests/auto/corelib/io/qresourceengine/qresourceengine.pro
+++ b/tests/auto/corelib/io/qresourceengine/qresourceengine.pro
@@ -1,25 +1,2 @@
-CONFIG += testcase
-TARGET = tst_qresourceengine
-
-QT = core testlib
-SOURCES = tst_qresourceengine.cpp
-RESOURCES += testqrc/test.qrc
-
-qtPrepareTool(QMAKE_RCC, rcc, _DEP)
-runtime_resource.target = runtime_resource.rcc
-runtime_resource.depends = $$PWD/testqrc/test.qrc $$QMAKE_RCC_EXE
-runtime_resource.commands = $$QMAKE_RCC -root /runtime_resource/ -binary $$PWD/testqrc/test.qrc -o $${runtime_resource.target}
-QMAKE_EXTRA_TARGETS = runtime_resource
-PRE_TARGETDEPS += $${runtime_resource.target}
-QMAKE_DISTCLEAN += $${runtime_resource.target}
-
-TESTDATA += \
- parentdir.txt \
- testqrc/*
-GENERATED_TESTDATA = $${runtime_resource.target}
-
-android:!android-embedded {
- RESOURCES += android_testdata.qrc
-}
-
-builtin_testdata: DEFINES += BUILTIN_TESTDATA
+TEMPLATE = subdirs
+SUBDIRS = staticplugin qresourceengine_test.pro
diff --git a/tests/auto/corelib/io/qresourceengine/qresourceengine_test.pro b/tests/auto/corelib/io/qresourceengine/qresourceengine_test.pro
new file mode 100644
index 0000000000..3838a72c21
--- /dev/null
+++ b/tests/auto/corelib/io/qresourceengine/qresourceengine_test.pro
@@ -0,0 +1,33 @@
+CONFIG += testcase
+TARGET = tst_qresourceengine
+
+QT = core testlib
+SOURCES = tst_qresourceengine.cpp
+RESOURCES += testqrc/test.qrc
+
+qtPrepareTool(QMAKE_RCC, rcc, _DEP)
+runtime_resource.target = runtime_resource.rcc
+runtime_resource.depends = $$PWD/testqrc/test.qrc $$QMAKE_RCC_EXE
+runtime_resource.commands = $$QMAKE_RCC -root /runtime_resource/ -binary $$PWD/testqrc/test.qrc -o $${runtime_resource.target}
+QMAKE_EXTRA_TARGETS = runtime_resource
+PRE_TARGETDEPS += $${runtime_resource.target}
+QMAKE_DISTCLEAN += $${runtime_resource.target}
+
+TESTDATA += \
+ parentdir.txt \
+ testqrc/*
+GENERATED_TESTDATA = $${runtime_resource.target}
+
+android:!android-embedded {
+ RESOURCES += android_testdata.qrc
+}
+
+win32 {
+ CONFIG(debug, debug|release): LIBS += -Lstaticplugin/debug
+ else: LIBS += -Lstaticplugin/release
+} else {
+ LIBS += -Lstaticplugin
+}
+LIBS += -lmoctestplugin
+
+builtin_testdata: DEFINES += BUILTIN_TESTDATA
diff --git a/tests/auto/corelib/io/qresourceengine/staticplugin/.gitignore b/tests/auto/corelib/io/qresourceengine/staticplugin/.gitignore
new file mode 100644
index 0000000000..c397dde6a5
--- /dev/null
+++ b/tests/auto/corelib/io/qresourceengine/staticplugin/.gitignore
@@ -0,0 +1 @@
+moctestplugin_plugin_resources.cpp
diff --git a/tests/auto/corelib/io/qresourceengine/staticplugin/main.cpp b/tests/auto/corelib/io/qresourceengine/staticplugin/main.cpp
new file mode 100644
index 0000000000..39a3a1e012
--- /dev/null
+++ b/tests/auto/corelib/io/qresourceengine/staticplugin/main.cpp
@@ -0,0 +1,9 @@
+#include <QObject>
+
+class PluginClass : public QObject
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.tests.moc" FILE "staticplugin.json")
+};
+
+#include "main.moc"
diff --git a/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.json b/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.json
new file mode 100644
index 0000000000..4103ecb18c
--- /dev/null
+++ b/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.json
@@ -0,0 +1 @@
+{ "Keys": [ "staticplugin" ] }
diff --git a/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.pro b/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.pro
new file mode 100644
index 0000000000..e19d884548
--- /dev/null
+++ b/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.pro
@@ -0,0 +1,8 @@
+TEMPLATE = lib
+TARGET = moctestplugin
+CONFIG += plugin static
+SOURCES = main.cpp
+plugin_resource.files = main.cpp
+plugin_resource.prefix = /staticplugin
+RESOURCES += plugin_resource
+QT = core
diff --git a/tests/auto/corelib/io/qresourceengine/testqrc/aliasdir/aliasdir.txt b/tests/auto/corelib/io/qresourceengine/testqrc/aliasdir/aliasdir.txt
index 21a3dfa0b8..dcf7937f0a 100644
--- a/tests/auto/corelib/io/qresourceengine/testqrc/aliasdir/aliasdir.txt
+++ b/tests/auto/corelib/io/qresourceengine/testqrc/aliasdir/aliasdir.txt
@@ -1 +1 @@
-"This is a korean text file"
+"This is a korean text file"
diff --git a/tests/auto/corelib/io/qresourceengine/testqrc/blahblah.txt b/tests/auto/corelib/io/qresourceengine/testqrc/blahblah.txt
index 436c4d11c3..19f0805d8d 100644
--- a/tests/auto/corelib/io/qresourceengine/testqrc/blahblah.txt
+++ b/tests/auto/corelib/io/qresourceengine/testqrc/blahblah.txt
@@ -1 +1 @@
-qwerty
+qwerty
diff --git a/tests/auto/corelib/io/qresourceengine/testqrc/currentdir.txt b/tests/auto/corelib/io/qresourceengine/testqrc/currentdir.txt
index 38e389979a..65f1f43def 100644
--- a/tests/auto/corelib/io/qresourceengine/testqrc/currentdir.txt
+++ b/tests/auto/corelib/io/qresourceengine/testqrc/currentdir.txt
@@ -1 +1 @@
-"This is the current dir"
+"This is the current dir"
diff --git a/tests/auto/corelib/io/qresourceengine/testqrc/currentdir2.txt b/tests/auto/corelib/io/qresourceengine/testqrc/currentdir2.txt
index 6ac16a3306..7d89108011 100644
--- a/tests/auto/corelib/io/qresourceengine/testqrc/currentdir2.txt
+++ b/tests/auto/corelib/io/qresourceengine/testqrc/currentdir2.txt
@@ -1 +1 @@
-"This is also the current dir"
+"This is also the current dir"
diff --git a/tests/auto/corelib/io/qresourceengine/testqrc/otherdir/otherdir.txt b/tests/auto/corelib/io/qresourceengine/testqrc/otherdir/otherdir.txt
index b0e4a124ee..e1b430f33b 100644
--- a/tests/auto/corelib/io/qresourceengine/testqrc/otherdir/otherdir.txt
+++ b/tests/auto/corelib/io/qresourceengine/testqrc/otherdir/otherdir.txt
@@ -1 +1 @@
-"This is the other dir"
+"This is the other dir"
diff --git a/tests/auto/corelib/io/qresourceengine/testqrc/subdir/subdir.txt b/tests/auto/corelib/io/qresourceengine/testqrc/subdir/subdir.txt
index b6115207a2..4506acf413 100644
--- a/tests/auto/corelib/io/qresourceengine/testqrc/subdir/subdir.txt
+++ b/tests/auto/corelib/io/qresourceengine/testqrc/subdir/subdir.txt
@@ -1 +1 @@
-"This is in the sub directory"
+"This is in the sub directory"
diff --git a/tests/auto/corelib/io/qresourceengine/testqrc/test/test/test1.txt b/tests/auto/corelib/io/qresourceengine/testqrc/test/test/test1.txt
index adc01d1354..8baef1b4ab 100644
--- a/tests/auto/corelib/io/qresourceengine/testqrc/test/test/test1.txt
+++ b/tests/auto/corelib/io/qresourceengine/testqrc/test/test/test1.txt
@@ -1 +1 @@
-abc
+abc
diff --git a/tests/auto/corelib/io/qresourceengine/testqrc/test/test/test2.txt b/tests/auto/corelib/io/qresourceengine/testqrc/test/test/test2.txt
index 3f48e3cdc3..24c5735c3e 100644
--- a/tests/auto/corelib/io/qresourceengine/testqrc/test/test/test2.txt
+++ b/tests/auto/corelib/io/qresourceengine/testqrc/test/test/test2.txt
@@ -1 +1 @@
-def
+def
diff --git a/tests/auto/corelib/io/qresourceengine/testqrc/test/testdir.txt b/tests/auto/corelib/io/qresourceengine/testqrc/test/testdir.txt
index 40ee68dccb..b8cb3a8c01 100644
--- a/tests/auto/corelib/io/qresourceengine/testqrc/test/testdir.txt
+++ b/tests/auto/corelib/io/qresourceengine/testqrc/test/testdir.txt
@@ -1 +1 @@
-"This is in the test directory"
+"This is in the test directory"
diff --git a/tests/auto/corelib/io/qresourceengine/testqrc/test/testdir2.txt b/tests/auto/corelib/io/qresourceengine/testqrc/test/testdir2.txt
index 051430298a..dccfdc9bcf 100644
--- a/tests/auto/corelib/io/qresourceengine/testqrc/test/testdir2.txt
+++ b/tests/auto/corelib/io/qresourceengine/testqrc/test/testdir2.txt
@@ -1 +1 @@
-"This is another file in this directory"
+"This is another file in this directory"
diff --git a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
index b7e85e8f05..0b50c391b8 100644
--- a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
+++ b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -57,6 +58,7 @@ private slots:
void doubleSlashInRoot();
void setLocale();
void lastModified();
+ void resourcesInStaticPlugins();
private:
const QString m_runtimeResourceRcc;
@@ -103,7 +105,7 @@ void tst_QResourceEngine::cleanupTestCase()
void tst_QResourceEngine::checkStructure_data()
{
QTest::addColumn<QString>("pathName");
- QTest::addColumn<QString>("contents");
+ QTest::addColumn<QByteArray>("contents");
QTest::addColumn<QStringList>("containedFiles");
QTest::addColumn<QStringList>("containedDirs");
QTest::addColumn<QLocale>("locale");
@@ -119,6 +121,7 @@ void tst_QResourceEngine::checkStructure_data()
<< QLatin1String("searchpath1")
<< QLatin1String("searchpath2")
<< QLatin1String("secondary_root")
+ << QLatin1String("staticplugin")
<< QLatin1String("test")
<< QLatin1String("withoutslashes");
@@ -127,12 +130,12 @@ void tst_QResourceEngine::checkStructure_data()
#endif
#if defined(BUILTIN_TESTDATA)
- rootContents.insert(8, QLatin1String("testqrc"));
+ rootContents.insert(9, QLatin1String("testqrc"));
#endif
QTest::newRow("root dir") << QString(":/")
- << QString()
+ << QByteArray()
<< (QStringList()
#if defined(BUILTIN_TESTDATA)
<< "parentdir.txt"
@@ -144,7 +147,7 @@ void tst_QResourceEngine::checkStructure_data()
<< qlonglong(0);
QTest::newRow("secondary root") << QString(":/secondary_root/")
- << QString()
+ << QByteArray()
<< QStringList()
<< (QStringList() << QLatin1String("runtime_resource"))
<< QLocale::c()
@@ -155,73 +158,73 @@ void tst_QResourceEngine::checkStructure_data()
for(int i = 0; i < roots.size(); ++i) {
const QString root = roots.at(i);
- QTest::newRow(QString(root + "prefix dir").toLatin1().constData()) << QString(root + "test/abc/123/+++")
- << QString()
+ QTest::addRow("%s prefix dir", qPrintable(root)) << QString(root + "test/abc/123/+++")
+ << QByteArray()
<< (QStringList() << QLatin1String("currentdir.txt") << QLatin1String("currentdir2.txt") << QLatin1String("parentdir.txt"))
<< (QStringList() << QLatin1String("subdir"))
<< QLocale::c()
<< qlonglong(0);
- QTest::newRow(QString(root + "parent to prefix").toLatin1().constData()) << QString(root + "test/abc/123")
- << QString()
+ QTest::addRow("%s parent to prefix", qPrintable(root)) << QString(root + "test/abc/123")
+ << QByteArray()
<< QStringList()
<< (QStringList() << QLatin1String("+++"))
<< QLocale::c()
<< qlonglong(0);
- QTest::newRow(QString(root + "two parents prefix").toLatin1().constData()) << QString(root + "test/abc")
- << QString()
+ QTest::addRow("%s two parents prefix", qPrintable(root)) << QString(root + "test/abc")
+ << QByteArray()
<< QStringList()
<< QStringList(QLatin1String("123"))
<< QLocale::c()
<< qlonglong(0);
- QTest::newRow(QString(root + "test dir ").toLatin1().constData()) << QString(root + "test")
- << QString()
+ QTest::addRow("%s test dir ", qPrintable(root)) << QString(root + "test")
+ << QByteArray()
<< (QStringList() << QLatin1String("testdir.txt"))
<< (QStringList() << QLatin1String("abc") << QLatin1String("test"))
<< QLocale::c()
<< qlonglong(0);
- QTest::newRow(QString(root + "prefix no slashes").toLatin1().constData()) << QString(root + "withoutslashes")
- << QString()
+ QTest::addRow("%s prefix no slashes", qPrintable(root)) << QString(root + "withoutslashes")
+ << QByteArray()
<< QStringList("blahblah.txt")
<< QStringList()
<< QLocale::c()
<< qlonglong(0);
- QTest::newRow(QString(root + "other dir").toLatin1().constData()) << QString(root + "otherdir")
- << QString()
+ QTest::addRow("%s other dir", qPrintable(root)) << QString(root + "otherdir")
+ << QByteArray()
<< QStringList(QLatin1String("otherdir.txt"))
<< QStringList()
<< QLocale::c()
<< qlonglong(0);
- QTest::newRow(QString(root + "alias dir").toLatin1().constData()) << QString(root + "aliasdir")
- << QString()
+ QTest::addRow("%s alias dir", qPrintable(root)) << QString(root + "aliasdir")
+ << QByteArray()
<< QStringList(QLatin1String("aliasdir.txt"))
<< QStringList()
<< QLocale::c()
<< qlonglong(0);
- QTest::newRow(QString(root + "second test dir").toLatin1().constData()) << QString(root + "test/test")
- << QString()
+ QTest::addRow("%s second test dir", qPrintable(root)) << QString(root + "test/test")
+ << QByteArray()
<< (QStringList() << QLatin1String("test1.txt") << QLatin1String("test2.txt"))
<< QStringList()
<< QLocale::c()
<< qlonglong(0);
info = QFileInfo(QFINDTESTDATA("testqrc/test/test/test1.txt"));
- QTest::newRow(QString(root + "test1 text").toLatin1().constData()) << QString(root + "test/test/test1.txt")
- << QString("abc")
+ QTest::addRow("%s test1 text", qPrintable(root)) << QString(root + "test/test/test1.txt")
+ << QByteArray("abc\n")
<< QStringList()
<< QStringList()
<< QLocale::c()
<< qlonglong(info.size());
info = QFileInfo(QFINDTESTDATA("testqrc/blahblah.txt"));
- QTest::newRow(QString(root + "text no slashes").toLatin1().constData()) << QString(root + "withoutslashes/blahblah.txt")
- << QString("qwerty")
+ QTest::addRow("%s text no slashes", qPrintable(root)) << QString(root + "withoutslashes/blahblah.txt")
+ << QByteArray("qwerty\n")
<< QStringList()
<< QStringList()
<< QLocale::c()
@@ -229,96 +232,96 @@ void tst_QResourceEngine::checkStructure_data()
info = QFileInfo(QFINDTESTDATA("testqrc/test/test/test2.txt"));
- QTest::newRow(QString(root + "test1 text").toLatin1().constData()) << QString(root + "test/test/test2.txt")
- << QString("def")
+ QTest::addRow("%s test1 text", qPrintable(root)) << QString(root + "test/test/test2.txt")
+ << QByteArray("def\n")
<< QStringList()
<< QStringList()
<< QLocale::c()
<< qlonglong(info.size());
info = QFileInfo(QFINDTESTDATA("testqrc/currentdir.txt"));
- QTest::newRow(QString(root + "currentdir text").toLatin1().constData()) << QString(root + "test/abc/123/+++/currentdir.txt")
- << QString("\"This is the current dir\" ")
+ QTest::addRow("%s currentdir text", qPrintable(root)) << QString(root + "test/abc/123/+++/currentdir.txt")
+ << QByteArray("\"This is the current dir\"\n")
<< QStringList()
<< QStringList()
<< QLocale::c()
<< qlonglong(info.size());
info = QFileInfo(QFINDTESTDATA("testqrc/currentdir2.txt"));
- QTest::newRow(QString(root + "currentdir text2").toLatin1().constData()) << QString(root + "test/abc/123/+++/currentdir2.txt")
- << QString("\"This is also the current dir\" ")
+ QTest::addRow("%s currentdir text2", qPrintable(root)) << QString(root + "test/abc/123/+++/currentdir2.txt")
+ << QByteArray("\"This is also the current dir\"\n")
<< QStringList()
<< QStringList()
<< QLocale::c()
<< qlonglong(info.size());
info = QFileInfo(QFINDTESTDATA("parentdir.txt"));
- QTest::newRow(QString(root + "parentdir text").toLatin1().constData()) << QString(root + "test/abc/123/+++/parentdir.txt")
- << QString("abcdefgihklmnopqrstuvwxyz ")
+ QTest::addRow("%s parentdir text", qPrintable(root)) << QString(root + "test/abc/123/+++/parentdir.txt")
+ << QByteArray("abcdefgihklmnopqrstuvwxyz \n")
<< QStringList()
<< QStringList()
<< QLocale::c()
<< qlonglong(info.size());
info = QFileInfo(QFINDTESTDATA("testqrc/subdir/subdir.txt"));
- QTest::newRow(QString(root + "subdir text").toLatin1().constData()) << QString(root + "test/abc/123/+++/subdir/subdir.txt")
- << QString("\"This is in the sub directory\" ")
+ QTest::addRow("%s subdir text", qPrintable(root)) << QString(root + "test/abc/123/+++/subdir/subdir.txt")
+ << QByteArray("\"This is in the sub directory\"\n")
<< QStringList()
<< QStringList()
<< QLocale::c()
<< qlonglong(info.size());
info = QFileInfo(QFINDTESTDATA("testqrc/test/testdir.txt"));
- QTest::newRow(QString(root + "testdir text").toLatin1().constData()) << QString(root + "test/testdir.txt")
- << QString("\"This is in the test directory\" ")
+ QTest::addRow("%s testdir text", qPrintable(root)) << QString(root + "test/testdir.txt")
+ << QByteArray("\"This is in the test directory\"\n")
<< QStringList()
<< QStringList()
<< QLocale::c()
<< qlonglong(info.size());
info = QFileInfo(QFINDTESTDATA("testqrc/otherdir/otherdir.txt"));
- QTest::newRow(QString(root + "otherdir text").toLatin1().constData()) << QString(root + "otherdir/otherdir.txt")
- << QString("\"This is the other dir\" ")
+ QTest::addRow("%s otherdir text", qPrintable(root)) << QString(root + "otherdir/otherdir.txt")
+ << QByteArray("\"This is the other dir\"\n")
<< QStringList()
<< QStringList()
<< QLocale::c()
<< qlonglong(info.size());
info = QFileInfo(QFINDTESTDATA("testqrc/test/testdir2.txt"));
- QTest::newRow(QString(root + "alias text").toLatin1().constData()) << QString(root + "aliasdir/aliasdir.txt")
- << QString("\"This is another file in this directory\" ")
+ QTest::addRow("%s alias text", qPrintable(root)) << QString(root + "aliasdir/aliasdir.txt")
+ << QByteArray("\"This is another file in this directory\"\n")
<< QStringList()
<< QStringList()
<< QLocale::c()
<< qlonglong(info.size());
info = QFileInfo(QFINDTESTDATA("testqrc/aliasdir/aliasdir.txt"));
- QTest::newRow(QString(root + "korean text").toLatin1().constData()) << QString(root + "aliasdir/aliasdir.txt")
- << QString("\"This is a korean text file\" ")
+ QTest::addRow("%s korean text", qPrintable(root)) << QString(root + "aliasdir/aliasdir.txt")
+ << QByteArray("\"This is a korean text file\"\n")
<< QStringList()
<< QStringList()
<< QLocale("ko")
<< qlonglong(info.size());
info = QFileInfo(QFINDTESTDATA("testqrc/aliasdir/aliasdir.txt"));
- QTest::newRow(QString(root + "korean text 2").toLatin1().constData()) << QString(root + "aliasdir/aliasdir.txt")
- << QString("\"This is a korean text file\" ")
+ QTest::addRow("%s korean text 2", qPrintable(root)) << QString(root + "aliasdir/aliasdir.txt")
+ << QByteArray("\"This is a korean text file\"\n")
<< QStringList()
<< QStringList()
<< QLocale("ko_KR")
<< qlonglong(info.size());
info = QFileInfo(QFINDTESTDATA("testqrc/test/german.txt"));
- QTest::newRow(QString(root + "german text").toLatin1().constData()) << QString(root + "aliasdir/aliasdir.txt")
- << QString("Deutsch")
+ QTest::addRow("%s german text", qPrintable(root)) << QString(root + "aliasdir/aliasdir.txt")
+ << QByteArray("Deutsch\n")
<< QStringList()
<< QStringList()
<< QLocale("de")
<< qlonglong(info.size());
info = QFileInfo(QFINDTESTDATA("testqrc/test/german.txt"));
- QTest::newRow(QString(root + "german text 2").toLatin1().constData()) << QString(root + "aliasdir/aliasdir.txt")
- << QString("Deutsch")
+ QTest::addRow("%s german text 2", qPrintable(root)) << QString(root + "aliasdir/aliasdir.txt")
+ << QByteArray("Deutsch\n")
<< QStringList()
<< QStringList()
<< QLocale("de_DE")
@@ -327,8 +330,8 @@ void tst_QResourceEngine::checkStructure_data()
QFile file(QFINDTESTDATA("testqrc/aliasdir/compressme.txt"));
file.open(QFile::ReadOnly);
info = QFileInfo(QFINDTESTDATA("testqrc/aliasdir/compressme.txt"));
- QTest::newRow(QString(root + "compressed text").toLatin1().constData()) << QString(root + "aliasdir/aliasdir.txt")
- << QString(file.readAll())
+ QTest::addRow("%s compressed text", qPrintable(root)) << QString(root + "aliasdir/aliasdir.txt")
+ << file.readAll()
<< QStringList()
<< QStringList()
<< QLocale("de_CH")
@@ -339,7 +342,7 @@ void tst_QResourceEngine::checkStructure_data()
void tst_QResourceEngine::checkStructure()
{
QFETCH(QString, pathName);
- QFETCH(QString, contents);
+ QFETCH(QByteArray, contents);
QFETCH(QStringList, containedFiles);
QFETCH(QStringList, containedDirs);
QFETCH(QLocale, locale);
@@ -399,8 +402,18 @@ void tst_QResourceEngine::checkStructure()
QFile file(pathName);
QVERIFY(file.open(QFile::ReadOnly));
- QByteArray ba = file.readAll();
- QVERIFY(QString(ba).startsWith(contents));
+ // check contents
+ QCOMPARE(file.readAll(), contents);
+
+ // check memory map too
+ uchar *ptr = file.map(0, file.size(), QFile::MapPrivateOption);
+ QVERIFY2(ptr, qPrintable(file.errorString()));
+ QByteArray ba = QByteArray::fromRawData(reinterpret_cast<const char *>(ptr), file.size());
+ QCOMPARE(ba, contents);
+
+ // check that it is still valid after closing the file
+ file.close();
+ QCOMPARE(ba, contents);
}
QLocale::setDefault(QLocale::system());
}
@@ -520,6 +533,16 @@ void tst_QResourceEngine::lastModified()
}
}
+Q_IMPORT_PLUGIN(PluginClass)
+void tst_QResourceEngine::resourcesInStaticPlugins()
+{
+ // We built a separate static plugin and attempted linking against
+ // it. That should successfully register the resources linked into
+ // the plugin via moc generated Q_INIT_RESOURCE calls in a
+ // Q_CONSTRUCTOR_FUNCTION.
+ QVERIFY(QFile::exists(":/staticplugin/main.cpp"));
+}
+
QTEST_MAIN(tst_QResourceEngine)
#include "tst_qresourceengine.moc"
diff --git a/tests/auto/corelib/io/qsettings/BLACKLIST b/tests/auto/corelib/io/qsettings/BLACKLIST
deleted file mode 100644
index 36d68bd918..0000000000
--- a/tests/auto/corelib/io/qsettings/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[isWritable:native]
-osx-10.11
diff --git a/tests/auto/corelib/io/qsettings/qsettings.pro b/tests/auto/corelib/io/qsettings/qsettings.pro
index 5b4cc8a691..79552b62df 100644
--- a/tests/auto/corelib/io/qsettings/qsettings.pro
+++ b/tests/auto/corelib/io/qsettings/qsettings.pro
@@ -6,4 +6,6 @@ RESOURCES += qsettings.qrc
INCLUDEPATH += $$PWD/../../kernel/qmetatype
msvc: LIBS += advapi32.lib
+darwin: LIBS += -framework CoreFoundation
+
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
index db756ada39..5357194406 100644
--- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
+++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
@@ -531,7 +531,7 @@ void tst_QSettings::ctor()
// more details in QMacSettingsPrivate::QMacSettingsPrivate(), organization was comify()-ed
caseSensitive = settings5.fileName().contains("SoftWare.ORG");;
} else {
- caseSensitive = pathconf(QDir::currentPath().toLatin1().constData(), _PC_CASE_SENSITIVE);
+ caseSensitive = pathconf(settings5.fileName().toLatin1().constData(), _PC_CASE_SENSITIVE);
}
#elif defined(Q_OS_WIN32) || defined(Q_OS_WINRT)
caseSensitive = false;
@@ -1186,6 +1186,10 @@ static void testMetaTypesHelper(QSettings::Format format)
F(QJsonArray) \
F(QJsonDocument) \
F(QPersistentModelIndex) \
+ F(QCborSimpleType) \
+ F(QCborValue) \
+ F(QCborArray) \
+ F(QCborMap) \
#define EXCLUDE_NON_SUPPORTED_METATYPES(MetaTypeName) \
template<> void testMetaTypesHelper<QMetaType::MetaTypeName>(QSettings::Format) \
diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
index 3de777653e..5cb130f631 100644
--- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
+++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
@@ -183,12 +183,14 @@ void tst_qstandardpaths::testDefaultLocations()
#endif
}
+#ifdef Q_XDG_PLATFORM
static void createTestFile(const QString &fileName)
{
QFile file(fileName);
QVERIFY(file.open(QIODevice::WriteOnly));
QVERIFY(file.write("Hello"));
}
+#endif
void tst_qstandardpaths::testCustomLocations()
{
diff --git a/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp b/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp
index 8b1aa105de..1317489e2f 100644
--- a/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp
+++ b/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp
@@ -80,7 +80,7 @@ static int qInfoPrinter(const char *format, ...)
// flush
QtMessageHandler qt_message_print = qInstallMessageHandler(0);
qInstallMessageHandler(qt_message_print); // restore the handler
- qt_message_print(QtInfoMsg, QMessageLogContext(), QString::fromLocal8Bit(buf));
+ qt_message_print(QtInfoMsg, QMessageLogContext(), QString::fromLocal8Bit(buf).trimmed());
bufuse = 0;
}
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp
index 62af907037..84af1c255a 100644
--- a/tests/auto/corelib/io/qurl/tst_qurl.cpp
+++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp
@@ -180,6 +180,8 @@ private slots:
void testThreading();
void matches_data();
void matches();
+ void ipv6_zoneId_data();
+ void ipv6_zoneId();
private:
void testThreadingHelper();
@@ -1876,6 +1878,24 @@ void tst_QUrl::ipv6_data()
QTest::newRow("encoded-digit") << "//[::%31]" << true << "//[::1]";
QTest::newRow("encoded-colon") << "//[%3A%3A]" << true << "//[::]";
+
+ QTest::newRow("full ipv6 with zone id (decoded %)") << QString::fromLatin1("//[56:56:56:56:56:56:56:56%eth0]") << true
+ << "//[56:56:56:56:56:56:56:56%25eth0]";
+
+ QTest::newRow("full ipv6 with zone id (encoded %)") << QString::fromLatin1("//[56:56:56:56:56:56:56:56%25eth0]") << true
+ << "//[56:56:56:56:56:56:56:56%25eth0]";
+
+ QTest::newRow("full ipv6 with invalid zone id") << QString::fromLatin1("//[56:56:56:56:56:56:56:56%]") << false << "";
+
+ QTest::newRow("full ipv6 with invalid zone id (encoded)") << QString::fromLatin1("//[56:56:56:56:56:56:56:56%25]") << false << "";
+
+ QTest::newRow("full ipv6 with zone id 25 (encoded)") << QString::fromLatin1("//[56:56:56:56:56:56:56:56%2525]") << true << "//[56:56:56:56:56:56:56:56%2525]";
+
+ QTest::newRow("case 4 with less and ip4 and port and useinfo and zone id")
+ << QString::fromLatin1("//user:pass@[56::56:56:56:127.0.0.1%ethernet_1]:99") << true
+ << "//user:pass@[56::56:56:56:7f00:1%25ethernet_1]:99";
+
+ QTest::newRow("encoded-digit including zone id") << "//[::%31%25eth0]" << true << "//[::1%25eth0]";
}
void tst_QUrl::ipv6()
@@ -4149,6 +4169,38 @@ void tst_QUrl::matches()
QCOMPARE(urlOne.matches(urlTwo, QUrl::FormattingOptions(options)), matches);
}
+void tst_QUrl::ipv6_zoneId_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<QString>("decodedHost");
+ QTest::addColumn<QString>("prettyHost");
+ QTest::addColumn<QString>("encodedHost");
+
+ QTest::newRow("digit") << QUrl("x://[::%251]") << "::%1" << "::%251" << "::%251";
+ QTest::newRow("eth0") << QUrl("x://[::%25eth0]") << "::%eth0" << "::%25eth0" << "::%25eth0";
+ QTest::newRow("space") << QUrl("x://[::%25%20]") << "::% " << "::%25 " << "::%25%20";
+ QTest::newRow("subdelims") << QUrl("x://[::%25eth%2B]") << "::%eth+" << "::%25eth%2B" << "::%25eth%2B";
+ QTest::newRow("other") << QUrl("x://[::%25^]") << "::%^" << "::%25%5E" << "::%25%5E";
+ QTest::newRow("control") << QUrl("x://[::%25%7F]") << "::%\x7f" << "::%25%7F" << "::%25%7F";
+ QTest::newRow("unicode") << QUrl("x://[::%25wlán0]") << "::%wlán0" << "::%25wlán0" << "::%25wl%C3%A1n0";
+ QTest::newRow("non-utf8") << QUrl("x://[::%25%80]") << QString("::%") + QChar(QChar::ReplacementCharacter) << "::%25%80" << "::%25%80";
+ }
+
+void tst_QUrl::ipv6_zoneId()
+{
+ QFETCH(QUrl, url);
+ QFETCH(QString, decodedHost);
+ QFETCH(QString, prettyHost);
+ QFETCH(QString, encodedHost);
+
+ QVERIFY2(url.isValid(), qPrintable(url.errorString()));
+ QCOMPARE(url.host(QUrl::FullyDecoded), decodedHost);
+ QCOMPARE(url.host(), decodedHost);
+ QCOMPARE(url.host(QUrl::FullyEncoded), encodedHost);
+ QCOMPARE(url.toString(), "x://[" + prettyHost + "]");
+ QCOMPARE(url.toString(QUrl::FullyEncoded), "x://[" + encodedHost + "]");
+}
+
QTEST_MAIN(tst_QUrl)
#include "tst_qurl.moc"
diff --git a/tests/auto/corelib/itemmodels/itemmodels.pro b/tests/auto/corelib/itemmodels/itemmodels.pro
index a09f03a7b4..cca350ad43 100644
--- a/tests/auto/corelib/itemmodels/itemmodels.pro
+++ b/tests/auto/corelib/itemmodels/itemmodels.pro
@@ -1,9 +1,9 @@
TEMPLATE=subdirs
-SUBDIRS = qabstractitemmodel \
- qstringlistmodel \
+SUBDIRS = qstringlistmodel
qtHaveModule(gui): SUBDIRS += \
+ qabstractitemmodel \
qabstractproxymodel \
qidentityproxymodel \
qitemselectionmodel \
@@ -11,7 +11,8 @@ qtHaveModule(gui): SUBDIRS += \
qtHaveModule(widgets) {
SUBDIRS += \
- qsortfilterproxymodel
+ qsortfilterproxymodel_regexp \
+ qsortfilterproxymodel_regularexpression
qtHaveModule(sql): SUBDIRS += \
qitemmodel
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/.gitignore b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/.gitignore
deleted file mode 100644
index d3672fe4ae..0000000000
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-tst_qsortfilterproxymodel
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/qsortfilterproxymodel.pro b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/qsortfilterproxymodel.pro
deleted file mode 100644
index dfa8b9fa1b..0000000000
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/qsortfilterproxymodel.pro
+++ /dev/null
@@ -1,9 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qsortfilterproxymodel
-
-QT += widgets testlib
-mtdir = ../../../other/qabstractitemmodelutils
-
-INCLUDEPATH += $$PWD/$${mtdir}
-SOURCES += tst_qsortfilterproxymodel.cpp $${mtdir}/dynamictreemodel.cpp
-HEADERS += $${mtdir}/dynamictreemodel.h
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp
index bced3f5790..82cd26971b 100644
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp
@@ -27,147 +27,17 @@
****************************************************************************/
#include <QtTest/QtTest>
+#include "tst_qsortfilterproxymodel.h"
#include "dynamictreemodel.h"
#include <QtCore/QCoreApplication>
#include <QtGui/QStandardItem>
+#include <QtWidgets/QComboBox>
#include <QtWidgets/QTreeView>
#include <QtWidgets/QTableView>
#include <qdebug.h>
-typedef QList<int> IntList;
-typedef QPair<int, int> IntPair;
-typedef QList<IntPair> IntPairList;
-
-Q_DECLARE_METATYPE(QList<QPersistentModelIndex>)
-
-class tst_QSortFilterProxyModel : public QObject
-{
- Q_OBJECT
-public:
- tst_QSortFilterProxyModel();
-
-public slots:
- void initTestCase();
- void cleanupTestCase();
- void cleanup();
-
-private slots:
- void getSetCheck();
- void sort_data();
- void sort();
- void sortHierarchy_data();
- void sortHierarchy();
-
- void insertRows_data();
- void insertRows();
- void prependRow();
- void removeRows_data();
- void removeRows();
- void removeColumns_data();
- void removeColumns();
- void insertAfterSelect();
- void removeAfterSelect();
- void filter_data();
- void filter();
- void filterHierarchy_data();
- void filterHierarchy();
- void filterColumns_data();
- void filterColumns();
-
- void filterTable();
- void filterCurrent();
- void filter_qtbug30662();
-
- void changeSourceLayout();
- void changeSourceLayoutFilteredOut();
- void removeSourceRows_data();
- void removeSourceRows();
- void insertSourceRows_data();
- void insertSourceRows();
- void changeFilter_data();
- void changeFilter();
- void changeSourceData_data();
- void changeSourceData();
- void changeSourceDataKeepsStableSorting_qtbug1548();
- void changeSourceDataForwardsRoles_qtbug35440();
- void resortingDoesNotBreakTreeModels();
- void dynamicFilterWithoutSort();
- void sortFilterRole();
- void selectionFilteredOut();
- void match_data();
- void match();
- void insertIntoChildrenlessItem();
- void invalidateMappedChildren();
- void insertRowIntoFilteredParent();
- void filterOutParentAndFilterInChild();
-
- void sourceInsertRows();
- void sourceModelDeletion();
-
- void sortColumnTracking1();
- void sortColumnTracking2();
-
- void sortStable();
-
- void hiddenColumns();
- void insertRowsSort();
- void staticSorting();
- void dynamicSorting();
- void fetchMore();
- void hiddenChildren();
- void mapFromToSource();
- void removeRowsRecursive();
- void doubleProxySelectionSetSourceModel();
- void appearsAndSort();
- void unnecessaryDynamicSorting();
- void unnecessaryMapCreation();
- void resetInvalidate_data();
- void resetInvalidate();
-
- void testMultipleProxiesWithSelection();
- void mapSelectionFromSource();
- void testResetInternalData();
- void filteredColumns();
- void headerDataChanged();
-
- void testParentLayoutChanged();
- void moveSourceRows();
-
- void hierarchyFilterInvalidation();
- void simpleFilterInvalidation();
-
- void chainedProxyModelRoleNames();
-
- void noMapAfterSourceDelete();
- void forwardDropApi();
- void canDropMimeData();
- void filterHint();
-
- void sourceLayoutChangeLeavesValidPersistentIndexes();
- void rowMoveLeavesValidPersistentIndexes();
-
- void emitLayoutChangedOnlyIfSortingChanged_data();
- void emitLayoutChangedOnlyIfSortingChanged();
-
- void checkSetNewModel();
- void filterAndInsertRow_data();
- void filterAndInsertRow();
- void filterAndInsertColumn_data();
- void filterAndInsertColumn();
-
-protected:
- void buildHierarchy(const QStringList &data, QAbstractItemModel *model);
- void checkHierarchy(const QStringList &data, const QAbstractItemModel *model);
-
-private:
- QStandardItemModel *m_model;
- QSortFilterProxyModel *m_proxy;
-};
-
-Q_DECLARE_METATYPE(QAbstractItemModel::LayoutChangeHint)
-
// Testing get/set functions
void tst_QSortFilterProxyModel::getSetCheck()
{
@@ -205,7 +75,15 @@ void tst_QSortFilterProxyModel::cleanupTestCase()
void tst_QSortFilterProxyModel::cleanup()
{
- m_proxy->setFilterRegExp(QRegExp());
+ switch (m_filterType) {
+ case FilterType::RegExp:
+ m_proxy->setFilterRegExp(QRegExp());
+ break;
+ case FilterType::RegularExpression:
+ m_proxy->setFilterRegularExpression(QRegularExpression());
+ break;
+ }
+
m_proxy->sort(-1, Qt::AscendingOrder);
m_model->clear();
m_model->insertColumns(0, 1);
@@ -629,6 +507,58 @@ void tst_QSortFilterProxyModel::prependRow()
QCOMPARE(proxy.rowCount(QModelIndex()), 1); //only the "root" item is there
}
+void tst_QSortFilterProxyModel::appendRowFromCombobox_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QString>("newitem");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("filter_out_second_last_item")
+ << "^[0-9]*$"
+ << (QStringList() << "a" << "1")
+ << "2"
+ << (QStringList() << "a" << "1" << "2");
+
+ QTest::newRow("filter_out_everything")
+ << "^c*$"
+ << (QStringList() << "a" << "b")
+ << "c"
+ << (QStringList() << "a" << "b" << "c");
+
+ QTest::newRow("no_filter")
+ << ""
+ << (QStringList() << "0" << "1")
+ << "2"
+ << (QStringList() << "0" << "1" << "2");
+
+ QTest::newRow("filter_out_last_item")
+ << "^[a-z]*$"
+ << (QStringList() << "a" << "1")
+ << "b"
+ << (QStringList() << "a" << "1" << "b");
+}
+
+void tst_QSortFilterProxyModel::appendRowFromCombobox()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QStringList, initial);
+ QFETCH(QString, newitem);
+ QFETCH(QStringList, expected);
+
+ QStringListModel model(initial);
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ proxy.setFilterRegExp(pattern);
+
+ QComboBox comboBox;
+ comboBox.setModel(&proxy);
+ comboBox.addItem(newitem);
+
+ QCOMPARE(model.stringList(), expected);
+}
+
void tst_QSortFilterProxyModel::removeRows_data()
{
QTest::addColumn<QStringList>("initial");
@@ -916,8 +846,9 @@ void tst_QSortFilterProxyModel::removeRows()
if (sortOrder != -1)
proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+
if (!filter.isEmpty())
- proxy.setFilterRegExp(QRegExp(filter));
+ setupFilter(&proxy, filter);
// remove the rows
QCOMPARE(proxy.removeRows(position, count, QModelIndex()), success);
@@ -939,14 +870,29 @@ class MyFilteredColumnProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
- MyFilteredColumnProxyModel(QObject *parent = 0)
- : QSortFilterProxyModel(parent) { }
+ MyFilteredColumnProxyModel(FilterType filterType, QObject *parent = 0) :
+ QSortFilterProxyModel(parent),
+ m_filterType(filterType)
+ { }
+
protected:
bool filterAcceptsColumn(int sourceColumn, const QModelIndex &) const
{
QString key = sourceModel()->headerData(sourceColumn, Qt::Horizontal).toString();
- return key.contains(filterRegExp());
+ bool result = false;
+ switch (m_filterType) {
+ case FilterType::RegExp:
+ result = key.contains(filterRegExp());
+ break;
+ case FilterType::RegularExpression:
+ result = key.contains(filterRegularExpression());
+ break;
+ }
+ return result;
}
+
+private:
+ FilterType m_filterType;
};
void tst_QSortFilterProxyModel::removeColumns_data()
@@ -1155,10 +1101,10 @@ void tst_QSortFilterProxyModel::removeColumns()
QFETCH(QStringList, expectedSource);
QStandardItemModel model;
- MyFilteredColumnProxyModel proxy;
+ MyFilteredColumnProxyModel proxy(m_filterType);
proxy.setSourceModel(&model);
if (!filter.isEmpty())
- proxy.setFilterRegExp(QRegExp(filter));
+ setupFilter(&proxy, filter);
// prepare model
model.setHorizontalHeaderLabels(initial);
@@ -1226,7 +1172,8 @@ void tst_QSortFilterProxyModel::filterColumns()
QModelIndex index = m_model->index(0, col, QModelIndex());
m_model->setData(index, initial.at(col), Qt::DisplayRole);
}
- m_proxy->setFilterRegExp(pattern);
+ setupFilter(m_proxy, pattern);
+
m_proxy->setFilterKeyColumn(-1);
// make sure the model is unchanged
for (int col = 0; col < m_model->columnCount(QModelIndex()); ++col) {
@@ -1292,6 +1239,7 @@ void tst_QSortFilterProxyModel::filter()
QFETCH(QString, pattern);
QFETCH(QStringList, initial);
QFETCH(QStringList, expected);
+
// prepare model
QVERIFY(m_model->insertRows(0, initial.count(), QModelIndex()));
QCOMPARE(m_model->rowCount(QModelIndex()), initial.count());
@@ -1301,7 +1249,7 @@ void tst_QSortFilterProxyModel::filter()
QModelIndex index = m_model->index(row, 0, QModelIndex());
m_model->setData(index, initial.at(row), Qt::DisplayRole);
}
- m_proxy->setFilterRegExp(pattern);
+ setupFilter(m_proxy, pattern);
// make sure the proxy is unfiltered
QCOMPARE(m_proxy->columnCount(QModelIndex()), 1);
QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.count());
@@ -1340,7 +1288,7 @@ void tst_QSortFilterProxyModel::filterHierarchy()
QFETCH(QStringList, initial);
QFETCH(QStringList, expected);
buildHierarchy(initial, m_model);
- m_proxy->setFilterRegExp(pattern);
+ setupFilter(m_proxy, pattern);
checkHierarchy(initial, m_model);
checkHierarchy(expected, m_proxy);
}
@@ -1405,6 +1353,18 @@ void tst_QSortFilterProxyModel::checkHierarchy(const QStringList &l, const QAbst
}
}
+void tst_QSortFilterProxyModel::setupFilter(QSortFilterProxyModel *model, const QString& pattern)
+{
+ switch (m_filterType) {
+ case FilterType::RegExp:
+ model->setFilterRegExp(pattern);
+ break;
+ case FilterType::RegularExpression:
+ model->setFilterRegularExpression(pattern);
+ break;
+ }
+}
+
class TestModel: public QAbstractTableModel
{
public:
@@ -1423,7 +1383,7 @@ void tst_QSortFilterProxyModel::filterTable()
TestModel model;
QSortFilterProxyModel filter;
filter.setSourceModel(&model);
- filter.setFilterRegExp("9");
+ setupFilter(&filter, QLatin1String("9"));
for (int i = 0; i < filter.rowCount(); ++i)
QVERIFY(filter.data(filter.index(i, 0)).toString().contains(QLatin1Char('9')));
@@ -1487,7 +1447,7 @@ void tst_QSortFilterProxyModel::filterCurrent()
view.setCurrentIndex(proxy.index(0, 0));
QCOMPARE(spy.count(), 1);
- proxy.setFilterRegExp(QRegExp("^B"));
+ setupFilter(&proxy, QLatin1String("^B"));
QCOMPARE(spy.count(), 2);
}
@@ -1498,7 +1458,7 @@ void tst_QSortFilterProxyModel::filter_qtbug30662()
proxy.setSourceModel(&model);
// make sure the filter does not match any entry
- proxy.setFilterRegExp(QRegExp("[0-9]+"));
+ setupFilter(&proxy, QLatin1String("[0-9]+"));
QStringList slSource;
slSource << "z" << "x" << "a" << "b";
@@ -1508,7 +1468,7 @@ void tst_QSortFilterProxyModel::filter_qtbug30662()
model.setStringList(slSource);
// without fix for QTBUG-30662 this will make all entries visible - but unsorted
- proxy.setFilterRegExp(QRegExp("[a-z]+"));
+ setupFilter(&proxy, QLatin1String("[a-z]+"));
QStringList slResult;
for (int i = 0; i < proxy.rowCount(); ++i)
@@ -1554,7 +1514,8 @@ void tst_QSortFilterProxyModel::changeSourceLayoutFilteredOut()
QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
// Filter everything out
- proxy.setFilterRegExp(QRegExp("c"));
+ setupFilter(&proxy, QLatin1String("c"));
+
QCOMPARE(removeSpy.count(), 1);
QCOMPARE(0, proxy.rowCount());
@@ -1563,7 +1524,8 @@ void tst_QSortFilterProxyModel::changeSourceLayoutFilteredOut()
QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
// Remove filter; we expect an insert
- proxy.setFilterRegExp(QRegExp(""));
+ setupFilter(&proxy, "");
+
QCOMPARE(insertSpy.count(), 1);
QCOMPARE(beforeSortFilter, proxy.rowCount());
}
@@ -1843,7 +1805,7 @@ void tst_QSortFilterProxyModel::changeFilter()
QVERIFY(initialRemoveSpy.isValid());
QVERIFY(initialInsertSpy.isValid());
- proxy.setFilterRegExp(initialFilter);
+ setupFilter(&proxy, initialFilter);
QCOMPARE(initialRemoveSpy.count(), initialRemoveIntervals.count());
QCOMPARE(initialInsertSpy.count(), 0);
@@ -1867,7 +1829,7 @@ void tst_QSortFilterProxyModel::changeFilter()
QVERIFY(finalRemoveSpy.isValid());
QVERIFY(finalInsertSpy.isValid());
- proxy.setFilterRegExp(finalFilter);
+ setupFilter(&proxy, finalFilter);
QCOMPARE(finalRemoveSpy.count(), finalRemoveIntervals.count());
for (int i = 0; i < finalRemoveSpy.count(); ++i) {
@@ -2061,7 +2023,7 @@ void tst_QSortFilterProxyModel::changeSourceData()
proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
(void)proxy.rowCount(QModelIndex()); // force mapping
- proxy.setFilterRegExp(filter);
+ setupFilter(&proxy, filter);
QCOMPARE(proxy.rowCount(), expectedInitialProxyItems.count());
for (int i = 0; i < expectedInitialProxyItems.count(); ++i) {
@@ -2254,7 +2216,8 @@ void tst_QSortFilterProxyModel::sortFilterRole()
model.setData(index, sourceItems.at(i).second, Qt::UserRole);
}
- proxy.setFilterRegExp("2");
+ setupFilter(&proxy, QLatin1String("2"));
+
QCOMPARE(proxy.rowCount(), 0); // Qt::DisplayRole is default role
proxy.setFilterRole(Qt::UserRole);
@@ -2263,7 +2226,8 @@ void tst_QSortFilterProxyModel::sortFilterRole()
proxy.setFilterRole(Qt::DisplayRole);
QCOMPARE(proxy.rowCount(), 0);
- proxy.setFilterRegExp("1|2|3");
+ setupFilter(&proxy, QLatin1String("1|2|3"));
+
QCOMPARE(proxy.rowCount(), 0);
proxy.setFilterRole(Qt::UserRole);
@@ -2274,7 +2238,8 @@ void tst_QSortFilterProxyModel::sortFilterRole()
proxy.setSortRole(Qt::UserRole);
proxy.setFilterRole(Qt::DisplayRole);
- proxy.setFilterRegExp("a|c");
+ setupFilter(&proxy, QLatin1String("a|c"));
+
QCOMPARE(proxy.rowCount(), orderedItems.count());
for (int i = 0; i < proxy.rowCount(); ++i) {
QModelIndex index = proxy.index(i, 0, QModelIndex());
@@ -2298,7 +2263,8 @@ void tst_QSortFilterProxyModel::selectionFilteredOut()
view.setCurrentIndex(proxy.index(0, 0));
QCOMPARE(spy.count(), 1);
- proxy.setFilterRegExp(QRegExp("^B"));
+
+ setupFilter(&proxy, QLatin1String("^B"));
QCOMPARE(spy.count(), 2);
}
@@ -2384,7 +2350,7 @@ void tst_QSortFilterProxyModel::match()
}
proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
- proxy.setFilterRegExp(filter);
+ setupFilter(&proxy, filter);
QModelIndex startIndex = proxy.index(proxyStartRow, 0);
QModelIndexList indexes = proxy.match(startIndex, Qt::DisplayRole, what,
@@ -2509,7 +2475,8 @@ void tst_QSortFilterProxyModel::filterOutParentAndFilterInChild()
QSortFilterProxyModel proxy;
proxy.setSourceModel(&model);
- proxy.setFilterRegExp("A|B");
+ setupFilter(&proxy, QLatin1String("A|B"));
+
QStandardItem *itemA = new QStandardItem("A");
model.appendRow(itemA); // not filtered
QStandardItem *itemB = new QStandardItem("B");
@@ -2523,7 +2490,7 @@ void tst_QSortFilterProxyModel::filterOutParentAndFilterInChild()
QVERIFY(removedSpy.isValid());
QVERIFY(insertedSpy.isValid());
- proxy.setFilterRegExp("C"); // A and B will be filtered out, C filtered in
+ setupFilter(&proxy, QLatin1String("C")); // A and B will be filtered out, C filtered in
// we should now have been notified that the subtree represented by itemA has been removed
QCOMPARE(removedSpy.count(), 1);
@@ -2936,7 +2903,7 @@ void tst_QSortFilterProxyModel::hiddenChildren()
itemA->appendRow(itemB);
QStandardItem *itemC = new QStandardItem("C");
itemA->appendRow(itemC);
- proxy.setFilterRegExp("VISIBLE");
+ setupFilter(&proxy, QLatin1String("VISIBLE"));
QCOMPARE(proxy.rowCount(QModelIndex()) , 1);
QPersistentModelIndex indexA = proxy.index(0,0);
@@ -2963,7 +2930,8 @@ void tst_QSortFilterProxyModel::hiddenChildren()
QModelIndex indexC = proxy.index(0, 0, indexA);
QCOMPARE(proxy.data(indexC).toString(), QString::fromLatin1("C VISIBLE"));
- proxy.setFilterRegExp("C");
+ setupFilter(&proxy, QLatin1String("C"));
+
QCOMPARE(proxy.rowCount(QModelIndex()), 0);
itemC->setText("invisible");
itemA->setText("AC");
@@ -3285,7 +3253,8 @@ void tst_QSortFilterProxyModel::mapSelectionFromSource()
QSortFilterProxyModel proxy;
proxy.setDynamicSortFilter(true);
- proxy.setFilterRegExp("d.*");
+ setupFilter(&proxy, QLatin1String("d.*"));
+
proxy.setSourceModel(&model);
// Only "delta" remains.
@@ -3840,13 +3809,13 @@ void tst_QSortFilterProxyModel::moveSourceRows()
filterProxy.setDynamicSortFilter(true);
filterProxy.sort(0, Qt::AscendingOrder);
filterProxy.setSourceModel(&proxy);
- filterProxy.setFilterRegExp("6"); // One of the parents
+ setupFilter(&filterProxy, QLatin1String("6")); // One of the parents
QSortFilterProxyModel filterBothProxy;
filterBothProxy.setDynamicSortFilter(true);
filterBothProxy.sort(0, Qt::AscendingOrder);
filterBothProxy.setSourceModel(&proxy);
- filterBothProxy.setFilterRegExp("5"); // The parents are 6 and 3. This filters both out.
+ setupFilter(&filterBothProxy, QLatin1String("5")); // The parents are 6 and 3. This filters both out.
QSignalSpy modelBeforeSpy(&model, &DynamicTreeModel::rowsAboutToBeMoved);
QSignalSpy modelAfterSpy(&model, &DynamicTreeModel::rowsMoved);
@@ -4244,7 +4213,7 @@ void tst_QSortFilterProxyModel::filterHint()
QSortFilterProxyModel proxy2;
proxy2.setSourceModel(&proxy1);
proxy2.setFilterRole(Qt::DisplayRole);
- proxy2.setFilterRegExp("^[^ ]*$");
+ setupFilter(&proxy2, QLatin1String("^[^ ]*$"));
proxy2.setDynamicSortFilter(true);
QSignalSpy proxy1BeforeSpy(&proxy1, &QSortFilterProxyModel::layoutAboutToBeChanged);
@@ -4372,8 +4341,7 @@ void tst_QSortFilterProxyModel::sourceLayoutChangeLeavesValidPersistentIndexes()
QSortFilterProxyModel proxy1;
proxy1.setSourceModel(&model);
Q_SET_OBJECT_NAME(proxy1);
-
- proxy1.setFilterRegExp("1|2");
+ setupFilter(&proxy1, QLatin1String("1|2"));
// The current state of things:
// model proxy
@@ -4420,7 +4388,7 @@ void tst_QSortFilterProxyModel::rowMoveLeavesValidPersistentIndexes()
proxy1.setSourceModel(&model);
Q_SET_OBJECT_NAME(proxy1);
- proxy1.setFilterRegExp("1|2");
+ setupFilter(&proxy1, QLatin1String("1|2"));
auto item5 = model.match(model.index(0, 0), Qt::DisplayRole, "5", 1, Qt::MatchRecursive).first();
auto item3 = model.match(model.index(0, 0), Qt::DisplayRole, "3", 1, Qt::MatchRecursive).first();
@@ -4482,6 +4450,44 @@ void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged_data()
QTest::newRow("many_changes_no_layoutChanged") << -1 << Qt::DisplayRole << "7,5,4,3,2,1,0,8" << "75432108" << "0248" << 0;
}
+// Custom version of QStringListModel which supports emitting dataChanged for many rows at once
+class CustomStringListModel : public QAbstractListModel
+{
+public:
+ bool setData(const QModelIndex &index, const QVariant &value, int role) override
+ {
+ if (index.row() >= 0 && index.row() < lst.size()
+ && (role == Qt::EditRole || role == Qt::DisplayRole)) {
+ lst.replace(index.row(), value.toString());
+ emit dataChanged(index, index, { Qt::DisplayRole, Qt::EditRole });
+ return true;
+ }
+ return false;
+ }
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
+ {
+ if (role == Qt::DisplayRole || role == Qt::EditRole)
+ return lst.at(index.row());
+ return QVariant();
+ }
+ int rowCount(const QModelIndex & = QModelIndex()) const override { return lst.count(); }
+
+ void replaceData(const QStringList &newData)
+ {
+ lst = newData;
+ emit dataChanged(index(0, 0), index(rowCount() - 1, 0), { Qt::DisplayRole, Qt::EditRole });
+ }
+
+ void emitDecorationChangedSignal()
+ {
+ const QModelIndex idx = index(0, 0);
+ emit dataChanged(idx, idx, { Qt::DecorationRole });
+ }
+
+private:
+ QStringList lst;
+};
+
void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged()
{
QFETCH(int, changedRow);
@@ -4491,45 +4497,6 @@ void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged()
QFETCH(QString, expectedProxyRowTexts);
QFETCH(int, expectedLayoutChanged);
- // Custom version of QStringListModel which supports emitting dataChanged for many rows at once
- class CustomStringListModel : public QAbstractListModel
- {
- public:
- bool setData(const QModelIndex &index, const QVariant &value, int role) override
- {
- if (index.row() >= 0 && index.row() < lst.size()
- && (role == Qt::EditRole || role == Qt::DisplayRole)) {
- lst.replace(index.row(), value.toString());
- emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
- return true;
- }
- return false;
- }
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
- {
- if (role == Qt::DisplayRole || role == Qt::EditRole)
- return lst.at(index.row());
- return QVariant();
- }
- int rowCount(const QModelIndex & = QModelIndex()) const override
- {
- return lst.count();
- }
-
- void replaceData(const QStringList &newData)
- {
- lst = newData;
- emit dataChanged(index(0, 0), index(rowCount()-1, 0), {Qt::DisplayRole, Qt::EditRole});
- }
-
- void emitDecorationChangedSignal()
- {
- const QModelIndex idx = index(0, 0);
- emit dataChanged(idx, idx, {Qt::DecorationRole});
- }
- private:
- QStringList lst;
- };
CustomStringListModel model;
QStringList strings;
for (auto i = 8; i >= 1; --i)
@@ -4567,6 +4534,137 @@ void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged()
QCOMPARE(proxyLayoutChangedSpy.size(), expectedLayoutChanged);
}
+void tst_QSortFilterProxyModel::removeIntervals_data()
+{
+ QTest::addColumn<QStringList>("sourceItems");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QString>("filter");
+ QTest::addColumn<QStringList>("replacementSourceItems");
+ QTest::addColumn<IntPairList>("expectedRemovedProxyIntervals");
+ QTest::addColumn<QStringList>("expectedProxyItems");
+
+ QTest::newRow("filter all, sort ascending")
+ << (QStringList() << "a"
+ << "b"
+ << "c") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "[^x]" // filter
+ << (QStringList() << "x"
+ << "x"
+ << "x") // replacementSourceItems
+ << (IntPairList() << IntPair(0, 2)) // expectedRemovedIntervals
+ << QStringList() // expectedProxyItems
+ ;
+
+ QTest::newRow("filter all, sort descending")
+ << (QStringList() << "a"
+ << "b"
+ << "c") // sourceItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << "[^x]" // filter
+ << (QStringList() << "x"
+ << "x"
+ << "x") // replacementSourceItems
+ << (IntPairList() << IntPair(0, 2)) // expectedRemovedIntervals
+ << QStringList() // expectedProxyItems
+ ;
+
+ QTest::newRow("filter first and last, sort ascending")
+ << (QStringList() << "a"
+ << "b"
+ << "c") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "[^x]" // filter
+ << (QStringList() << "x"
+ << "b"
+ << "x") // replacementSourceItems
+ << (IntPairList() << IntPair(2, 2) << IntPair(0, 0)) // expectedRemovedIntervals
+ << (QStringList() << "b") // expectedProxyItems
+ ;
+
+ QTest::newRow("filter first and last, sort descending")
+ << (QStringList() << "a"
+ << "b"
+ << "c") // sourceItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << "[^x]" // filter
+ << (QStringList() << "x"
+ << "b"
+ << "x") // replacementSourceItems
+ << (IntPairList() << IntPair(2, 2) << IntPair(0, 0)) // expectedRemovedIntervals
+ << (QStringList() << "b") // expectedProxyItems
+ ;
+}
+
+void tst_QSortFilterProxyModel::removeIntervals()
+{
+ QFETCH(QStringList, sourceItems);
+ QFETCH(int, sortOrder);
+ QFETCH(QString, filter);
+ QFETCH(QStringList, replacementSourceItems);
+ QFETCH(IntPairList, expectedRemovedProxyIntervals);
+ QFETCH(QStringList, expectedProxyItems);
+
+ CustomStringListModel model;
+ QSortFilterProxyModel proxy;
+
+ model.replaceData(sourceItems);
+ proxy.setSourceModel(&model);
+
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex sindex = model.index(i, 0, QModelIndex());
+ QModelIndex pindex = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(pindex, Qt::DisplayRole), model.data(sindex, Qt::DisplayRole));
+ }
+
+ proxy.setDynamicSortFilter(true);
+
+ if (sortOrder != -1)
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ if (!filter.isEmpty())
+ setupFilter(&proxy, filter);
+
+ (void)proxy.rowCount(QModelIndex()); // force mapping
+
+ QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
+ QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
+ QSignalSpy aboutToRemoveSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeRemoved);
+ QSignalSpy aboutToInsertSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeInserted);
+
+ QVERIFY(removeSpy.isValid());
+ QVERIFY(insertSpy.isValid());
+ QVERIFY(aboutToRemoveSpy.isValid());
+ QVERIFY(aboutToInsertSpy.isValid());
+
+ model.replaceData(replacementSourceItems);
+
+ QCOMPARE(aboutToRemoveSpy.count(), expectedRemovedProxyIntervals.count());
+ for (int i = 0; i < aboutToRemoveSpy.count(); ++i) {
+ QList<QVariant> args = aboutToRemoveSpy.at(i);
+ QCOMPARE(args.at(1).type(), QVariant::Int);
+ QCOMPARE(args.at(2).type(), QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second);
+ }
+ QCOMPARE(removeSpy.count(), expectedRemovedProxyIntervals.count());
+ for (int i = 0; i < removeSpy.count(); ++i) {
+ QList<QVariant> args = removeSpy.at(i);
+ QCOMPARE(args.at(1).type(), QVariant::Int);
+ QCOMPARE(args.at(2).type(), QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second);
+ }
+
+ QCOMPARE(insertSpy.count(), 0);
+ QCOMPARE(aboutToInsertSpy.count(), 0);
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxyItems.count());
+ for (int i = 0; i < expectedProxyItems.count(); ++i) {
+ QModelIndex pindex = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(pindex, Qt::DisplayRole).toString(), expectedProxyItems.at(i));
+ }
+}
+
void tst_QSortFilterProxyModel::dynamicFilterWithoutSort()
{
QStringListModel model;
@@ -4849,5 +4947,4 @@ void tst_QSortFilterProxyModel::filterAndInsertRow()
}
}
-QTEST_MAIN(tst_QSortFilterProxyModel)
#include "tst_qsortfilterproxymodel.moc"
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h
new file mode 100644
index 0000000000..82d4b7344e
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef TST_QSORTFILTERPROXYMODEL_H
+#define TST_QSORTFILTERPROXYMODEL_H
+
+#include <QtTest/QtTest>
+#include "dynamictreemodel.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtGui/QStandardItem>
+#include <QtWidgets/QTreeView>
+#include <QtWidgets/QTableView>
+
+#include <qdebug.h>
+
+typedef QList<int> IntList;
+typedef QPair<int, int> IntPair;
+typedef QList<IntPair> IntPairList;
+
+enum class FilterType {
+ RegExp,
+ RegularExpression
+};
+
+Q_DECLARE_METATYPE(QList<QPersistentModelIndex>)
+
+class tst_QSortFilterProxyModel : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QSortFilterProxyModel();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void cleanup();
+
+private slots:
+ void getSetCheck();
+ void sort_data();
+ void sort();
+ void sortHierarchy_data();
+ void sortHierarchy();
+
+ void insertRows_data();
+ void insertRows();
+ void prependRow();
+ void appendRowFromCombobox_data();
+ void appendRowFromCombobox();
+ void removeRows_data();
+ void removeRows();
+ void removeColumns_data();
+ void removeColumns();
+ void insertAfterSelect();
+ void removeAfterSelect();
+ void filter_data();
+ void filter();
+ void filterHierarchy_data();
+ void filterHierarchy();
+ void filterColumns_data();
+ void filterColumns();
+
+ void filterTable();
+ void filterCurrent();
+ void filter_qtbug30662();
+
+ void changeSourceLayout();
+ void changeSourceLayoutFilteredOut();
+ void removeSourceRows_data();
+ void removeSourceRows();
+ void insertSourceRows_data();
+ void insertSourceRows();
+ void changeFilter_data();
+ void changeFilter();
+ void changeSourceData_data();
+ void changeSourceData();
+ void changeSourceDataKeepsStableSorting_qtbug1548();
+ void changeSourceDataForwardsRoles_qtbug35440();
+ void resortingDoesNotBreakTreeModels();
+ void dynamicFilterWithoutSort();
+ void sortFilterRole();
+ void selectionFilteredOut();
+ void match_data();
+ void match();
+ void insertIntoChildrenlessItem();
+ void invalidateMappedChildren();
+ void insertRowIntoFilteredParent();
+ void filterOutParentAndFilterInChild();
+
+ void sourceInsertRows();
+ void sourceModelDeletion();
+
+ void sortColumnTracking1();
+ void sortColumnTracking2();
+
+ void sortStable();
+
+ void hiddenColumns();
+ void insertRowsSort();
+ void staticSorting();
+ void dynamicSorting();
+ void fetchMore();
+ void hiddenChildren();
+ void mapFromToSource();
+ void removeRowsRecursive();
+ void doubleProxySelectionSetSourceModel();
+ void appearsAndSort();
+ void unnecessaryDynamicSorting();
+ void unnecessaryMapCreation();
+ void resetInvalidate_data();
+ void resetInvalidate();
+
+ void testMultipleProxiesWithSelection();
+ void mapSelectionFromSource();
+ void testResetInternalData();
+ void filteredColumns();
+ void headerDataChanged();
+
+ void testParentLayoutChanged();
+ void moveSourceRows();
+
+ void hierarchyFilterInvalidation();
+ void simpleFilterInvalidation();
+
+ void chainedProxyModelRoleNames();
+
+ void noMapAfterSourceDelete();
+ void forwardDropApi();
+ void canDropMimeData();
+ void filterHint();
+
+ void sourceLayoutChangeLeavesValidPersistentIndexes();
+ void rowMoveLeavesValidPersistentIndexes();
+
+ void emitLayoutChangedOnlyIfSortingChanged_data();
+ void emitLayoutChangedOnlyIfSortingChanged();
+
+ void checkSetNewModel();
+ void filterAndInsertRow_data();
+ void filterAndInsertRow();
+ void filterAndInsertColumn_data();
+ void filterAndInsertColumn();
+
+ void removeIntervals_data();
+ void removeIntervals();
+
+protected:
+ void buildHierarchy(const QStringList &data, QAbstractItemModel *model);
+ void checkHierarchy(const QStringList &data, const QAbstractItemModel *model);
+ void setupFilter(QSortFilterProxyModel *model, const QString& pattern);
+
+protected:
+ FilterType m_filterType;
+
+private:
+ QStandardItemModel *m_model;
+ QSortFilterProxyModel *m_proxy;
+};
+
+Q_DECLARE_METATYPE(QAbstractItemModel::LayoutChangeHint)
+
+#endif // TST_QSORTFILTERPROXYMODEL_H
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/.gitignore b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/.gitignore
new file mode 100644
index 0000000000..4fdaebc09d
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/.gitignore
@@ -0,0 +1 @@
+tst_qsortfilterproxymodel_regexp
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/qsortfilterproxymodel_regexp.pro b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/qsortfilterproxymodel_regexp.pro
new file mode 100644
index 0000000000..7c510930f4
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/qsortfilterproxymodel_regexp.pro
@@ -0,0 +1,16 @@
+CONFIG += testcase
+TARGET = tst_qsortfilterproxymodel_regexp
+
+QT += widgets testlib
+mtdir = ../../../other/qabstractitemmodelutils
+qsfpmdir = ../qsortfilterproxymodel_common
+
+INCLUDEPATH += $$PWD/$${mtdir} $$PWD/$${qsfpmdir}
+SOURCES += \
+ tst_qsortfilterproxymodel_regexp.cpp \
+ $${qsfpmdir}/tst_qsortfilterproxymodel.cpp \
+ $${mtdir}/dynamictreemodel.cpp
+
+HEADERS += \
+ $${qsfpmdir}/tst_qsortfilterproxymodel.h \
+ $${mtdir}/dynamictreemodel.h
diff --git a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/tst_qsortfilterproxymodel_regexp.cpp
index a815c6cab9..38607f1378 100644
--- a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/tst_qsortfilterproxymodel_regexp.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
+** 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.
@@ -27,13 +27,43 @@
****************************************************************************/
#include <QtTest/QtTest>
-#include "../tst_qregularexpression.h"
-class tst_QRegularExpression_DefaultOptimize : public tst_QRegularExpression
+#include "tst_qsortfilterproxymodel.h"
+
+class tst_QSortFilterProxyModelRegExp : public tst_QSortFilterProxyModel
{
Q_OBJECT
+public:
+ tst_QSortFilterProxyModelRegExp();
+private slots:
+ void tst_invalid();
+ void tst_caseSensitivity();
};
-QTEST_APPLESS_MAIN(tst_QRegularExpression_DefaultOptimize)
+tst_QSortFilterProxyModelRegExp::tst_QSortFilterProxyModelRegExp() :
+ tst_QSortFilterProxyModel()
+{
+ m_filterType = FilterType::RegExp;
+}
+
+void tst_QSortFilterProxyModelRegExp::tst_invalid()
+{
+ const QLatin1String pattern("test");
+ QSortFilterProxyModel model;
+ model.setFilterRegExp(pattern);
+ QCOMPARE(model.filterRegExp(), QRegExp(pattern));
+ model.setFilterRegularExpression(pattern);
+ QCOMPARE(model.filterRegExp(), QRegExp());
+}
+
+void tst_QSortFilterProxyModelRegExp::tst_caseSensitivity()
+{
+ const QLatin1String pattern("test");
+ QSortFilterProxyModel model;
+ model.setFilterCaseSensitivity(Qt::CaseInsensitive);
+ model.setFilterRegExp(pattern);
+ QCOMPARE(model.filterCaseSensitivity(), Qt::CaseInsensitive);
+}
-#include "tst_qregularexpression_defaultoptimize.moc"
+QTEST_MAIN(tst_QSortFilterProxyModelRegExp)
+#include "tst_qsortfilterproxymodel_regexp.moc"
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/.gitignore b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/.gitignore
new file mode 100644
index 0000000000..286771e250
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/.gitignore
@@ -0,0 +1 @@
+tst_qsortfilterproxymodel_regularexpression
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/qsortfilterproxymodel_regularexpression.pro b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/qsortfilterproxymodel_regularexpression.pro
new file mode 100644
index 0000000000..e993d07126
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/qsortfilterproxymodel_regularexpression.pro
@@ -0,0 +1,16 @@
+CONFIG += testcase
+TARGET = tst_qsortfilterproxymodel_regularexpression
+
+QT += widgets testlib
+mtdir = ../../../other/qabstractitemmodelutils
+qsfpmdir = ../qsortfilterproxymodel_common
+
+INCLUDEPATH += $$PWD/$${mtdir} $${qsfpmdir}
+SOURCES += \
+ tst_qsortfilterproxymodel_regularexpression.cpp \
+ $${qsfpmdir}/tst_qsortfilterproxymodel.cpp \
+ $${mtdir}/dynamictreemodel.cpp
+
+HEADERS += \
+ $${qsfpmdir}/tst_qsortfilterproxymodel.h \
+ $${mtdir}/dynamictreemodel.h
diff --git a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp
index 6d2ae48235..821e199bcb 100644
--- a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
+** 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.
@@ -27,25 +27,33 @@
****************************************************************************/
#include <QtTest/QtTest>
-#include "../tst_qregularexpression.h"
-class tst_QRegularExpression_AlwaysOptimize : public tst_QRegularExpression
+#include "tst_qsortfilterproxymodel.h"
+
+class tst_QSortFilterProxyModelRegularExpression : public tst_QSortFilterProxyModel
{
Q_OBJECT
-
+public:
+ tst_QSortFilterProxyModelRegularExpression();
private slots:
- void initTestCase();
+ void tst_invalid();
};
-QT_BEGIN_NAMESPACE
-extern Q_CORE_EXPORT unsigned int qt_qregularexpression_optimize_after_use_count; // from qregularexpression.cpp
-QT_END_NAMESPACE
-
-void tst_QRegularExpression_AlwaysOptimize::initTestCase()
+tst_QSortFilterProxyModelRegularExpression::tst_QSortFilterProxyModelRegularExpression() :
+ tst_QSortFilterProxyModel()
{
- qt_qregularexpression_optimize_after_use_count = 1;
+ m_filterType = FilterType::RegularExpression;
}
-QTEST_APPLESS_MAIN(tst_QRegularExpression_AlwaysOptimize)
+void tst_QSortFilterProxyModelRegularExpression::tst_invalid()
+{
+ const QLatin1String pattern("test");
+ QSortFilterProxyModel model;
+ model.setFilterRegularExpression(pattern);
+ QCOMPARE(model.filterRegularExpression(), QRegularExpression(pattern));
+ model.setFilterRegExp(pattern);
+ QCOMPARE(model.filterRegularExpression(), QRegularExpression());
+}
-#include "tst_qregularexpression_alwaysoptimize.moc"
+QTEST_MAIN(tst_QSortFilterProxyModelRegularExpression)
+#include "tst_qsortfilterproxymodel_regularexpression.moc"
diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
index 5e9dbdd226..a53501b9dd 100644
--- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
+++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
@@ -415,7 +415,7 @@ void tst_QCoreApplication::removePostedEvents()
expected.clear();
}
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
class DeliverInDefinedOrderThread : public QThread
{
Q_OBJECT
@@ -532,7 +532,7 @@ void tst_QCoreApplication::deliverInDefinedOrder()
QObject::connect(&obj, SIGNAL(done()), &app, SLOT(quit()));
app.exec();
}
-#endif // QT_NO_QTHREAD
+#endif // QT_CONFIG(thread)
void tst_QCoreApplication::applicationPid()
{
diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h
index b6c20a915f..105cca5174 100644
--- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h
+++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h
@@ -43,7 +43,7 @@ private slots:
void argc();
void postEvent();
void removePostedEvents();
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
void deliverInDefinedOrder();
#endif
void applicationPid();
diff --git a/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST b/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST
index 4cd3c2f0c8..4dd71ca9f4 100644
--- a/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST
+++ b/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST
@@ -1,3 +1,4 @@
[elapsed]
windows
osx-10.12
+osx-10.13
diff --git a/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST b/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST
index 402d87b82f..06588188d4 100644
--- a/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST
+++ b/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST
@@ -1,6 +1,6 @@
[sendPostedEvents]
windows
-osx
[registerTimer]
windows
+winrt
osx
diff --git a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
index 5784f0728c..49c10c6a24 100644
--- a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
+++ b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
@@ -28,6 +28,7 @@
#ifdef QT_GUI_LIB
# include <QtGui/QGuiApplication>
+# define tst_QEventDispatcher tst_QGuiEventDispatcher
#else
# include <QtCore/QCoreApplication>
#endif
@@ -92,77 +93,151 @@ void tst_QEventDispatcher::initTestCase()
}
}
+class TimerManager {
+ Q_DISABLE_COPY(TimerManager)
+
+public:
+ TimerManager(QAbstractEventDispatcher *eventDispatcher, QObject *parent)
+ : m_eventDispatcher(eventDispatcher), m_parent(parent)
+ {
+ }
+
+ ~TimerManager()
+ {
+ if (!registeredTimers().isEmpty())
+ m_eventDispatcher->unregisterTimers(m_parent);
+ }
+
+ TimerManager(TimerManager &&) = delete;
+ TimerManager &operator=(TimerManager &&) = delete;
+
+ int preciseTimerId() const { return m_preciseTimerId; }
+ int coarseTimerId() const { return m_coarseTimerId; }
+ int veryCoarseTimerId() const { return m_veryCoarseTimerId; }
+
+ bool foundPrecise() const { return m_preciseTimerId > 0; }
+ bool foundCoarse() const { return m_coarseTimerId > 0; }
+ bool foundVeryCoarse() const { return m_veryCoarseTimerId > 0; }
+
+ QList<QAbstractEventDispatcher::TimerInfo> registeredTimers() const
+ {
+ return m_eventDispatcher->registeredTimers(m_parent);
+ }
+
+ void registerAll()
+ {
+ // start 3 timers, each with the different timer types and different intervals
+ m_preciseTimerId = m_eventDispatcher->registerTimer(
+ PreciseTimerInterval, Qt::PreciseTimer, m_parent);
+ m_coarseTimerId = m_eventDispatcher->registerTimer(
+ CoarseTimerInterval, Qt::CoarseTimer, m_parent);
+ m_veryCoarseTimerId = m_eventDispatcher->registerTimer(
+ VeryCoarseTimerInterval, Qt::VeryCoarseTimer, m_parent);
+ QVERIFY(m_preciseTimerId > 0);
+ QVERIFY(m_coarseTimerId > 0);
+ QVERIFY(m_veryCoarseTimerId > 0);
+ findTimers();
+ }
+
+ void unregister(int timerId)
+ {
+ m_eventDispatcher->unregisterTimer(timerId);
+ findTimers();
+ }
+
+ void unregisterAll()
+ {
+ m_eventDispatcher->unregisterTimers(m_parent);
+ findTimers();
+ }
+
+private:
+ void findTimers()
+ {
+ bool foundPrecise = false;
+ bool foundCoarse = false;
+ bool foundVeryCoarse = false;
+ const QList<QAbstractEventDispatcher::TimerInfo> timers = registeredTimers();
+ for (int i = 0; i < timers.count(); ++i) {
+ const QAbstractEventDispatcher::TimerInfo &timerInfo = timers.at(i);
+ if (timerInfo.timerId == m_preciseTimerId) {
+ QCOMPARE(timerInfo.interval, int(PreciseTimerInterval));
+ QCOMPARE(timerInfo.timerType, Qt::PreciseTimer);
+ foundPrecise = true;
+ } else if (timerInfo.timerId == m_coarseTimerId) {
+ QCOMPARE(timerInfo.interval, int(CoarseTimerInterval));
+ QCOMPARE(timerInfo.timerType, Qt::CoarseTimer);
+ foundCoarse = true;
+ } else if (timerInfo.timerId == m_veryCoarseTimerId) {
+ QCOMPARE(timerInfo.interval, int(VeryCoarseTimerInterval));
+ QCOMPARE(timerInfo.timerType, Qt::VeryCoarseTimer);
+ foundVeryCoarse = true;
+ }
+ }
+ if (!foundPrecise)
+ m_preciseTimerId = -1;
+ if (!foundCoarse)
+ m_coarseTimerId = -1;
+ if (!foundVeryCoarse)
+ m_veryCoarseTimerId = -1;
+ }
+
+ QAbstractEventDispatcher *m_eventDispatcher = nullptr;
+
+ int m_preciseTimerId = -1;
+ int m_coarseTimerId = -1;
+ int m_veryCoarseTimerId = -1;
+
+ QObject *m_parent = nullptr;
+};
+
// test that the eventDispatcher's timer implementation is complete and working
void tst_QEventDispatcher::registerTimer()
{
-#define FIND_TIMERS() \
- do { \
- foundPrecise = false; \
- foundCoarse = false; \
- foundVeryCoarse = false; \
- for (int i = 0; i < registeredTimers.count(); ++i) { \
- const QAbstractEventDispatcher::TimerInfo &timerInfo = registeredTimers.at(i); \
- if (timerInfo.timerId == preciseTimerId) { \
- QCOMPARE(timerInfo.interval, int(PreciseTimerInterval)); \
- QCOMPARE(timerInfo.timerType, Qt::PreciseTimer); \
- foundPrecise = true; \
- } else if (timerInfo.timerId == coarseTimerId) { \
- QCOMPARE(timerInfo.interval, int(CoarseTimerInterval)); \
- QCOMPARE(timerInfo.timerType, Qt::CoarseTimer); \
- foundCoarse = true; \
- } else if (timerInfo.timerId == veryCoarseTimerId) { \
- QCOMPARE(timerInfo.interval, int(VeryCoarseTimerInterval)); \
- QCOMPARE(timerInfo.timerType, Qt::VeryCoarseTimer); \
- foundVeryCoarse = true; \
- } \
- } \
- } while (0)
-
- // start 3 timers, each with the different timer types and different intervals
- int preciseTimerId = eventDispatcher->registerTimer(PreciseTimerInterval, Qt::PreciseTimer, this);
- int coarseTimerId = eventDispatcher->registerTimer(CoarseTimerInterval, Qt::CoarseTimer, this);
- int veryCoarseTimerId = eventDispatcher->registerTimer(VeryCoarseTimerInterval, Qt::VeryCoarseTimer, this);
- QVERIFY(preciseTimerId > 0);
- QVERIFY(coarseTimerId > 0);
- QVERIFY(veryCoarseTimerId > 0);
+ TimerManager timers(eventDispatcher, this);
+ timers.registerAll();
+ if (QTest::currentTestFailed())
+ return;
// check that all 3 are present in the eventDispatcher's registeredTimer() list
- QList<QAbstractEventDispatcher::TimerInfo> registeredTimers = eventDispatcher->registeredTimers(this);
- QCOMPARE(registeredTimers.count(), 3);
- bool foundPrecise, foundCoarse, foundVeryCoarse;
- FIND_TIMERS();
- QVERIFY(foundPrecise && foundCoarse && foundVeryCoarse);
+ QCOMPARE(timers.registeredTimers().count(), 3);
+ QVERIFY(timers.foundPrecise());
+ QVERIFY(timers.foundCoarse());
+ QVERIFY(timers.foundVeryCoarse());
// process events, waiting for the next event... this should only fire the precise timer
receivedEventType = -1;
timerIdFromEvent = -1;
QTRY_COMPARE_WITH_TIMEOUT(receivedEventType, int(QEvent::Timer), PreciseTimerInterval * 2);
- QCOMPARE(timerIdFromEvent, preciseTimerId);
+ QCOMPARE(timerIdFromEvent, timers.preciseTimerId());
// now unregister it and make sure it's gone
- eventDispatcher->unregisterTimer(preciseTimerId);
- registeredTimers = eventDispatcher->registeredTimers(this);
- QCOMPARE(registeredTimers.count(), 2);
- FIND_TIMERS();
- QVERIFY(!foundPrecise && foundCoarse && foundVeryCoarse);
+ timers.unregister(timers.preciseTimerId());
+ if (QTest::currentTestFailed())
+ return;
+ QCOMPARE(timers.registeredTimers().count(), 2);
+ QVERIFY(!timers.foundPrecise());
+ QVERIFY(timers.foundCoarse());
+ QVERIFY(timers.foundVeryCoarse());
// do the same again for the coarse timer
receivedEventType = -1;
timerIdFromEvent = -1;
QTRY_COMPARE_WITH_TIMEOUT(receivedEventType, int(QEvent::Timer), CoarseTimerInterval * 2);
- QCOMPARE(timerIdFromEvent, coarseTimerId);
+ QCOMPARE(timerIdFromEvent, timers.coarseTimerId());
// now unregister it and make sure it's gone
- eventDispatcher->unregisterTimer(coarseTimerId);
- registeredTimers = eventDispatcher->registeredTimers(this);
- QCOMPARE(registeredTimers.count(), 1);
- FIND_TIMERS();
- QVERIFY(!foundPrecise && !foundCoarse && foundVeryCoarse);
+ timers.unregister(timers.coarseTimerId());
+ if (QTest::currentTestFailed())
+ return;
+ QCOMPARE(timers.registeredTimers().count(), 1);
+ QVERIFY(!timers.foundPrecise());
+ QVERIFY(!timers.foundCoarse());
+ QVERIFY(timers.foundVeryCoarse());
// not going to wait for the VeryCoarseTimer, would take too long, just unregister it
- eventDispatcher->unregisterTimers(this);
- registeredTimers = eventDispatcher->registeredTimers(this);
- QVERIFY(registeredTimers.isEmpty());
-
-#undef FIND_TIMERS
+ timers.unregisterAll();
+ if (QTest::currentTestFailed())
+ return;
+ QVERIFY(timers.registeredTimers().isEmpty());
}
void tst_QEventDispatcher::sendPostedEvents_data()
diff --git a/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp b/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp
index e4aa8b80c0..6ed0a6caa9 100644
--- a/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp
+++ b/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp
@@ -37,19 +37,33 @@ class tst_QMetaEnum : public QObject
Q_OBJECT
public:
enum SuperEnum { SuperValue1 = 1 , SuperValue2 = 2 };
+ enum Flag { Flag1 = 1 , Flag2 = 2 };
+ Q_DECLARE_FLAGS(Flags, Flag)
Q_ENUM(SuperEnum)
+ Q_FLAG(Flags)
private slots:
void fromType();
void valuesToKeys_data();
void valuesToKeys();
+ void defaultConstructed();
};
void tst_QMetaEnum::fromType()
{
QMetaEnum meta = QMetaEnum::fromType<SuperEnum>();
QVERIFY(meta.isValid());
+ QVERIFY(!meta.isFlag());
QCOMPARE(meta.name(), "SuperEnum");
+ QCOMPARE(meta.enumName(), "SuperEnum");
+ QCOMPARE(meta.enclosingMetaObject(), &staticMetaObject);
+ QCOMPARE(meta.keyCount(), 2);
+
+ meta = QMetaEnum::fromType<Flags>();
+ QVERIFY(meta.isValid());
+ QVERIFY(meta.isFlag());
+ QCOMPARE(meta.name(), "Flags");
+ QCOMPARE(meta.enumName(), "Flag");
QCOMPARE(meta.enclosingMetaObject(), &staticMetaObject);
QCOMPARE(meta.keyCount(), 2);
}
@@ -86,6 +100,15 @@ void tst_QMetaEnum::valuesToKeys()
QCOMPARE(me.valueToKeys(windowFlags), expected);
}
+void tst_QMetaEnum::defaultConstructed()
+{
+ QMetaEnum e;
+ QVERIFY(!e.isValid());
+ QVERIFY(!e.isScoped());
+ QVERIFY(!e.isFlag());
+ QCOMPARE(e.name(), QByteArray());
+}
+
Q_STATIC_ASSERT(QtPrivate::IsQEnumHelper<tst_QMetaEnum::SuperEnum>::Value);
Q_STATIC_ASSERT(QtPrivate::IsQEnumHelper<Qt::WindowFlags>::Value);
Q_STATIC_ASSERT(QtPrivate::IsQEnumHelper<Qt::Orientation>::Value);
diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
index 431a9ebdea..9855bec520 100644
--- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
+++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
@@ -54,6 +54,11 @@ namespace MyNamespace {
MyEnum2,
MyEnum3
};
+ enum class MyScopedEnum {
+ Enum1,
+ Enum2,
+ Enum3
+ };
enum MyAnotherEnum {
MyAnotherEnum1 = 1,
MyAnotherEnum2 = 2,
@@ -64,7 +69,13 @@ namespace MyNamespace {
MyFlag2 = 0x02,
MyFlag3 = 0x04
};
+ enum class MyScopedFlag {
+ MyFlag1 = 0x10,
+ MyFlag2 = 0x20,
+ MyFlag3 = 0x40
+ };
Q_DECLARE_FLAGS(MyFlags, MyFlag)
+ Q_DECLARE_FLAGS(MyScopedFlags, MyScopedFlag)
MyEnum myEnum() const { return m_enum; }
void setMyEnum(MyEnum val) { m_enum = val; }
@@ -79,8 +90,10 @@ namespace MyNamespace {
{ }
private:
Q_ENUM(MyEnum)
+ Q_ENUM(MyScopedEnum)
Q_ENUM(MyAnotherEnum)
Q_FLAG(MyFlags)
+ Q_FLAG(MyScopedFlags)
MyEnum m_enum;
MyFlags m_flags;
@@ -1730,20 +1743,35 @@ void tst_QMetaObject::signalIndex()
void tst_QMetaObject::enumDebugStream()
{
- QTest::ignoreMessage(QtDebugMsg, "hello MyNamespace::MyClass::MyEnum(MyEnum2) world ");
- MyNamespace::MyClass::MyEnum e = MyNamespace::MyClass::MyEnum2;
- qDebug() << "hello" << e << "world";
+ QTest::ignoreMessage(QtDebugMsg, "hello MyNamespace::MyClass::MyEnum2 world ");
+ qDebug() << "hello" << MyNamespace::MyClass::MyEnum2 << "world";
+
+ QTest::ignoreMessage(QtDebugMsg, "hello MyNamespace::MyClass::MyScopedEnum::Enum3 scoped world ");
+ qDebug() << "hello" << MyNamespace::MyClass::MyScopedEnum::Enum3 << "scoped world";
- QTest::ignoreMessage(QtDebugMsg, "Qt::WindowType(WindowTitleHint) Qt::WindowType(Window) Qt::WindowType(Desktop) Qt::WindowType(WindowSystemMenuHint)");
- qDebug() << Qt::WindowTitleHint << Qt::Window <<Qt::Desktop << Qt::WindowSystemMenuHint;
+ QTest::ignoreMessage(QtDebugMsg, "Qt::WindowTitleHint Qt::Window Qt::Desktop Qt::WindowSystemMenuHint");
+ qDebug() << Qt::WindowTitleHint << Qt::Window << Qt::Desktop << Qt::WindowSystemMenuHint;
- QTest::ignoreMessage(QtDebugMsg, "hello QFlags<MyNamespace::MyClass::MyFlags>(MyFlag1) world");
+ QTest::ignoreMessage(QtDebugMsg, "hello QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) world");
MyNamespace::MyClass::MyFlags f1 = MyNamespace::MyClass::MyFlag1;
qDebug() << "hello" << f1 << "world";
MyNamespace::MyClass::MyFlags f2 = MyNamespace::MyClass::MyFlag2 | MyNamespace::MyClass::MyFlag3;
- QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyFlags>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlags>(MyFlag2|MyFlag3)");
+ QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3)");
qDebug() << f1 << f2;
+
+ QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2)");
+ MyNamespace::MyClass::MyScopedFlags f3 = MyNamespace::MyClass::MyScopedFlag::MyFlag2;
+ qDebug() << f3;
+
+ QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2|MyFlag3)");
+ f3 |= MyNamespace::MyClass::MyScopedFlag::MyFlag3;
+ qDebug() << f3;
+
+ // Single flag recognized as enum:
+ QTest::ignoreMessage(QtDebugMsg, "MyNamespace::MyClass::MyFlag1");
+ MyNamespace::MyClass::MyFlag f4 = MyNamespace::MyClass::MyFlag1;
+ qDebug() << f4;
}
void tst_QMetaObject::inherits_data()
diff --git a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
index 6bb031e357..56623773a2 100644
--- a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
+++ b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
@@ -830,6 +830,7 @@ void tst_QMetaObjectBuilder::enumerator()
// Modify the attributes on enum1.
enum1.setIsFlag(true);
enum1.setIsScoped(true);
+ enum1.setEnumName(QByteArrayLiteral("fooFlag"));
QCOMPARE(enum1.addKey("ABC", 0), 0);
QCOMPARE(enum1.addKey("DEF", 1), 1);
QCOMPARE(enum1.addKey("GHI", -1), 2);
@@ -838,6 +839,7 @@ void tst_QMetaObjectBuilder::enumerator()
QCOMPARE(enum1.name(), QByteArray("foo"));
QVERIFY(enum1.isFlag());
QVERIFY(enum1.isScoped());
+ QCOMPARE(enum1.enumName(), QByteArray("fooFlag"));
QCOMPARE(enum1.keyCount(), 3);
QCOMPARE(enum1.index(), 0);
QCOMPARE(enum1.key(0), QByteArray("ABC"));
diff --git a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro
index ad148ccc7f..d70befecfd 100644
--- a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro
+++ b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro
@@ -1,6 +1,6 @@
CONFIG += testcase
TARGET = tst_qmetatype
-QT = core testlib
+QT = core-private testlib
INCLUDEPATH += $$PWD/../../../other/qvariant_common
SOURCES = tst_qmetatype.cpp
TESTDATA=./typeFlags.bin
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index e312199980..5d9b5ca95c 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -29,6 +29,7 @@
#include <QtCore>
#include <QtTest/QtTest>
+#include <QtCore/private/qmetaobjectbuilder_p.h>
#include "tst_qmetatype.h"
#include "tst_qvariant_common.h"
@@ -38,6 +39,7 @@
#endif
#include <algorithm>
+#include <memory>
// mingw gcc 4.8 also takes way too long, letting the CI system abort the test
#if defined(__MINGW32__)
@@ -52,12 +54,19 @@ class tst_QMetaType: public QObject
Q_PROPERTY(QList<QVariant> prop READ prop WRITE setProp)
public:
+ struct GadgetPropertyType {
+ QByteArray type;
+ QByteArray name;
+ QVariant testData;
+ };
+
tst_QMetaType() { propList << 42 << "Hello"; }
QList<QVariant> prop() const { return propList; }
void setProp(const QList<QVariant> &list) { propList = list; }
private:
+ void registerGadget(const char * name, const QVector<GadgetPropertyType> &gadgetProperties);
QList<QVariant> propList;
private slots:
@@ -89,6 +98,7 @@ private slots:
void flagsBinaryCompatibility5_0();
void construct_data();
void construct();
+ void typedConstruct();
void constructCopy_data();
void constructCopy();
void typedefs();
@@ -115,6 +125,128 @@ private slots:
void customDebugStream();
};
+struct BaseGenericType
+{
+ int m_typeId = -1;
+ virtual void *constructor(int typeId, void *where, const void *copy) = 0;
+ virtual void staticMetacallFunction(QMetaObject::Call _c, int _id, void **_a) = 0;
+ virtual void saveOperator(QDataStream & out) const = 0;
+ virtual void loadOperator(QDataStream &in) = 0;
+ virtual ~BaseGenericType() {}
+};
+
+struct GenericGadgetType : BaseGenericType
+{
+ void *constructor(int typeId, void *where, const void *copy) override
+ {
+ GenericGadgetType *ret = where ? new(where) GenericGadgetType : new GenericGadgetType;
+ ret->m_typeId = typeId;
+ if (copy) {
+ Q_ASSERT(ret->m_typeId == reinterpret_cast<const GenericGadgetType*>(copy)->m_typeId);
+ *ret = *reinterpret_cast<const GenericGadgetType*>(copy);
+ } else {
+ ret->properties = properties;
+ }
+ return ret;
+ }
+
+ void staticMetacallFunction(QMetaObject::Call _c, int _id, void **_a) override
+ {
+ if (_c == QMetaObject::ReadProperty) {
+ if (_id < properties.size()) {
+ const auto &prop = properties.at(_id);
+ QMetaType::destruct(int(prop.userType()), _a[0]);
+ QMetaType::construct(int(prop.userType()), _a[0], prop.constData());
+ }
+ } else if (_c == QMetaObject::WriteProperty) {
+ if (_id < properties.size()) {
+ auto & prop = properties[_id];
+ prop = QVariant(prop.userType(), _a[0]);
+ }
+ }
+ }
+
+ void saveOperator(QDataStream & out) const override
+ {
+ for (const auto &prop : properties)
+ out << prop;
+ }
+
+ void loadOperator(QDataStream &in) override
+ {
+ for (auto &prop : properties)
+ in >> prop;
+ }
+ QVector<QVariant> properties;
+};
+
+struct GenericPODType : BaseGenericType
+{
+ // BaseGenericType interface
+ void *constructor(int typeId, void *where, const void *copy) override
+ {
+ GenericPODType *ret = where ? new(where) GenericPODType : new GenericPODType;
+ ret->m_typeId = typeId;
+ if (copy) {
+ Q_ASSERT(ret->m_typeId == reinterpret_cast<const GenericPODType*>(copy)->m_typeId);
+ *ret = *reinterpret_cast<const GenericPODType*>(copy);
+ } else {
+ ret->podData = podData;
+ }
+ return ret;
+ }
+
+ void staticMetacallFunction(QMetaObject::Call _c, int _id, void **_a) override
+ {
+ Q_UNUSED(_c);
+ Q_UNUSED(_id);
+ Q_UNUSED(_a);
+ Q_ASSERT(false);
+ }
+
+ void saveOperator(QDataStream &out) const override
+ {
+ out << podData;
+ }
+ void loadOperator(QDataStream &in) override
+ {
+ in >> podData;
+ }
+ QByteArray podData;
+};
+
+using RegisteredType = QPair<std::shared_ptr<BaseGenericType>, std::shared_ptr<QMetaObject>>;
+static QHash<int, RegisteredType> s_managedTypes;
+
+static void GadgetsStaticMetacallFunction(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
+{
+ reinterpret_cast<BaseGenericType*>(_o)->staticMetacallFunction(_c, _id, _a);
+}
+
+static void GadgetTypedDestructor(int typeId, void *ptr)
+{
+ QCOMPARE(typeId, reinterpret_cast<BaseGenericType*>(ptr)->m_typeId);
+ reinterpret_cast<BaseGenericType*>(ptr)->~BaseGenericType();
+}
+
+static void *GadgetTypedConstructor(int type, void *where, const void *copy)
+{
+ auto it = s_managedTypes.find(type);
+ if (it == s_managedTypes.end())
+ return nullptr; // crash the test
+ return it->first->constructor(type, where, copy);
+}
+
+static void GadgetSaveOperator(QDataStream & out, const void *data)
+{
+ reinterpret_cast<const BaseGenericType *>(data)->saveOperator(out);
+}
+
+static void GadgetLoadOperator(QDataStream &in, void *data)
+{
+ reinterpret_cast<BaseGenericType *>(data)->loadOperator(in);
+}
+
struct Foo { int i; };
@@ -149,6 +281,34 @@ class GadgetDerivedAndTyped : public CustomGadget {};
Q_DECLARE_METATYPE(GadgetDerivedAndTyped<int>)
Q_DECLARE_METATYPE(GadgetDerivedAndTyped<int>*)
+void tst_QMetaType::registerGadget(const char *name, const QVector<GadgetPropertyType> &gadgetProperties)
+{
+ QMetaObjectBuilder gadgetBuilder;
+ gadgetBuilder.setClassName(name);
+ QMetaObjectBuilder::MetaObjectFlags metaObjectflags = QMetaObjectBuilder::DynamicMetaObject | QMetaObjectBuilder::PropertyAccessInStaticMetaCall;
+ gadgetBuilder.setFlags(metaObjectflags);
+ auto dynamicGadgetProperties = std::make_shared<GenericGadgetType>();
+ for (const auto &prop : gadgetProperties) {
+ int propertyType = QMetaType::type(prop.type);
+ dynamicGadgetProperties->properties.push_back(QVariant(QVariant::Type(propertyType)));
+ auto dynamicPropery = gadgetBuilder.addProperty(prop.name, prop.type);
+ dynamicPropery.setWritable(true);
+ dynamicPropery.setReadable(true);
+ }
+ auto meta = gadgetBuilder.toMetaObject();
+ meta->d.static_metacall = &GadgetsStaticMetacallFunction;
+ meta->d.superdata = nullptr;
+ const auto flags = QMetaType::WasDeclaredAsMetaType | QMetaType::IsGadget | QMetaType::NeedsConstruction | QMetaType::NeedsDestruction;
+ int gadgetTypeId = QMetaType::registerType(name,
+ &GadgetTypedDestructor,
+ &GadgetTypedConstructor,
+ sizeof(GenericGadgetType),
+ flags, meta);
+ QVERIFY(gadgetTypeId > 0);
+ QMetaType::registerStreamOperators(gadgetTypeId, &GadgetSaveOperator, &GadgetLoadOperator);
+ s_managedTypes[gadgetTypeId] = qMakePair(dynamicGadgetProperties, std::shared_ptr<QMetaObject>{meta, [](QMetaObject *ptr){ ::free(ptr); }});
+}
+
void tst_QMetaType::defined()
{
QCOMPARE(int(QMetaTypeId2<QString>::Defined), 1);
@@ -906,6 +1066,90 @@ FOR_EACH_CORE_METATYPE(RETURN_CONSTRUCT_FUNCTION)
TypeTestFunctionGetter::get(type)();
}
+void tst_QMetaType::typedConstruct()
+{
+ auto testMetaObjectWriteOnGadget = [](QVariant &gadget, const QVector<GadgetPropertyType> &properties)
+ {
+ auto metaObject = QMetaType::metaObjectForType(gadget.userType());
+ QVERIFY(metaObject != nullptr);
+ QCOMPARE(metaObject->methodCount(), 0);
+ QCOMPARE(metaObject->propertyCount(), properties.size());
+ for (int i = 0; i < metaObject->propertyCount(); ++i) {
+ auto prop = metaObject->property(i);
+ QCOMPARE(properties[i].name, prop.name());
+ QCOMPARE(properties[i].type, prop.typeName());
+ prop.writeOnGadget(gadget.data(), properties[i].testData);
+ }
+ };
+
+ auto testMetaObjectReadOnGadget = [](QVariant gadget, const QVector<GadgetPropertyType> &properties)
+ {
+ auto metaObject = QMetaType::metaObjectForType(gadget.userType());
+ QVERIFY(metaObject != nullptr);
+ QCOMPARE(metaObject->methodCount(), 0);
+ QCOMPARE(metaObject->propertyCount(), properties.size());
+ for (int i = 0; i < metaObject->propertyCount(); ++i) {
+ auto prop = metaObject->property(i);
+ QCOMPARE(properties[i].name, prop.name());
+ QCOMPARE(properties[i].type, prop.typeName());
+ if (!QMetaType::typeFlags(prop.userType()).testFlag(QMetaType::IsGadget))
+ QCOMPARE(properties[i].testData, prop.readOnGadget(gadget.constData()));
+ }
+ };
+
+ QVector<GadgetPropertyType> dynamicGadget1 = {
+ {"int", "int_prop", 34526},
+ {"float", "float_prop", 1.23f},
+ {"QString", "string_prop", QString{"Test QString"}}
+ };
+ registerGadget("DynamicGadget1", dynamicGadget1);
+
+ QVariant testGadget1(QVariant::Type(QMetaType::type("DynamicGadget1")));
+ testMetaObjectWriteOnGadget(testGadget1, dynamicGadget1);
+ testMetaObjectReadOnGadget(testGadget1, dynamicGadget1);
+
+
+ QVector<GadgetPropertyType> dynamicGadget2 = {
+ {"int", "int_prop", 512},
+ {"double", "double_prop", 4.56},
+ {"QString", "string_prop", QString{"Another String"}},
+ {"DynamicGadget1", "dynamicGadget1_prop", testGadget1}
+ };
+ registerGadget("DynamicGadget2", dynamicGadget2);
+ QVariant testGadget2(QVariant::Type(QMetaType::type("DynamicGadget2")));
+ testMetaObjectWriteOnGadget(testGadget2, dynamicGadget2);
+ testMetaObjectReadOnGadget(testGadget2, dynamicGadget2);
+ auto g2mo = QMetaType::metaObjectForType(testGadget2.userType());
+ auto dynamicGadget1_prop = g2mo->property(g2mo->indexOfProperty("dynamicGadget1_prop"));
+ testMetaObjectReadOnGadget(dynamicGadget1_prop.readOnGadget(testGadget2.constData()), dynamicGadget1);
+
+
+ // Register POD
+ const QByteArray myPodTesData = "My POD test data";
+ const char podTypeName[] = "DynamicPOD";
+ auto dynamicGadgetProperties = std::make_shared<GenericPODType>();
+ dynamicGadgetProperties->podData = myPodTesData;
+ const auto flags = QMetaType::NeedsConstruction | QMetaType::NeedsDestruction;
+ int podTypeId = QMetaType::registerType(podTypeName,
+ &GadgetTypedDestructor,
+ &GadgetTypedConstructor,
+ sizeof(GenericGadgetType),
+ flags, nullptr);
+ QVERIFY(podTypeId > 0);
+ QMetaType::registerStreamOperators(podTypeId, &GadgetSaveOperator, &GadgetLoadOperator);
+ s_managedTypes[podTypeId] = qMakePair(dynamicGadgetProperties, std::shared_ptr<QMetaObject>{});
+
+ // Test POD
+ QCOMPARE(podTypeId, QMetaType::type(podTypeName));
+ QVariant podVariant{QVariant::Type(podTypeId)};
+ QCOMPARE(myPodTesData, static_cast<const GenericPODType *>(reinterpret_cast<const BaseGenericType *>(podVariant.constData()))->podData);
+
+ QVariant podVariant1{podVariant};
+ podVariant1.detach(); // Test stream operators
+ static_cast<GenericPODType *>(reinterpret_cast<BaseGenericType *>(podVariant.data()))->podData.clear();
+ QCOMPARE(myPodTesData, static_cast<const GenericPODType *>(reinterpret_cast<const BaseGenericType *>(podVariant1.constData()))->podData);
+}
+
template<int ID>
static void testConstructCopyHelper()
{
@@ -1574,6 +1818,9 @@ DECLARE_NONSTREAMABLE(QJsonValue)
DECLARE_NONSTREAMABLE(QJsonObject)
DECLARE_NONSTREAMABLE(QJsonArray)
DECLARE_NONSTREAMABLE(QJsonDocument)
+DECLARE_NONSTREAMABLE(QCborValue)
+DECLARE_NONSTREAMABLE(QCborArray)
+DECLARE_NONSTREAMABLE(QCborMap)
DECLARE_NONSTREAMABLE(QObject*)
DECLARE_NONSTREAMABLE(QWidget*)
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
index 93ff33bb67..6bda9638f7 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
@@ -273,6 +273,24 @@ template<> struct TestValueFactory<QMetaType::QJsonDocument> {
);
}
};
+
+template<> struct TestValueFactory<QMetaType::QCborSimpleType> {
+ static QCborSimpleType *create() { return new QCborSimpleType(QCborSimpleType::True); }
+};
+template<> struct TestValueFactory<QMetaType::QCborValue> {
+ static QCborValue *create() { return new QCborValue(123.); }
+};
+template<> struct TestValueFactory<QMetaType::QCborMap> {
+ static QCborMap *create() {
+ return new QCborMap{{0, 0}, {"Hello", 1}, {1, nullptr}};
+ }
+};
+template<> struct TestValueFactory<QMetaType::QCborArray> {
+ static QCborArray *create() {
+ return new QCborArray{0, 1, -2, 2.5, false, nullptr, "Hello", QByteArray("World") };
+ }
+};
+
template<> struct TestValueFactory<QMetaType::QVariant> {
static QVariant *create() { return new QVariant(QStringList(QStringList() << "Q" << "t")); }
};
diff --git a/tests/auto/corelib/kernel/qobject/.gitignore b/tests/auto/corelib/kernel/qobject/.gitignore
index 7970e32c8f..d609065333 100644
--- a/tests/auto/corelib/kernel/qobject/.gitignore
+++ b/tests/auto/corelib/kernel/qobject/.gitignore
@@ -1,3 +1,7 @@
tst_qobject
-signalbug/signalbug
-signalbug/signalbug.exe
+signalbug_helper
+signalbug_helper.exe
+debug/signalbug_helper
+release/signalbug_helper
+debug/signalbug_helper.exe
+release/signalbug_helper.exe
diff --git a/tests/auto/corelib/kernel/qobject/qobject.pro b/tests/auto/corelib/kernel/qobject/qobject.pro
index 978aab86c1..75ad7b5f14 100644
--- a/tests/auto/corelib/kernel/qobject/qobject.pro
+++ b/tests/auto/corelib/kernel/qobject/qobject.pro
@@ -1,8 +1,4 @@
TEMPLATE = subdirs
-!winrt {
- test.depends = signalbug
- SUBDIRS += signalbug
-}
-
-SUBDIRS += test
+SUBDIRS += test.pro
+!winrt: SUBDIRS += signalbug
diff --git a/tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro b/tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro
index cc51b4c661..d21b3a62a9 100644
--- a/tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro
+++ b/tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro
@@ -1,11 +1,6 @@
-CONFIG -= app_bundle debug_and_release
-CONFIG += console
-DESTDIR = ./
QT = core
HEADERS += signalbug.h
SOURCES += signalbug.cpp
-# This app is testdata for tst_qobject
-target.path = $$[QT_INSTALL_TESTS]/tst_qobject/$$TARGET
-INSTALLS += target
+load(qt_test_helper)
diff --git a/tests/auto/corelib/kernel/qobject/test/test.pro b/tests/auto/corelib/kernel/qobject/test.pro
index 4e77cb48c5..af5203e152 100644
--- a/tests/auto/corelib/kernel/qobject/test/test.pro
+++ b/tests/auto/corelib/kernel/qobject/test.pro
@@ -1,10 +1,10 @@
CONFIG += testcase console
-TARGET = ../tst_qobject
+
QT = core-private network testlib
-SOURCES = ../tst_qobject.cpp
+TARGET = tst_qobject
+SOURCES = tst_qobject.cpp
# Force C++17 if available (needed due to P0012R1)
contains(QT_CONFIG, c++1z): CONFIG += c++1z
-!winrt: TEST_HELPER_INSTALLS = ../signalbug/signalbug
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index ec57522f48..effc82261b 100644
--- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -55,7 +55,6 @@ class tst_QObject : public QObject
{
Q_OBJECT
private slots:
- void initTestCase();
void disconnect();
void connectSlotsByName();
void connectSignalsToSignalsWithDefaultArguments();
@@ -104,6 +103,7 @@ private slots:
void deleteQObjectWhenDeletingEvent();
void overloads();
void isSignalConnected();
+ void isSignalConnectedAfterDisconnection();
void qMetaObjectConnect();
void qMetaObjectDisconnectOne();
void sameName();
@@ -145,6 +145,7 @@ private slots:
void disconnectDoesNotLeakFunctor();
void contextDoesNotLeakFunctor();
void connectBase();
+ void connectWarnings();
void qmlConnect();
void exceptions();
void noDeclarativeParentChangedOnDestruction();
@@ -282,14 +283,6 @@ static void playWithObjects()
}
}
-void tst_QObject::initTestCase()
-{
-#if QT_CONFIG(process)
- const QString testDataDir = QFileInfo(QFINDTESTDATA("signalbug")).absolutePath();
- QVERIFY2(QDir::setCurrent(testDataDir), qPrintable("Could not chdir to " + testDataDir));
-#endif
-}
-
void tst_QObject::disconnect()
{
SenderObject *s = new SenderObject;
@@ -3026,7 +3019,7 @@ void tst_QObject::recursiveSignalEmission()
#else
QProcess proc;
// signalbug helper app should always be next to this test binary
- const QString path = QStringLiteral("signalbug/signalbug");
+ const QString path = QStringLiteral("signalbug_helper");
proc.start(path);
QVERIFY2(proc.waitForStarted(), qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, proc.errorString())));
QVERIFY(proc.waitForFinished());
@@ -3843,6 +3836,58 @@ void tst_QObject::isSignalConnected()
QVERIFY(!o.isSignalConnected(QMetaMethod()));
}
+void tst_QObject::isSignalConnectedAfterDisconnection()
+{
+ ManySignals o;
+ const QMetaObject *meta = o.metaObject();
+
+ const QMetaMethod sig00 = meta->method(meta->indexOfSignal("sig00()"));
+ QVERIFY(!o.isSignalConnected(sig00));
+ QObject::connect(&o, &ManySignals::sig00, qt_noop);
+ QVERIFY(o.isSignalConnected(sig00));
+ QVERIFY(QObject::disconnect(&o, &ManySignals::sig00, 0, 0));
+ QVERIFY(!o.isSignalConnected(sig00));
+
+ const QMetaMethod sig69 = meta->method(meta->indexOfSignal("sig69()"));
+ QVERIFY(!o.isSignalConnected(sig69));
+ QObject::connect(&o, &ManySignals::sig69, qt_noop);
+ QVERIFY(o.isSignalConnected(sig69));
+ QVERIFY(QObject::disconnect(&o, &ManySignals::sig69, 0, 0));
+ QVERIFY(!o.isSignalConnected(sig69));
+
+ {
+ ManySignals o2;
+ QObject::connect(&o, &ManySignals::sig00, &o2, &ManySignals::sig00);
+ QVERIFY(o.isSignalConnected(sig00));
+ // o2 is destructed
+ }
+ QVERIFY(!o.isSignalConnected(sig00));
+
+ const QMetaMethod sig01 = meta->method(meta->indexOfSignal("sig01()"));
+ QObject::connect(&o, &ManySignals::sig00, qt_noop);
+ QObject::connect(&o, &ManySignals::sig01, qt_noop);
+ QObject::connect(&o, &ManySignals::sig69, qt_noop);
+ QVERIFY(o.isSignalConnected(sig00));
+ QVERIFY(o.isSignalConnected(sig01));
+ QVERIFY(o.isSignalConnected(sig69));
+ QVERIFY(QObject::disconnect(&o, &ManySignals::sig69, 0, 0));
+ QVERIFY(o.isSignalConnected(sig00));
+ QVERIFY(o.isSignalConnected(sig01));
+ QVERIFY(!o.isSignalConnected(sig69));
+ QVERIFY(QObject::disconnect(&o, &ManySignals::sig00, 0, 0));
+ QVERIFY(!o.isSignalConnected(sig00));
+ QVERIFY(o.isSignalConnected(sig01));
+ QVERIFY(!o.isSignalConnected(sig69));
+ QObject::connect(&o, &ManySignals::sig69, qt_noop);
+ QVERIFY(!o.isSignalConnected(sig00));
+ QVERIFY(o.isSignalConnected(sig01));
+ QVERIFY(o.isSignalConnected(sig69));
+ QVERIFY(QObject::disconnect(&o, &ManySignals::sig01, 0, 0));
+ QVERIFY(!o.isSignalConnected(sig00));
+ QVERIFY(!o.isSignalConnected(sig01));
+ QVERIFY(o.isSignalConnected(sig69));
+}
+
void tst_QObject::qMetaObjectConnect()
{
SenderObject *s = new SenderObject;
@@ -6697,6 +6742,26 @@ void tst_QObject::connectBase()
QCOMPARE( r1.count_slot3, 1 );
}
+void tst_QObject::connectWarnings()
+{
+ SubSender sub;
+ SenderObject obj;
+ ReceiverObject r1;
+ r1.reset();
+
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SenderObject, ReceiverObject): invalid null parameter");
+ connect(nullptr, &SubSender::signal1, &r1, &ReceiverObject::slot1);
+
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SubSender, Unknown): invalid null parameter");
+ connect(&sub, &SubSender::signal1, nullptr, &ReceiverObject::slot1);
+
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SenderObject, ReceiverObject): invalid null parameter");
+ connect(nullptr, &SenderObject::signal1, &r1, &ReceiverObject::slot1);
+
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SenderObject, Unknown): invalid null parameter");
+ connect(&obj, &SenderObject::signal1, nullptr, &ReceiverObject::slot1);
+}
+
struct QmlReceiver : public QtPrivate::QSlotObjectBase
{
int callCount;
diff --git a/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/main.cpp b/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/main.cpp
index ffbad37d82..ffbad37d82 100644
--- a/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/main.cpp
+++ b/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/main.cpp
diff --git a/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/producerconsumer.pro b/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/producerconsumer.pro
new file mode 100644
index 0000000000..a6156ed5b6
--- /dev/null
+++ b/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/producerconsumer.pro
@@ -0,0 +1,5 @@
+QT = core testlib
+
+SOURCES += main.cpp
+
+load(qt_test_helper)
diff --git a/tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro b/tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro
index 3a4697750e..323d5bbd37 100644
--- a/tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro
+++ b/tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro
@@ -1,6 +1,6 @@
TEMPLATE = subdirs
qtConfig(sharedmemory) {
- !winrt: SUBDIRS = sharedmemoryhelper
- SUBDIRS += test
+ !winrt: SUBDIRS = producerconsumer
+ SUBDIRS += test.pro
}
diff --git a/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/sharedmemoryhelper.pro b/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/sharedmemoryhelper.pro
deleted file mode 100644
index 389015d504..0000000000
--- a/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/sharedmemoryhelper.pro
+++ /dev/null
@@ -1,17 +0,0 @@
-QT = core testlib
-
-win32: CONFIG += console
-mac:CONFIG -= app_bundle
-
-SOURCES += main.cpp
-TARGET = helperbinary
-
-CONFIG(debug_and_release) {
- CONFIG(debug, debug|release) {
- DESTDIR = ../debug
- } else {
- DESTDIR = ../release
- }
-} else {
- DESTDIR = ..
-}
diff --git a/tests/auto/corelib/kernel/qsharedmemory/test.pro b/tests/auto/corelib/kernel/qsharedmemory/test.pro
new file mode 100644
index 0000000000..8b3badadb0
--- /dev/null
+++ b/tests/auto/corelib/kernel/qsharedmemory/test.pro
@@ -0,0 +1,8 @@
+CONFIG += testcase
+
+QT = core-private testlib
+
+TARGET = tst_qsharedmemory
+SOURCES += tst_qsharedmemory.cpp
+
+linux: LIBS += -lrt
diff --git a/tests/auto/corelib/kernel/qsharedmemory/test/test.pro b/tests/auto/corelib/kernel/qsharedmemory/test/test.pro
deleted file mode 100644
index 61124c27ee..0000000000
--- a/tests/auto/corelib/kernel/qsharedmemory/test/test.pro
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG += testcase
-
-QT = core-private testlib
-
-linux:LIBS += -lrt
-
-SOURCES += tst_qsharedmemory.cpp
-TARGET = tst_qsharedmemory
-
-CONFIG(debug_and_release) {
- CONFIG(debug, debug|release) {
- DESTDIR = ../debug
- } else {
- DESTDIR = ../release
- }
-} else {
- DESTDIR = ..
-}
diff --git a/tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp b/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp
index f81324b894..55deb8eb1a 100644
--- a/tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp
+++ b/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp
@@ -51,7 +51,6 @@ public:
public Q_SLOTS:
void init();
- void initTestCase();
void cleanup();
@@ -101,7 +100,6 @@ private slots:
void uniqueKey();
protected:
- static QString helperBinary();
int remove(const QString &key);
QString rememberKey(const QString &key)
@@ -125,7 +123,7 @@ private:
tst_QSharedMemory::tst_QSharedMemory()
: existingSharedMemory(0)
- , m_helperBinary(tst_QSharedMemory::helperBinary())
+ , m_helperBinary("producerconsumer_helper")
{
}
@@ -133,13 +131,6 @@ tst_QSharedMemory::~tst_QSharedMemory()
{
}
-void tst_QSharedMemory::initTestCase()
-{
-#if QT_CONFIG(process)
- QVERIFY2(!m_helperBinary.isEmpty(), "Could not find helper binary");
-#endif
-}
-
void tst_QSharedMemory::init()
{
existingSharedMemory = new QSharedMemory(EXISTING_SHARE);
@@ -179,15 +170,6 @@ void tst_QSharedMemory::cleanup()
#include <errno.h>
#endif
-QString tst_QSharedMemory::helperBinary()
-{
- QString binary = QStringLiteral("helperbinary");
-#ifdef Q_OS_WIN
- binary += QStringLiteral(".exe");
-#endif
- return QFINDTESTDATA(binary);
-}
-
int tst_QSharedMemory::remove(const QString &key)
{
#ifdef Q_OS_WIN
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/acquirerelease.pro b/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/acquirerelease.pro
new file mode 100644
index 0000000000..a6156ed5b6
--- /dev/null
+++ b/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/acquirerelease.pro
@@ -0,0 +1,5 @@
+QT = core testlib
+
+SOURCES += main.cpp
+
+load(qt_test_helper)
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/main.cpp b/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/main.cpp
index 7bfb6b16cc..7bfb6b16cc 100644
--- a/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/main.cpp
+++ b/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/main.cpp
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro b/tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro
index f8a49254d2..70526426aa 100644
--- a/tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro
+++ b/tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro
@@ -1,3 +1,3 @@
TEMPLATE = subdirs
-SUBDIRS = systemsemaphorehelper test
+SUBDIRS = acquirerelease test.pro
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/systemsemaphorehelper.pro b/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/systemsemaphorehelper.pro
deleted file mode 100644
index 389015d504..0000000000
--- a/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/systemsemaphorehelper.pro
+++ /dev/null
@@ -1,17 +0,0 @@
-QT = core testlib
-
-win32: CONFIG += console
-mac:CONFIG -= app_bundle
-
-SOURCES += main.cpp
-TARGET = helperbinary
-
-CONFIG(debug_and_release) {
- CONFIG(debug, debug|release) {
- DESTDIR = ../debug
- } else {
- DESTDIR = ../release
- }
-} else {
- DESTDIR = ..
-}
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/test.pro b/tests/auto/corelib/kernel/qsystemsemaphore/test.pro
new file mode 100644
index 0000000000..13bd1fa270
--- /dev/null
+++ b/tests/auto/corelib/kernel/qsystemsemaphore/test.pro
@@ -0,0 +1,7 @@
+CONFIG += testcase
+QT = core testlib
+
+SOURCES += tst_qsystemsemaphore.cpp
+TARGET = tst_qsystemsemaphore
+
+win32: CONFIG += console
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/test/test.pro b/tests/auto/corelib/kernel/qsystemsemaphore/test/test.pro
deleted file mode 100644
index f60207eb01..0000000000
--- a/tests/auto/corelib/kernel/qsystemsemaphore/test/test.pro
+++ /dev/null
@@ -1,17 +0,0 @@
-CONFIG += testcase
-QT = core testlib
-
-win32: CONFIG += console
-
-SOURCES += tst_qsystemsemaphore.cpp
-TARGET = tst_qsystemsemaphore
-
-CONFIG(debug_and_release) {
- CONFIG(debug, debug|release) {
- DESTDIR = ../debug
- } else {
- DESTDIR = ../release
- }
-} else {
- DESTDIR = ..
-}
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp b/tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp
index 6ff1e14976..5f010ae3d1 100644
--- a/tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp
+++ b/tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp
@@ -42,7 +42,6 @@ public:
tst_QSystemSemaphore();
public Q_SLOTS:
- void initTestCase();
void init();
void cleanup();
@@ -65,22 +64,16 @@ private slots:
void initialValue();
private:
- static QString helperBinary();
QSystemSemaphore *existingLock;
const QString m_helperBinary;
};
tst_QSystemSemaphore::tst_QSystemSemaphore()
- : m_helperBinary(helperBinary())
+ : m_helperBinary("acquirerelease_helper")
{
}
-void tst_QSystemSemaphore::initTestCase()
-{
- QVERIFY2(!m_helperBinary.isEmpty(), "Could not find helper binary");
-}
-
void tst_QSystemSemaphore::init()
{
existingLock = new QSystemSemaphore(EXISTING_SHARE, 1, QSystemSemaphore::Create);
@@ -294,14 +287,6 @@ void tst_QSystemSemaphore::initialValue()
#endif
}
-QString tst_QSystemSemaphore::helperBinary()
-{
- QString binary = QStringLiteral("helperbinary");
-#ifdef Q_OS_WIN
- binary += QStringLiteral(".exe");
-#endif
- return QFINDTESTDATA(binary);
-}
QTEST_MAIN(tst_QSystemSemaphore)
#include "tst_qsystemsemaphore.moc"
diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
index 5b2d77a02c..8d194dafc1 100644
--- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
+++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
@@ -75,6 +75,7 @@ private slots:
void dontBlockEvents();
void postedEventsShouldNotStarveTimers();
+ void callOnTimeout();
};
void tst_QTimer::zeroTimer()
@@ -455,8 +456,7 @@ void tst_QTimer::moveToThread()
#if defined(Q_OS_WIN32)
QSKIP("Does not work reliably on Windows :(");
#elif defined(Q_OS_MACOS)
- if (__builtin_available(macOS 10.12, *))
- QSKIP("Does not work reliably on macOS 10.12 (QTBUG-59679)");
+ QSKIP("Does not work reliably on macOS 10.12+ (QTBUG-59679)");
#endif
QTimer ti1;
QTimer ti2;
@@ -979,5 +979,30 @@ void tst_QTimer::crossThreadSingleShotToFunctor()
delete o;
}
+void tst_QTimer::callOnTimeout()
+{
+ QTimer timer;
+ QSignalSpy timeoutSpy(&timer, &QTimer::timeout);
+ timer.setInterval(0);
+ timer.start();
+
+ auto context = new QObject();
+
+ int count = 0;
+ timer.callOnTimeout([&count] { count++; });
+ QMetaObject::Connection connection = timer.callOnTimeout(context, [&count] { count++; });
+ timer.callOnTimeout(&timer, &QTimer::stop);
+
+
+ QTest::qWait(100);
+ QCOMPARE(count, 2);
+ QCOMPARE(timeoutSpy.count(), 1);
+
+ // Test that connection is bound to context lifetime
+ QVERIFY(connection);
+ delete context;
+ QVERIFY(!connection);
+}
+
QTEST_MAIN(tst_QTimer)
#include "tst_qtimer.moc"
diff --git a/tests/auto/corelib/kernel/qtranslator/android_testdata.qrc b/tests/auto/corelib/kernel/qtranslator/android_testdata.qrc
index b33995ef21..39b85db664 100644
--- a/tests/auto/corelib/kernel/qtranslator/android_testdata.qrc
+++ b/tests/auto/corelib/kernel/qtranslator/android_testdata.qrc
@@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/android_testdata">
<file>hellotr_la.qm</file>
+ <file>hellotr_empty.qm</file>
<file>msgfmt_from_po.qm</file>
<file>dependencies_la.qm</file>
</qresource>
diff --git a/tests/auto/corelib/kernel/qtranslator/hellotr_empty.qm b/tests/auto/corelib/kernel/qtranslator/hellotr_empty.qm
new file mode 100644
index 0000000000..be651eede2
--- /dev/null
+++ b/tests/auto/corelib/kernel/qtranslator/hellotr_empty.qm
@@ -0,0 +1 @@
+<d!` \ No newline at end of file
diff --git a/tests/auto/corelib/kernel/qtranslator/hellotr_empty.ts b/tests/auto/corelib/kernel/qtranslator/hellotr_empty.ts
new file mode 100644
index 0000000000..85e0d3992b
--- /dev/null
+++ b/tests/auto/corelib/kernel/qtranslator/hellotr_empty.ts
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1"/>
diff --git a/tests/auto/corelib/kernel/qtranslator/qtranslator.pro b/tests/auto/corelib/kernel/qtranslator/qtranslator.pro
index d8924c2d5f..a985f35a14 100644
--- a/tests/auto/corelib/kernel/qtranslator/qtranslator.pro
+++ b/tests/auto/corelib/kernel/qtranslator/qtranslator.pro
@@ -5,5 +5,5 @@ SOURCES = tst_qtranslator.cpp
RESOURCES += qtranslator.qrc
android:!android-embedded: RESOURCES += android_testdata.qrc
-else: TESTDATA += dependencies_la.qm hellotr_la.qm msgfmt_from_po.qm
+else: TESTDATA += dependencies_la.qm hellotr_empty.qm hellotr_la.qm msgfmt_from_po.qm
diff --git a/tests/auto/corelib/kernel/qtranslator/qtranslator.qrc b/tests/auto/corelib/kernel/qtranslator/qtranslator.qrc
index 333dcfaa21..cb82c6cc95 100644
--- a/tests/auto/corelib/kernel/qtranslator/qtranslator.qrc
+++ b/tests/auto/corelib/kernel/qtranslator/qtranslator.qrc
@@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/tst_qtranslator">
<file>hellotr_la.qm</file>
+ <file>hellotr_empty.qm</file>
</qresource>
</RCC>
diff --git a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
index 451f96339e..40a29c723c 100644
--- a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
+++ b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
@@ -41,13 +41,12 @@ protected:
private slots:
void initTestCase();
+ void load_data();
void load();
- void load2();
void threadLoad();
void testLanguageChange();
void plural();
void translate_qm_file_generated_with_msgfmt();
- void loadFromResource();
void loadDirectory();
void dependencies();
void translationInThreadWhileInstallingTranslator();
@@ -106,24 +105,45 @@ bool tst_QTranslator::eventFilter(QObject *, QEvent *event)
return false;
}
-void tst_QTranslator::load()
+void tst_QTranslator::load_data()
{
+ QTest::addColumn<QString>("filepath");
+ QTest::addColumn<bool>("isEmpty");
+ QTest::addColumn<QString>("translation");
- QTranslator tor( 0 );
- tor.load("hellotr_la");
- QVERIFY(!tor.isEmpty());
- QCOMPARE(tor.translate("QPushButton", "Hello world!"), QLatin1String("Hallo Welt!"));
+ QTest::newRow("hellotr_la") << "hellotr_la.qm" << false << "Hallo Welt!";
+ QTest::newRow("hellotr_empty") << "hellotr_empty.qm" << true << "";
}
-void tst_QTranslator::load2()
+void tst_QTranslator::load()
{
- QTranslator tor( 0 );
- QFile file("hellotr_la.qm");
- file.open(QFile::ReadOnly);
- QByteArray data = file.readAll();
- tor.load((const uchar *)data.constData(), data.length());
- QVERIFY(!tor.isEmpty());
- QCOMPARE(tor.translate("QPushButton", "Hello world!"), QLatin1String("Hallo Welt!"));
+ QFETCH(QString, filepath);
+ QFETCH(bool, isEmpty);
+ QFETCH(QString, translation);
+
+ {
+ QTranslator tor;
+ QVERIFY(tor.load(QFileInfo(filepath).baseName()));
+ QCOMPARE(tor.isEmpty(), isEmpty);
+ QCOMPARE(tor.translate("QPushButton", "Hello world!"), translation);
+ }
+
+ {
+ QFile file(filepath);
+ file.open(QFile::ReadOnly);
+ QByteArray data = file.readAll();
+ QTranslator tor;
+ QVERIFY(tor.load((const uchar *)data.constData(), data.length()));
+ QCOMPARE(tor.isEmpty(), isEmpty);
+ QCOMPARE(tor.translate("QPushButton", "Hello world!"), translation);
+ }
+
+ {
+ QTranslator tor;
+ QVERIFY(tor.load(QString(":/tst_qtranslator/%1").arg(filepath)));
+ QCOMPARE(tor.isEmpty(), isEmpty);
+ QCOMPARE(tor.translate("QPushButton", "Hello world!"), translation);
+ }
}
class TranslatorThread : public QThread
@@ -240,14 +260,6 @@ void tst_QTranslator::translate_qm_file_generated_with_msgfmt()
qApp->removeTranslator(&translator);
}
-void tst_QTranslator::loadFromResource()
-{
- QTranslator tor;
- tor.load(":/tst_qtranslator/hellotr_la.qm");
- QVERIFY(!tor.isEmpty());
- QCOMPARE(tor.translate("QPushButton", "Hello world!"), QLatin1String("Hallo Welt!"));
-}
-
void tst_QTranslator::loadDirectory()
{
QString current_base = QDir::current().dirName();
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index 0780fb9172..4da34c407e 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -525,6 +525,12 @@ void tst_QVariant::canConvert_data()
var = QVariant::fromValue<signed char>(-1);
QTest::newRow("SChar")
<< var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << N << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
+ var = QVariant((short)-3);
+ QTest::newRow("Short")
+ << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << Y << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
+ var = QVariant((ushort)7);
+ QTest::newRow("UShort")
+ << var << N << N << Y << N << Y << N << N << N << N << Y << N << N << Y << N << Y << N << Y << N << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
var = QVariant::fromValue<QJsonValue>(QJsonValue(QStringLiteral("hello")));
QTest::newRow("JsonValue")
<< var << N << N << Y << N << N << N << N << N << N << Y << N << N << Y << N << N << Y << Y << Y << N << N << N << N << N << N << N << N << Y << N << N << Y << Y;
@@ -563,6 +569,8 @@ void tst_QVariant::toInt_data()
QTest::newRow( "char" ) << QVariant::fromValue('a') << int('a') << true;
signed char signedChar = -13;
QTest::newRow( "signed char" ) << QVariant::fromValue(signedChar) << -13 << true;
+ QTest::newRow( "short" ) << QVariant::fromValue(short(-7)) << int(-7) << true;
+ QTest::newRow( "ushort" ) << QVariant::fromValue(ushort(30000)) << 30000 << true;
QTest::newRow( "double" ) << QVariant( 3.1415927 ) << 3 << true;
QTest::newRow( "float" ) << QVariant( 3.1415927f ) << 3 << true;
QTest::newRow( "uint" ) << QVariant( 123u ) << 123 << true;
diff --git a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp
index e2a0c2dad3..ac8aaa1327 100644
--- a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp
+++ b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp
@@ -46,6 +46,7 @@ protected slots:
private slots:
void simple_data();
void simple();
+ void blockedWaiting();
void manyNotifiers();
void disableNotifiersInActivatedSlot_data();
void disableNotifiersInActivatedSlot();
@@ -104,6 +105,26 @@ void tst_QWinEventNotifier::simple()
QVERIFY(simpleActivated);
}
+void tst_QWinEventNotifier::blockedWaiting()
+{
+ simpleHEvent = CreateEvent(0, true, false, 0);
+ QWinEventNotifier n(simpleHEvent);
+ QObject::connect(&n, &QWinEventNotifier::activated,
+ this, &tst_QWinEventNotifier::simple_activated);
+ simpleActivated = false;
+
+ SetEvent(simpleHEvent);
+ QCOMPARE(WaitForSingleObject(simpleHEvent, 1000), WAIT_OBJECT_0);
+
+ n.setEnabled(false);
+ ResetEvent(simpleHEvent);
+ n.setEnabled(true);
+
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(QTestEventLoop::instance().timeout());
+ QVERIFY(!simpleActivated);
+}
+
class EventWithNotifier : public QObject
{
Q_OBJECT
diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.foo b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.foo
new file mode 100644
index 0000000000..ed5e761417
--- /dev/null
+++ b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.foo
@@ -0,0 +1,3 @@
+<?foo>
+<blah>
+</blah>
diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.xml b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.xml
new file mode 100644
index 0000000000..27b5bd7e1f
--- /dev/null
+++ b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
+ <!-- The real life example would be that this mime type is a sub class of application/xml
+ which has a magic that matches &lt;?xml .
+ XML files with an early appearing qnx tag are detected as
+ application/vnd.qnx.bar-descriptor. We want that XML files without the qnx tag to be
+ identified as application/xml, independent of the order in which the two are registered. -->
+ <mime-type type="application/vnd.qnx.bar-descriptor">
+ <sub-class-of type="application/foo"/>
+ <glob pattern="*.foo"/>
+ <magic><!-- higher priority than the parent magic -->
+ <match value="&lt;qnx&gt;" type="string" offset="0:200"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/foo">
+ <glob pattern="*.foo"/>
+ <magic priority="40">
+ <match value="&lt;?foo" type="string" offset="0"/>
+ </magic>
+ </mime-type>
+</mime-info>
diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy2.foo b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy2.foo
new file mode 100644
index 0000000000..fd90ed04b3
--- /dev/null
+++ b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy2.foo
@@ -0,0 +1,3 @@
+<?foo>
+<qnx>
+</qnx>
diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc b/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc
index 29666627a1..1002d0195d 100644
--- a/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc
+++ b/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc
@@ -7,5 +7,8 @@
<file>invalid-magic1.xml</file>
<file>invalid-magic2.xml</file>
<file>invalid-magic3.xml</file>
+ <file>magic-and-hierarchy.xml</file>
+ <file>magic-and-hierarchy.foo</file>
+ <file>magic-and-hierarchy2.foo</file>
</qresource>
</RCC>
diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
index 3144c3071c..9df52887f7 100644
--- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
+++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
@@ -52,6 +52,7 @@ static const char *const additionalMimeFiles[] = {
"invalid-magic1.xml",
"invalid-magic2.xml",
"invalid-magic3.xml",
+ "magic-and-hierarchy.xml",
0
};
@@ -985,6 +986,26 @@ void tst_QMimeDatabase::installNewGlobalMimeType()
qDebug() << objcsrc.globPatterns();
}
+ const QString fooTestFile = QLatin1String(RESOURCE_PREFIX "magic-and-hierarchy.foo");
+ QCOMPARE(db.mimeTypeForFile(fooTestFile).name(), QString::fromLatin1("application/foo"));
+
+ const QString fooTestFile2 = QLatin1String(RESOURCE_PREFIX "magic-and-hierarchy2.foo");
+ QCOMPARE(db.mimeTypeForFile(fooTestFile2).name(), QString::fromLatin1("application/vnd.qnx.bar-descriptor"));
+
+ // Test if we can use the default comment
+ {
+ struct RestoreLocale
+ {
+ ~RestoreLocale() { QLocale::setDefault(QLocale::c()); }
+ } restoreLocale;
+
+ QLocale::setDefault(QLocale("zh_CN"));
+ QMimeType suseymp = db.mimeTypeForName("text/x-suse-ymp");
+ QVERIFY(suseymp.isValid());
+ QCOMPARE(suseymp.comment(),
+ QString::fromLatin1("YaST Meta Package"));
+ }
+
// Now test removing the mimetype definitions again
for (int i = 0; i < m_additionalMimeFileNames.size(); ++i)
QFile::remove(destDir + m_additionalMimeFileNames.at(i));
diff --git a/tests/auto/corelib/plugin/plugin.pro b/tests/auto/corelib/plugin/plugin.pro
index b094c24e55..240608fddf 100644
--- a/tests/auto/corelib/plugin/plugin.pro
+++ b/tests/auto/corelib/plugin/plugin.pro
@@ -11,6 +11,5 @@ qtConfig(library): SUBDIRS += \
contains(CONFIG, static) {
message(Disabling tests requiring shared build of Qt)
SUBDIRS -= qfactoryloader \
- qplugin \
- qpluginloader
+ qplugin
}
diff --git a/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp b/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
index d285ed79c0..a290c012df 100644
--- a/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
+++ b/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -30,8 +31,11 @@
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
+#include <qplugin.h>
#include <QPluginLoader>
+#include <private/qplugin_p.h>
+
class tst_QPlugin : public QObject
{
Q_OBJECT
@@ -124,7 +128,10 @@ void tst_QPlugin::scanInvalidPlugin_data()
{
QTest::addColumn<QByteArray>("metadata");
QTest::addColumn<bool>("loads");
+ QTest::addColumn<QString>("errMsg");
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ // Binary JSON metadata
QByteArray prefix = "QTMETADATA ";
{
@@ -138,27 +145,65 @@ void tst_QPlugin::scanInvalidPlugin_data()
obj.insert("debug", true);
#endif
obj.insert("MetaData", QJsonObject());
- QTest::newRow("control") << (prefix + QJsonDocument(obj).toBinaryData()) << true;
+ QTest::newRow("json-control") << (prefix + QJsonDocument(obj).toBinaryData()) << true << "";
}
- QTest::newRow("zeroes") << prefix << false;
+ QTest::newRow("json-zeroes") << prefix << false << " ";
prefix += "qbjs";
- QTest::newRow("bad-json-version0") << prefix << false;
- QTest::newRow("bad-json-version2") << (prefix + QByteArray("\2\0\0\0", 4)) << false;
+ QTest::newRow("bad-json-version0") << prefix << false << " ";
+ QTest::newRow("bad-json-version2") << (prefix + QByteArray("\2\0\0\0", 4)) << false << " ";
// valid qbjs version 1
prefix += QByteArray("\1\0\0\0");
// too large for the file (100 MB)
- QTest::newRow("bad-json-size-large1") << (prefix + QByteArray("\0\0\x40\x06")) << false;
+ QTest::newRow("bad-json-size-large1") << (prefix + QByteArray("\0\0\x40\x06")) << false << " ";
// too large for binary JSON (512 MB)
- QTest::newRow("bad-json-size-large2") << (prefix + QByteArray("\0\0\0\x20")) << false;
+ QTest::newRow("bad-json-size-large2") << (prefix + QByteArray("\0\0\0\x20")) << false << " ";
// could overflow
- QTest::newRow("bad-json-size-large3") << (prefix + "\xff\xff\xff\x7f") << false;
+ QTest::newRow("bad-json-size-large3") << (prefix + "\xff\xff\xff\x7f") << false << " ";
+#endif
+ // CBOR metadata
+ QByteArray cprefix = "QTMETADATA !1234";
+ cprefix[12] = 0; // current version
+ cprefix[13] = QT_VERSION_MAJOR;
+ cprefix[14] = QT_VERSION_MINOR;
+ cprefix[15] = qPluginArchRequirements();
+
+ QByteArray cborValid = [] {
+ QCborMap m;
+ m.insert(int(QtPluginMetaDataKeys::IID), QLatin1String("org.qt-project.tst_qplugin"));
+ m.insert(int(QtPluginMetaDataKeys::ClassName), QLatin1String("tst"));
+ m.insert(int(QtPluginMetaDataKeys::MetaData), QCborMap());
+ return QCborValue(m).toCbor();
+ }();
+ QTest::newRow("cbor-control") << (cprefix + cborValid) << true << "";
+
+ cprefix[12] = 1;
+ QTest::newRow("cbor-major-too-new") << (cprefix + cborValid) << false
+ << " Invalid metadata version";
+
+ cprefix[12] = 0;
+ cprefix[13] = QT_VERSION_MAJOR + 1;
+ QTest::newRow("cbor-major-too-new") << (cprefix + cborValid) << false << "";
+
+ cprefix[13] = QT_VERSION_MAJOR - 1;
+ QTest::newRow("cbor-major-too-old") << (cprefix + cborValid) << false << "";
+
+ cprefix[13] = QT_VERSION_MAJOR;
+ cprefix[14] = QT_VERSION_MINOR + 1;
+ QTest::newRow("cbor-minor-too-new") << (cprefix + cborValid) << false << "";
+
+ QTest::newRow("cbor-invalid") << (cprefix + "\xff") << false
+ << " Metadata parsing error: Invalid CBOR stream: unexpected 'break' byte";
+ QTest::newRow("cbor-not-map1") << (cprefix + "\x01") << false
+ << " Unexpected metadata contents";
+ QTest::newRow("cbor-not-map2") << (cprefix + "\x81\x01") << false
+ << " Unexpected metadata contents";
}
static const char invalidPluginSignature[] = "qplugin testfile";
@@ -214,6 +259,11 @@ void tst_QPlugin::scanInvalidPlugin()
// now try to load this
QFETCH(bool, loads);
+ QFETCH(QString, errMsg);
+ if (!errMsg.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg,
+ "Found invalid metadata in lib " + QFile::encodeName(newName) +
+ ":" + errMsg.toUtf8());
QPluginLoader loader(newName);
QCOMPARE(loader.load(), loads);
if (loads)
diff --git a/tests/auto/corelib/plugin/qplugin/tst_qplugin.pro b/tests/auto/corelib/plugin/qplugin/tst_qplugin.pro
index 8c6540fe87..4432ee20c1 100644
--- a/tests/auto/corelib/plugin/qplugin/tst_qplugin.pro
+++ b/tests/auto/corelib/plugin/qplugin/tst_qplugin.pro
@@ -1,6 +1,6 @@
CONFIG += testcase
TARGET = tst_qplugin
-QT = core testlib
+QT = core-private testlib
SOURCES = tst_qplugin.cpp
TESTDATA += plugins/*
diff --git a/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h b/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h
index 04ce042e24..ac349c2f75 100644
--- a/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h
+++ b/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h
@@ -35,7 +35,7 @@
class ThePlugin : public QObject, public PluginInterface
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.autotests.plugininterface" FILE "../empty.json")
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.autotests.plugininterface" FILE "../utf8_data.json")
Q_INTERFACES(PluginInterface)
public:
diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
index f34741281c..c517c0809a 100644
--- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
+++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
@@ -140,6 +140,10 @@ void tst_QPluginLoader::cleanup()
void tst_QPluginLoader::errorString()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
+
const QString unknown(QLatin1String("Unknown error"));
{
@@ -206,6 +210,14 @@ void tst_QPluginLoader::errorString()
{
QPluginLoader loader( sys_qualifiedLibraryName("theplugin")); //a plugin
+
+ // Check metadata
+ const QJsonObject metaData = loader.metaData();
+ QCOMPARE(metaData.value("IID").toString(), QStringLiteral("org.qt-project.Qt.autotests.plugininterface"));
+ const QJsonObject kpluginObject = metaData.value("MetaData").toObject().value("KPlugin").toObject();
+ QCOMPARE(kpluginObject.value("Name[mr]").toString(), QString::fromUtf8("चौकट भूमिती"));
+
+ // Load
QCOMPARE(loader.load(), true);
QCOMPARE(loader.errorString(), unknown);
@@ -224,6 +236,9 @@ void tst_QPluginLoader::errorString()
void tst_QPluginLoader::loadHints()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
QPluginLoader loader;
QCOMPARE(loader.loadHints(), (QLibrary::LoadHints)0); //Do not crash
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint);
@@ -233,6 +248,9 @@ void tst_QPluginLoader::loadHints()
void tst_QPluginLoader::deleteinstanceOnUnload()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
for (int pass = 0; pass < 2; ++pass) {
QPluginLoader loader1;
loader1.setFileName( sys_qualifiedLibraryName("theplugin")); //a plugin
@@ -268,6 +286,9 @@ void tst_QPluginLoader::deleteinstanceOnUnload()
void tst_QPluginLoader::loadDebugObj()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires a shared build of Qt, as QPluginLoader::setFileName is a no-op in static builds");
+#endif
#if defined (__ELF__)
QVERIFY(QFile::exists(QFINDTESTDATA("elftest/debugobj.so")));
QPluginLoader lib1(QFINDTESTDATA("elftest/debugobj.so"));
@@ -277,6 +298,9 @@ void tst_QPluginLoader::loadDebugObj()
void tst_QPluginLoader::loadCorruptElf()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires a shared build of Qt, as QPluginLoader::setFileName is a no-op in static builds");
+#endif
#if defined (__ELF__)
if (sizeof(void*) == 8) {
QVERIFY(QFile::exists(QFINDTESTDATA("elftest/corrupt1.elf64.so")));
@@ -377,6 +401,9 @@ void tst_QPluginLoader::loadMachO()
#if defined (Q_OS_UNIX)
void tst_QPluginLoader::loadGarbage()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires a shared build of Qt, as QPluginLoader::setFileName is a no-op in static builds");
+#endif
for (int i=0; i<5; i++) {
const QString name = QLatin1String("elftest/garbage") + QString::number(i + 1) + QLatin1String(".so");
QPluginLoader lib(QFINDTESTDATA(name));
@@ -388,6 +415,9 @@ void tst_QPluginLoader::loadGarbage()
void tst_QPluginLoader::relativePath()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
// Windows binaries run from release and debug subdirs, so we can't rely on the current dir.
const QString binDir = QFINDTESTDATA("bin");
QVERIFY(!binDir.isEmpty());
@@ -402,6 +432,9 @@ void tst_QPluginLoader::relativePath()
void tst_QPluginLoader::absolutePath()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
// Windows binaries run from release and debug subdirs, so we can't rely on the current dir.
const QString binDir = QFINDTESTDATA("bin");
QVERIFY(!binDir.isEmpty());
@@ -416,6 +449,9 @@ void tst_QPluginLoader::absolutePath()
void tst_QPluginLoader::reloadPlugin()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
QPluginLoader loader;
loader.setFileName( sys_qualifiedLibraryName("theplugin")); //a plugin
loader.load(); // not recommended, instance() should do the job.
@@ -451,6 +487,9 @@ void tst_QPluginLoader::preloadedPlugin_data()
void tst_QPluginLoader::preloadedPlugin()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
// check that using QPluginLoader does not interfere with QLibrary
QFETCH(QString, libname);
QLibrary lib(libname);
diff --git a/tests/auto/corelib/plugin/qpluginloader/utf8_data.json b/tests/auto/corelib/plugin/qpluginloader/utf8_data.json
new file mode 100644
index 0000000000..7763b65178
--- /dev/null
+++ b/tests/auto/corelib/plugin/qpluginloader/utf8_data.json
@@ -0,0 +1,17 @@
+{
+ "KPlugin": {
+ "Name": "WindowGeometry",
+ "Name[mr]": "चौकट भूमिती",
+ "Name[pa]": "ਵਿੰਡੋਜੁਮੈਟਰੀ",
+ "Name[th]": "มิติขนาดของหน้าต่าง",
+ "Name[uk]": "Розміри вікна",
+ "Name[zh_CN]": "窗口形状",
+ "Name[zh_TW]": "視窗位置",
+ "ServiceTypes": [
+ "KCModule"
+ ]
+ },
+ "X-KDE-ParentComponents": [
+ "windowgeometry"
+ ]
+}
diff --git a/tests/auto/corelib/serialization/qcborstreamreader/qcborstreamreader.pro b/tests/auto/corelib/serialization/qcborstreamreader/qcborstreamreader.pro
new file mode 100644
index 0000000000..5df331314a
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborstreamreader/qcborstreamreader.pro
@@ -0,0 +1,11 @@
+QT = core testlib
+TARGET = tst_qcborstreamreader
+CONFIG += testcase
+SOURCES += \
+ tst_qcborstreamreader.cpp
+
+INCLUDEPATH += \
+ ../../../../../src/3rdparty/tinycbor/src \
+ ../../../../../src/3rdparty/tinycbor/tests/parser
+
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
diff --git a/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp b/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp
new file mode 100644
index 0000000000..3dd4b5114c
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp
@@ -0,0 +1,1091 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qcborstream.h>
+#include <QtTest>
+
+class tst_QCborStreamReader : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void initTestCase_data();
+ void basics();
+ void clear_data();
+ void clear();
+ void integers_data();
+ void integers();
+ void fixed_data();
+ void fixed();
+ void strings_data();
+ void strings();
+ void tags_data();
+ void tags() { fixed(); }
+ void emptyContainers_data();
+ void emptyContainers();
+
+ void arrays_data();
+ void arrays();
+ void maps_data() { arrays_data(); }
+ void maps();
+ void undefLengthArrays_data() { arrays_data(); }
+ void undefLengthArrays();
+ void undefLengthMaps_data() { arrays_data(); }
+ void undefLengthMaps();
+
+ void next_data() { arrays_data(); }
+ void next();
+ void validation_data();
+ void validation();
+ void recursionLimit_data();
+ void recursionLimit();
+
+ void addData_singleElement_data();
+ void addData_singleElement();
+ void addData_complex_data() { arrays_data(); }
+ void addData_complex();
+};
+
+#define FOR_CBOR_TYPE(F) \
+ F(QCborStreamReader::UnsignedInteger) \
+ F(QCborStreamReader::NegativeInteger) \
+ F(QCborStreamReader::ByteArray) \
+ F(QCborStreamReader::String) \
+ F(QCborStreamReader::Array) \
+ F(QCborStreamReader::Map) \
+ F(QCborStreamReader::Tag) \
+ F(QCborStreamReader::SimpleType) \
+ F(QCborStreamReader::Float16) \
+ F(QCborStreamReader::Float) \
+ F(QCborStreamReader::Double) \
+ F(QCborStreamReader::Invalid)
+
+QT_BEGIN_NAMESPACE
+namespace QTest {
+template<> char *toString<QCborStreamReader::Type>(const QCborStreamReader::Type &t)
+{
+ return qstrdup([=]() {
+ switch (t) {
+#define TYPE(t) \
+ case t: return QT_STRINGIFY(t);
+ FOR_CBOR_TYPE(TYPE)
+#undef TYPE
+ }
+ return "<huh?>";
+ }());
+}
+} // namespace QTest
+QT_END_NAMESPACE
+
+// Get the data from TinyCBOR (see src/3rdparty/tinycbor/tests/parser/data.cpp)
+#include "data.cpp"
+
+void tst_QCborStreamReader::initTestCase_data()
+{
+ QTest::addColumn<bool>("useDevice");
+ QTest::newRow("QByteArray") << false;
+ QTest::newRow("QBuffer") << true;
+}
+
+void tst_QCborStreamReader::basics()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QBuffer buffer;
+ QCborStreamReader reader;
+
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ QVERIFY(reader.device() != nullptr);
+ } else {
+ QCOMPARE(reader.device(), nullptr);
+ }
+
+ QCOMPARE(reader.currentOffset(), 0);
+ QCOMPARE(reader.lastError(), QCborError::EndOfFile);
+
+ QCOMPARE(reader.type(), QCborStreamReader::Invalid);
+ QVERIFY(!reader.isUnsignedInteger());
+ QVERIFY(!reader.isNegativeInteger());
+ QVERIFY(!reader.isByteArray());
+ QVERIFY(!reader.isString());
+ QVERIFY(!reader.isArray());
+ QVERIFY(!reader.isContainer());
+ QVERIFY(!reader.isMap());
+ QVERIFY(!reader.isTag());
+ QVERIFY(!reader.isSimpleType());
+ QVERIFY(!reader.isBool());
+ QVERIFY(!reader.isNull());
+ QVERIFY(!reader.isUndefined());
+ QVERIFY(!reader.isFloat16());
+ QVERIFY(!reader.isFloat());
+ QVERIFY(!reader.isDouble());
+ QVERIFY(!reader.isValid());
+ QVERIFY(reader.isInvalid());
+
+ QCOMPARE(reader.containerDepth(), 0);
+ QCOMPARE(reader.parentContainerType(), QCborStreamReader::Invalid);
+ QVERIFY(!reader.hasNext());
+ QVERIFY(!reader.next());
+ QCOMPARE(reader.lastError(), QCborError::EndOfFile);
+
+ QVERIFY(reader.isLengthKnown()); // well, it's not unknown
+ QCOMPARE(reader.length(), ~0ULL);
+
+ if (useDevice) {
+ reader.reparse();
+ QVERIFY(reader.device() != nullptr);
+ } else {
+ reader.addData(QByteArray());
+ QCOMPARE(reader.device(), nullptr);
+ }
+
+ // nothing changes, we added nothing
+ QCOMPARE(reader.currentOffset(), 0);
+ QCOMPARE(reader.lastError(), QCborError::EndOfFile);
+
+ QCOMPARE(reader.type(), QCborStreamReader::Invalid);
+ QVERIFY(!reader.isUnsignedInteger());
+ QVERIFY(!reader.isNegativeInteger());
+ QVERIFY(!reader.isByteArray());
+ QVERIFY(!reader.isString());
+ QVERIFY(!reader.isArray());
+ QVERIFY(!reader.isContainer());
+ QVERIFY(!reader.isMap());
+ QVERIFY(!reader.isTag());
+ QVERIFY(!reader.isSimpleType());
+ QVERIFY(!reader.isBool());
+ QVERIFY(!reader.isNull());
+ QVERIFY(!reader.isUndefined());
+ QVERIFY(!reader.isFloat16());
+ QVERIFY(!reader.isFloat());
+ QVERIFY(!reader.isDouble());
+ QVERIFY(!reader.isValid());
+ QVERIFY(reader.isInvalid());
+
+ QVERIFY(reader.isLengthKnown()); // well, it's not unknown
+ QCOMPARE(reader.length(), ~0ULL);
+
+ QCOMPARE(reader.containerDepth(), 0);
+ QCOMPARE(reader.parentContainerType(), QCborStreamReader::Invalid);
+ QVERIFY(!reader.hasNext());
+ QVERIFY(!reader.next());
+
+ reader.clear();
+ QCOMPARE(reader.device(), nullptr);
+ QCOMPARE(reader.currentOffset(), 0);
+ QCOMPARE(reader.lastError(), QCborError::EndOfFile);
+}
+
+void tst_QCborStreamReader::clear_data()
+{
+ QTest::addColumn<QByteArray>("data");
+ QTest::addColumn<QCborError>("firstError");
+ QTest::addColumn<int>("offsetAfterSkip");
+ QTest::newRow("invalid") << QByteArray(512, '\xff') << QCborError{QCborError::UnexpectedBreak} << 0;
+ QTest::newRow("valid") << QByteArray(512, '\0') << QCborError{QCborError::NoError} << 0;
+ QTest::newRow("skipped") << QByteArray(512, '\0') << QCborError{QCborError::NoError} << 1;
+}
+
+void tst_QCborStreamReader::clear()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+ QFETCH(QCborError, firstError);
+ QFETCH(int, offsetAfterSkip);
+
+ QBuffer buffer(&data);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ QCOMPARE(reader.isValid(), !firstError);
+ QCOMPARE(reader.currentOffset(), 0);
+ QCOMPARE(reader.lastError(), firstError);
+
+ if (offsetAfterSkip) {
+ reader.next();
+ QVERIFY(!reader.isValid());
+ QCOMPARE(reader.currentOffset(), 1);
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ }
+
+ reader.clear();
+ QCOMPARE(reader.device(), nullptr);
+ QCOMPARE(reader.currentOffset(), 0);
+ QCOMPARE(reader.lastError(), QCborError::EndOfFile);
+}
+
+void tst_QCborStreamReader::integers_data()
+{
+ addIntegers();
+}
+
+void tst_QCborStreamReader::integers()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+ QFETCH(bool, isNegative);
+ QFETCH(quint64, expectedRaw);
+ QFETCH(qint64, expectedValue);
+ QFETCH(bool, inInt64Range);
+ quint64 absolute = (isNegative ? expectedRaw + 1 : expectedRaw);
+
+ QBuffer buffer(&data);
+ QCborStreamReader reader(useDevice ? QByteArray() : data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ QVERIFY(reader.isInteger());
+
+ if (inInt64Range)
+ QCOMPARE(reader.toInteger(), expectedValue);
+ if (isNegative)
+ QCOMPARE(quint64(reader.toNegativeInteger()), absolute);
+ else
+ QCOMPARE(reader.toUnsignedInteger(), absolute);
+}
+
+void escapedAppendTo(QString &result, const QByteArray &data)
+{
+ result += "h'" + QString::fromLatin1(data.toHex()) + '\'';
+}
+
+void escapedAppendTo(QString &result, const QString &data)
+{
+ result += '"';
+ for (int i = 0; i <= data.size(); i += 245) {
+ // hopefully we won't have a surrogate pair split here
+ QScopedArrayPointer<char> escaped(QTest::toPrettyUnicode(data.mid(i, 245)));
+ QLatin1String s(escaped.data() + 1); // skip opening "
+ s.chop(1); // drop the closing "
+ result += s;
+ }
+ result += '"';
+}
+
+template <typename S, QCborStreamReader::StringResult<S> (QCborStreamReader:: *Decoder)()>
+static QString parseOneString_helper(QCborStreamReader &reader)
+{
+ QString result;
+ bool parens = !reader.isLengthKnown();
+ if (parens)
+ result += '(';
+
+ auto r = (reader.*Decoder)();
+ const char *comma = "";
+ while (r.status == QCborStreamReader::Ok) {
+ result += comma;
+ escapedAppendTo(result, r.data);
+
+ r = (reader.*Decoder)();
+ comma = ", ";
+ }
+
+ if (r.status == QCborStreamReader::Error)
+ return QString();
+
+ if (parens)
+ result += ')';
+ return result;
+}
+
+static QString parseOneByteArray(QCborStreamReader &reader)
+{
+ return parseOneString_helper<QByteArray, &QCborStreamReader::readByteArray>(reader);
+}
+
+static QString parseOneString(QCborStreamReader &reader)
+{
+ return parseOneString_helper<QString, &QCborStreamReader::readString>(reader);
+}
+
+static QString makeNegativeString(QCborNegativeInteger n)
+{
+ return n == QCborNegativeInteger(0) ?
+ QString("-18446744073709551616") :
+ QString("-%1").arg(quint64(n));
+}
+
+template <typename T> static inline bool canConvertTo(double v)
+{
+ // The [conv.fpint] (7.10 Floating-integral conversions) section of the
+ // standard says only exact conversions are guaranteed. Converting
+ // integrals to floating-point with loss of precision has implementation-
+ // defined behavior whether the next higher or next lower is returned;
+ // converting FP to integral is UB if it can't be represented.;
+ Q_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
+
+ double supremum = ldexp(1, std::numeric_limits<T>::digits);
+ if (v >= supremum)
+ return false;
+
+ if (v < std::numeric_limits<T>::min()) // either zero or a power of two, so it's exact
+ return false;
+
+ // we're in range
+ return v == floor(v);
+}
+
+static QString makeFpString(double v)
+{
+ if (canConvertTo<qint64>(v))
+ return QString::number(qint64(v)) + '.';
+ if (canConvertTo<quint64>(v))
+ return QString::number(quint64(v)) + '.';
+
+ QString s = QString::number(v, 'g', std::numeric_limits<double>::digits10 + 2);
+ if (!s.contains('.') && !s.contains('e') && !qIsInf(v) && !qIsNaN(v))
+ s += '.';
+ return s;
+}
+
+static QString makeFpString(float v)
+{
+ if (qIsInf(v))
+ return v > 0 ? "inf" : "-inf";
+ if (qIsNaN(v))
+ return "nan";
+ return makeFpString(double(v)) + 'f';
+}
+
+static QString makeFpString(qfloat16 v)
+{
+ if (qIsInf(v))
+ return v > 0 ? "inf" : "-inf";
+ if (qIsNaN(v))
+ return "nan";
+ return makeFpString(double(v)) + "f16";
+}
+
+static QString parseOne(QCborStreamReader &reader)
+{
+ QString result;
+
+ switch (reader.type()) {
+ case QCborStreamReader::UnsignedInteger:
+ result = QString::number(reader.toUnsignedInteger());
+ break;
+ case QCborStreamReader::NegativeInteger:
+ result = makeNegativeString(reader.toNegativeInteger());
+ break;
+ case QCborStreamReader::ByteArray:
+ return parseOneByteArray(reader);
+ case QCborStreamReader::String:
+ return parseOneString(reader);
+ case QCborStreamReader::Array:
+ case QCborStreamReader::Map: {
+ const char *delimiters = (reader.isArray() ? "[]" : "{}");
+ result += delimiters[0];
+ reader.enterContainer();
+
+ QLatin1String comma("");
+ while (reader.lastError() == QCborError::NoError && reader.hasNext()) {
+ result += comma + parseOne(reader);
+ comma = QLatin1String(", ");
+
+ if (reader.parentContainerType() == QCborStreamReader::Map
+ && reader.lastError() == QCborError::NoError)
+ result += ": " + parseOne(reader);
+ }
+
+ if (reader.isValid())
+ return QString();
+ if (reader.lastError() != QCborError::NoError)
+ return QString();
+ reader.leaveContainer();
+ result += delimiters[1];
+ return result;
+ }
+ case QCborStreamReader::Tag: {
+ QCborTag tag = reader.toTag();
+ if (!reader.next())
+ return QString();
+ return QString("%1(%2)").arg(quint64(tag)).arg(parseOne(reader));
+ }
+ case QCborStreamReader::SimpleType:
+ switch (reader.toSimpleType()) {
+ case QCborSimpleType::False:
+ result = QStringLiteral("false");
+ break;
+ case QCborSimpleType::True:
+ result = QStringLiteral("true");
+ break;
+ case QCborSimpleType::Null:
+ result = QStringLiteral("null");
+ break;
+ case QCborSimpleType::Undefined:
+ result = QStringLiteral("undefined");
+ break;
+ default:
+ result = QString("simple(%1)").arg(quint8(reader.toSimpleType()));
+ break;
+ }
+ break;
+ case QCborStreamReader::Float16:
+ result = makeFpString(reader.toFloat16());
+ break;
+ case QCborStreamReader::Float:
+ result = makeFpString(reader.toFloat());
+ break;
+ case QCborStreamReader::Double:
+ result = makeFpString(reader.toDouble());
+ break;
+ case QCborStreamReader::Invalid:
+ return QStringLiteral("<invalid>");
+ }
+
+ if (!reader.next())
+ return QString();
+ return result;
+}
+
+bool parseNonRecursive(QString &result, bool &printingStringChunks, QCborStreamReader &reader)
+{
+ while (reader.lastError() == QCborError::NoError) {
+ if (!reader.hasNext()) {
+ if (result.endsWith(", "))
+ result.chop(2);
+ if (reader.containerDepth() == 0)
+ return true;
+ result += reader.parentContainerType() == QCborStreamReader::Map ? "}, " : "], ";
+ reader.leaveContainer();
+ continue;
+ }
+
+ switch (reader.type()) {
+ case QCborStreamReader::UnsignedInteger:
+ result += QString::number(reader.toUnsignedInteger());
+ break;
+ case QCborStreamReader::NegativeInteger:
+ result += makeNegativeString(reader.toNegativeInteger());
+ break;
+ case QCborStreamReader::ByteArray:
+ case QCborStreamReader::String: {
+ QCborStreamReader::StringResultCode status;
+ if (!printingStringChunks && !reader.isLengthKnown()) {
+ printingStringChunks = true;
+ result += '(';
+ }
+ if (reader.isByteArray()) {
+ auto r = reader.readByteArray();
+ status = r.status;
+ if (r.status == QCborStreamReader::Ok)
+ escapedAppendTo(result, r.data);
+ } else {
+ auto r = reader.readString();
+ status = r.status;
+ if (r.status == QCborStreamReader::Ok)
+ escapedAppendTo(result, r.data);
+ }
+
+ if (status == QCborStreamReader::EndOfString) {
+ if (result.endsWith(", "))
+ result.chop(2);
+ if (printingStringChunks)
+ result += ')';
+ result += ", ";
+ printingStringChunks = false;
+ }
+ if (status == QCborStreamReader::Ok && printingStringChunks)
+ result += ", ";
+
+ continue;
+ }
+ case QCborStreamReader::Array:
+ result += '[';
+ reader.enterContainer();
+ continue;
+ case QCborStreamReader::Map:
+ result += '{';
+ reader.enterContainer();
+ continue;
+ case QCborStreamReader::Tag:
+ result += QString("Tag:%1:").arg(quint64(reader.toTag()));
+ reader.next();
+ continue; // skip the comma
+ case QCborStreamReader::SimpleType:
+ switch (reader.toSimpleType()) {
+ case QCborSimpleType::False:
+ result += QStringLiteral("false");
+ break;
+ case QCborSimpleType::True:
+ result += QStringLiteral("true");
+ break;
+ case QCborSimpleType::Null:
+ result += QStringLiteral("null");
+ break;
+ case QCborSimpleType::Undefined:
+ result += QStringLiteral("undefined");
+ break;
+ default:
+ result += QString("simple(%1)").arg(quint8(reader.toSimpleType()));
+ break;
+ }
+ break;
+ case QCborStreamReader::Float16:
+ result += makeFpString(reader.toFloat16());
+ break;
+ case QCborStreamReader::Float:
+ result += makeFpString(reader.toFloat());
+ break;
+ case QCborStreamReader::Double:
+ result += makeFpString(reader.toDouble());
+ break;
+ case QCborStreamReader::Invalid:
+ break;
+ }
+
+ reader.next();
+ result += ", ";
+ }
+ return false;
+};
+
+
+static QString &removeIndicators(QString &str)
+{
+ // remove any CBOR encoding indicators from the string, since parseOne above
+ // doesn't produce them
+ static QRegularExpression rx("_(\\d+)? ?");
+ return str.replace(rx, QString());
+}
+
+void tst_QCborStreamReader::fixed_data()
+{
+ addColumns();
+ addFixedData();
+}
+
+void tst_QCborStreamReader::fixed()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ QBuffer buffer(&data);
+ QCborStreamReader reader(useDevice ? QByteArray() : data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ QCOMPARE(parseOne(reader), expected);
+
+ // verify that we can re-read
+ reader.reset();
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ QCOMPARE(parseOne(reader), expected);
+}
+
+void tst_QCborStreamReader::strings_data()
+{
+ addColumns();
+ addStringsData();
+}
+
+void tst_QCborStreamReader::strings()
+{
+ fixed();
+ if (QTest::currentTestFailed())
+ return;
+
+ // Extra string checks:
+ // We'll compare the reads using readString() and readByteArray()
+ // (henceforth "control data" because fixed() above tested them) with those
+ // obtained with readStringChunk().
+
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ QFETCH_GLOBAL(bool, useDevice);
+ bool isChunked = expected.startsWith('(');
+
+ QBuffer buffer(&data), controlBuffer(&data);
+ QCborStreamReader reader(data), controlReader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ controlBuffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ controlReader.setDevice(&controlBuffer);
+ }
+ QVERIFY(reader.isString() || reader.isByteArray());
+ QCOMPARE(reader.isLengthKnown(), !isChunked);
+
+ if (!isChunked)
+ QCOMPARE(reader.currentStringChunkSize(), qsizetype(reader.length()));
+
+ int chunks = 0;
+ forever {
+ QCborStreamReader::StringResult<QByteArray> controlData;
+ if (reader.isString()) {
+ auto r = controlReader.readString();
+ controlData.data = r.data.toUtf8();
+ controlData.status = r.status;
+ } else {
+ controlData = controlReader.readByteArray();
+ }
+ QVERIFY(controlData.status != QCborStreamReader::Error);
+
+ for (int i = 0; i < 10; ++i) {
+ // this call must work several times with the same result
+ QCOMPARE(reader.currentStringChunkSize(), controlData.data.size());
+ }
+
+ QByteArray chunk(controlData.data.size(), Qt::Uninitialized);
+ auto r = reader.readStringChunk(chunk.data(), chunk.size());
+ QCOMPARE(r.status, controlData.status);
+ if (r.status == QCborStreamReader::Ok)
+ QCOMPARE(r.data, controlData.data.size());
+ else
+ QCOMPARE(r.data, 0);
+ QCOMPARE(chunk, controlData.data);
+
+ if (r.status == QCborStreamReader::EndOfString)
+ break;
+ ++chunks;
+ }
+
+ if (!isChunked)
+ QCOMPARE(chunks, 1);
+}
+
+void tst_QCborStreamReader::tags_data()
+{
+ addColumns();
+ addTagsData();
+}
+
+void tst_QCborStreamReader::emptyContainers_data()
+{
+ addColumns();
+ addEmptyContainersData();
+}
+
+void tst_QCborStreamReader::emptyContainers()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ QBuffer buffer(&data);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ if (reader.isLengthKnown())
+ QCOMPARE(reader.length(), 0U);
+ QCOMPARE(parseOne(reader), expected);
+
+ // verify that we can re-read
+ reader.reset();
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ if (reader.isLengthKnown())
+ QCOMPARE(reader.length(), 0U);
+ QCOMPARE(parseOne(reader), expected);
+}
+
+void tst_QCborStreamReader::arrays_data()
+{
+ addColumns();
+ addFixedData();
+ addStringsData();
+ addTagsData();
+ addEmptyContainersData();
+}
+
+static void checkContainer(int len, const QByteArray &data, const QString &expected)
+{
+ QFETCH_GLOBAL(bool, useDevice);
+
+ QByteArray copy = data;
+ QBuffer buffer(&copy);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ if (len >= 0) {
+ QVERIFY(reader.isLengthKnown());
+ QCOMPARE(reader.length(), uint(len));
+ }
+ QCOMPARE(parseOne(reader), expected);
+
+ // verify that we can re-read
+ reader.reset();
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ if (len >= 0) {
+ QVERIFY(reader.isLengthKnown());
+ QCOMPARE(reader.length(), uint(len));
+ }
+ QCOMPARE(parseOne(reader), expected);
+}
+
+void tst_QCborStreamReader::arrays()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ checkContainer(1, '\x81' + data, '[' + expected + ']');
+ if (QTest::currentTestFailed())
+ return;
+
+ checkContainer(2, '\x82' + data + data, '[' + expected + ", " + expected + ']');
+}
+
+void tst_QCborStreamReader::maps()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ // int keys
+ checkContainer(1, "\xa1\1" + data, "{1: " + expected + '}');
+ if (QTest::currentTestFailed())
+ return;
+
+ checkContainer(2, "\xa2\1" + data + '\x20' + data,
+ "{1: " + expected + ", -1: " + expected + '}');
+ if (QTest::currentTestFailed())
+ return;
+
+ // string keys
+ checkContainer(1, "\xa1\x65Hello" + data, "{\"Hello\": " + expected + '}');
+ if (QTest::currentTestFailed())
+ return;
+
+ checkContainer(2, "\xa2\x65World" + data + "\x65Hello" + data,
+ "{\"World\": " + expected + ", \"Hello\": " + expected + '}');
+}
+
+void tst_QCborStreamReader::undefLengthArrays()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ checkContainer(-1, '\x9f' + data + '\xff', '[' + expected + ']');
+ if (QTest::currentTestFailed())
+ return;
+
+ checkContainer(-2, '\x9f' + data + data + '\xff', '[' + expected + ", " + expected + ']');
+}
+
+void tst_QCborStreamReader::undefLengthMaps()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ // int keys
+ checkContainer(-1, "\xbf\1" + data + '\xff', "{1: " + expected + '}');
+ if (QTest::currentTestFailed())
+ return;
+
+ checkContainer(-2, "\xbf\1" + data + '\x20' + data + '\xff',
+ "{1: " + expected + ", -1: " + expected + '}');
+ if (QTest::currentTestFailed())
+ return;
+
+ // string keys
+ checkContainer(-1, "\xbf\x65Hello" + data + '\xff', "{\"Hello\": " + expected + '}');
+ if (QTest::currentTestFailed())
+ return;
+
+ checkContainer(-2, "\xbf\x65World" + data + "\x65Hello" + data + '\xff',
+ "{\"World\": " + expected + ", \"Hello\": " + expected + '}');
+}
+
+void tst_QCborStreamReader::next()
+{
+ QFETCH(QByteArray, data);
+
+ auto doit = [](QByteArray data) {
+ QFETCH_GLOBAL(bool, useDevice);
+
+ QBuffer buffer(&data);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ return reader.next();
+ };
+
+ QVERIFY(doit('\x81' + data));
+ QVERIFY(doit('\x82' + data + data));
+ QVERIFY(doit('\x9f' + data + '\xff'));
+ QVERIFY(doit("\x81\x9f" + data + '\xff'));
+ QVERIFY(doit("\x9f\x81" + data + '\xff'));
+
+ QVERIFY(doit("\xa1\1" + data));
+ QVERIFY(doit("\xa2\1" + data + '\x20' + data));
+ QVERIFY(doit("\xbf\1" + data + '\xff'));
+ QVERIFY(doit("\xbf\x9f\1\xff\x9f" + data + "\xff\xff"));
+}
+
+void tst_QCborStreamReader::validation_data()
+{
+ addValidationColumns();
+ addValidationData();
+}
+
+void tst_QCborStreamReader::validation()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+
+ QBuffer buffer(&data);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ parseOne(reader);
+ QVERIFY(reader.lastError() != QCborError::NoError);
+
+ // next() should fail
+ reader.reset();
+ QVERIFY(!reader.next());
+ QVERIFY(reader.lastError() != QCborError::NoError);
+}
+
+static const int Recursions = 3;
+void tst_QCborStreamReader::recursionLimit_data()
+{
+ static const int recursions = Recursions + 2;
+ QTest::addColumn<QByteArray>("data");
+
+ QTest::newRow("array") << QByteArray(recursions, '\x81') + '\x20';
+ QTest::newRow("_array") << QByteArray(recursions, '\x9f') + '\x20' + QByteArray(recursions, '\xff');
+
+ QByteArray data;
+ for (int i = 0; i < recursions; ++i)
+ data += "\xa1\x65Hello";
+ data += '\2';
+ QTest::newRow("map-recursive-values") << data;
+
+ data.clear();
+ for (int i = 0; i < recursions; ++i)
+ data += "\xbf\x65World";
+ data += '\2';
+ for (int i = 0; i < recursions; ++i)
+ data += "\xff";
+ QTest::newRow("_map-recursive-values") << data;
+
+ data = QByteArray(recursions, '\xa1');
+ data += '\2';
+ for (int i = 0; i < recursions; ++i)
+ data += "\x7f\x64quux\xff";
+ QTest::newRow("map-recursive-keys") << data;
+
+ data = QByteArray(recursions, '\xbf');
+ data += '\2';
+ for (int i = 0; i < recursions; ++i)
+ data += "\1\xff";
+ QTest::newRow("_map-recursive-keys") << data;
+
+ data.clear();
+ for (int i = 0; i < recursions / 2; ++i)
+ data += "\x81\xa1\1";
+ data += '\2';
+ QTest::newRow("mixed") << data;
+}
+
+void tst_QCborStreamReader::recursionLimit()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+
+ data.prepend('\x81');
+ QBuffer buffer(&data);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+
+ // verify that it works normally:
+ QVERIFY(reader.enterContainer());
+ QVERIFY(reader.next());
+ QVERIFY(!reader.hasNext());
+
+ reader.reset();
+ QVERIFY(reader.enterContainer());
+ QVERIFY(!reader.next(Recursions));
+ QCOMPARE(reader.lastError(), QCborError::NestingTooDeep);
+}
+
+void tst_QCborStreamReader::addData_singleElement_data()
+{
+ addColumns();
+ addFixedData();
+ addNonChunkedStringsData();
+}
+
+void tst_QCborStreamReader::addData_singleElement()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ QByteArray growing;
+ QBuffer buffer(&growing);
+ QCborStreamReader reader;
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ for (int i = 0; i < data.size() - 1; ++i) {
+ // add one byte from the data
+ if (useDevice) {
+ growing.append(data.at(i));
+ reader.reparse();
+ } else {
+ reader.addData(data.constData() + i, 1);
+ }
+
+ parseOne(reader);
+ QCOMPARE(reader.lastError(), QCborError::EndOfFile);
+ }
+
+ // add the last byte
+ if (useDevice) {
+ growing.append(data.right(1));
+ reader.reparse();
+ } else {
+ reader.addData(data.right(1));
+ }
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ QCOMPARE(parseOne(reader), expected);
+}
+
+void tst_QCborStreamReader::addData_complex()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ // transform tags (parseNonRecursive can't produce the usual form)
+ expected.replace(QRegularExpression(R"/((\d+)\(([^)]+)\))/"), "Tag:\\1:\\2");
+
+ auto doit = [](const QByteArray &data) {
+ QFETCH_GLOBAL(bool, useDevice);
+
+ // start with one byte
+ int added = 1;
+ QByteArray growing = data.left(added);
+ QBuffer buffer(&growing);
+ QCborStreamReader reader(growing);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+
+ QString result;
+ bool printingStringChunks = false;
+ forever {
+ if (parseNonRecursive(result, printingStringChunks, reader))
+ return result;
+ if (reader.lastError() != QCborError::EndOfFile)
+ return reader.lastError().toString();
+
+ while (reader.lastError() == QCborError::EndOfFile) {
+ // add more data
+ if (added == data.size())
+ return QStringLiteral("Couldn't parse even with all data");
+
+ if (useDevice) {
+ growing.append(data.at(added));
+ reader.reparse();
+ } else {
+ reader.addData(data.constData() + added, 1);
+ }
+ ++added;
+ }
+ }
+ };
+
+ // plain:
+ QCOMPARE(doit(data), expected);
+
+ // in an array
+ QCOMPARE(doit('\x81' + data), '[' + expected + ']');
+ QCOMPARE(doit('\x82' + data + data), '[' + expected + ", " + expected + ']');
+
+ QCOMPARE(doit('\x9f' + data + '\xff'), '[' + expected + ']');
+ QCOMPARE(doit('\x9f' + data + data + '\xff'), '[' + expected + ", " + expected + ']');
+
+ // in a map
+ QCOMPARE(doit("\xa1\x01" + data), "{1, " + expected + '}');
+ QCOMPARE(doit("\xa1\x65Hello" + data), "{\"Hello\", " + expected + '}');
+ QCOMPARE(doit("\xa1\x7f\x65Hello\x65World\xff" + data), "{(\"Hello\", \"World\"), " + expected + '}');
+ QCOMPARE(doit("\xa2\x01" + data + "\x65Hello" + data),
+ "{1, " + expected + ", \"Hello\", " + expected + '}');
+
+ QCOMPARE(doit("\xbf\x01" + data + '\xff'), "{1, " + expected + '}');
+
+ // mixed
+ QCOMPARE(doit("\xbf\x01\x81" + data + '\xff'), "{1, [" + expected + "]}");
+ QCOMPARE(doit("\xbf\x01\x82" + data + data + '\xff'),
+ "{1, [" + expected + ", " + expected + "]}");
+ QCOMPARE(doit("\xbf\x01\x9f" + data + data + "\xff\xff"),
+ "{1, [" + expected + ", " + expected + "]}");
+}
+
+
+QTEST_MAIN(tst_QCborStreamReader)
+
+#include "tst_qcborstreamreader.moc"
diff --git a/tests/auto/corelib/serialization/qcborstreamwriter/qcborstreamwriter.pro b/tests/auto/corelib/serialization/qcborstreamwriter/qcborstreamwriter.pro
new file mode 100644
index 0000000000..3391b5a296
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborstreamwriter/qcborstreamwriter.pro
@@ -0,0 +1,8 @@
+QT = core testlib
+TARGET = tst_qcborstreamwriter
+CONFIG += testcase
+SOURCES += \
+ tst_qcborstreamwriter.cpp
+
+INCLUDEPATH += ../../../../../src/3rdparty/tinycbor/tests/encoder
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
diff --git a/tests/auto/corelib/serialization/qcborstreamwriter/tst_qcborstreamwriter.cpp b/tests/auto/corelib/serialization/qcborstreamwriter/tst_qcborstreamwriter.cpp
new file mode 100644
index 0000000000..6995b4d08b
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborstreamwriter/tst_qcborstreamwriter.cpp
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest>
+
+class tst_QCborStreamWriter : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void initTestCase_data();
+ void fixed_data();
+ void fixed();
+ void strings_data();
+ void strings() { fixed(); }
+ void nonAsciiStrings_data();
+ void nonAsciiStrings();
+ void arraysAndMaps_data();
+ void arraysAndMaps() { fixed(); }
+ void tags_data();
+ void tags();
+ void arrays_data() { tags_data(); }
+ void arrays();
+ void maps_data() { tags_data(); }
+ void maps();
+};
+
+// Get the data from TinyCBOR (see src/3rdparty/tinycbor/tests/encoder/data.cpp)
+typedef quint64 CborTag;
+#include "data.cpp"
+
+void encodeVariant(QCborStreamWriter &writer, const QVariant &v)
+{
+ int type = v.userType();
+ switch (type) {
+ case QVariant::Int:
+ case QVariant::LongLong:
+ return writer.append(v.toLongLong());
+
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ return writer.append(v.toULongLong());
+
+ case QVariant::Bool:
+ return writer.append(v.toBool());
+
+ case QVariant::Invalid:
+ return writer.appendUndefined();
+
+ case QMetaType::VoidStar:
+ return writer.append(nullptr);
+
+ case QVariant::Double:
+ return writer.append(v.toDouble());
+
+ case QMetaType::Float:
+ return writer.append(v.toFloat());
+
+ case QVariant::String:
+ return writer.append(v.toString());
+
+ case QVariant::ByteArray:
+ return writer.append(v.toByteArray());
+
+ default:
+ if (type == qMetaTypeId<NegativeInteger>())
+ return writer.append(QCborNegativeInteger(v.value<NegativeInteger>().abs));
+ if (type == qMetaTypeId<SimpleType>())
+ return writer.append(QCborSimpleType(v.value<SimpleType>().type));
+ if (type == qMetaTypeId<qfloat16>())
+ return writer.append(v.value<qfloat16>());
+ if (type == qMetaTypeId<Tag>()) {
+ writer.append(QCborTag(v.value<Tag>().tag));
+ return encodeVariant(writer, v.value<Tag>().tagged);
+ }
+ if (type == QVariant::List || type == qMetaTypeId<IndeterminateLengthArray>()) {
+ QVariantList list = v.toList();
+ if (type == qMetaTypeId<IndeterminateLengthArray>()) {
+ list = v.value<IndeterminateLengthArray>();
+ writer.startArray();
+ } else {
+ writer.startArray(list.length());
+ }
+ for (const QVariant &v2 : qAsConst(list))
+ encodeVariant(writer, v2);
+ QVERIFY(writer.endArray());
+ return;
+ }
+ if (type == qMetaTypeId<Map>() || type == qMetaTypeId<IndeterminateLengthMap>()) {
+ Map map = v.value<Map>();
+ if (type == qMetaTypeId<IndeterminateLengthMap>()) {
+ map = v.value<IndeterminateLengthMap>();
+ writer.startMap();
+ } else {
+ writer.startMap(map.length());
+ }
+ for (auto pair : qAsConst(map)) {
+ encodeVariant(writer, pair.first);
+ encodeVariant(writer, pair.second);
+ }
+ QVERIFY(writer.endMap());
+ return;
+ }
+ }
+ QFAIL("Shouldn't have got here");
+}
+
+void compare(const QVariant &input, const QByteArray &output)
+{
+ QFETCH_GLOBAL(bool, useDevice);
+
+ if (useDevice) {
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QCborStreamWriter writer(&buffer);
+ encodeVariant(writer, input);
+ QCOMPARE(buffer.data(), output);
+ } else {
+ QByteArray buffer;
+ QCborStreamWriter writer(&buffer);
+ encodeVariant(writer, input);
+ QCOMPARE(buffer, output);
+ }
+}
+
+void tst_QCborStreamWriter::initTestCase_data()
+{
+ QTest::addColumn<bool>("useDevice");
+ QTest::newRow("QByteArray") << false;
+ QTest::newRow("QIODevice") << true;
+}
+
+void tst_QCborStreamWriter::fixed_data()
+{
+ addColumns();
+ addFixedData();
+}
+
+void tst_QCborStreamWriter::fixed()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+ compare(input, output);
+}
+
+void tst_QCborStreamWriter::strings_data()
+{
+ addColumns();
+ addStringsData();
+}
+
+void tst_QCborStreamWriter::nonAsciiStrings_data()
+{
+ QTest::addColumn<QByteArray>("output");
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<bool>("isLatin1");
+
+ QByteArray latin1 = u8"Résumé";
+ QTest::newRow("shortlatin1")
+ << ("\x68" + latin1) << QString::fromUtf8(latin1) << true;
+
+ // replicate it 5 times (total 40 bytes)
+ latin1 += latin1 + latin1 + latin1 + latin1;
+ QTest::newRow("longlatin1")
+ << ("\x78\x28" + latin1) << QString::fromUtf8(latin1) << true;
+
+ QByteArray nonlatin1 = u8"Χαίρετε";
+ QTest::newRow("shortnonlatin1")
+ << ("\x6e" + nonlatin1) << QString::fromUtf8(nonlatin1) << false;
+
+ // replicate it 4 times (total 56 bytes)
+ nonlatin1 = nonlatin1 + nonlatin1 + nonlatin1 + nonlatin1;
+ QTest::newRow("longnonlatin1")
+ << ("\x78\x38" + nonlatin1) << QString::fromUtf8(nonlatin1) << false;
+}
+
+void tst_QCborStreamWriter::nonAsciiStrings()
+{
+ QFETCH(QByteArray, output);
+ QFETCH(QString, input);
+ QFETCH(bool, isLatin1);
+ QFETCH_GLOBAL(bool, useDevice);
+
+ // will be wrong if !isLatin1
+ QByteArray latin1 = input.toLatin1();
+
+ if (useDevice) {
+ {
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QCborStreamWriter writer(&buffer);
+ writer.append(input);
+ QCOMPARE(buffer.data(), output);
+ }
+
+ if (isLatin1) {
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QCborStreamWriter writer(&buffer);
+ writer.append(QLatin1String(latin1.constData(), latin1.size()));
+ QCOMPARE(buffer.data(), output);
+ }
+ } else {
+ {
+ QByteArray buffer;
+ QCborStreamWriter writer(&buffer);
+ encodeVariant(writer, input);
+ QCOMPARE(buffer, output);
+ }
+
+ if (isLatin1) {
+ QByteArray buffer;
+ QCborStreamWriter writer(&buffer);
+ writer.append(QLatin1String(latin1.constData(), latin1.size()));
+ QCOMPARE(buffer, output);
+ }
+ }
+}
+
+void tst_QCborStreamWriter::arraysAndMaps_data()
+{
+ addColumns();
+ addArraysAndMaps();
+}
+
+void tst_QCborStreamWriter::tags_data()
+{
+ addColumns();
+ addFixedData();
+ addStringsData();
+ addArraysAndMaps();
+}
+
+void tst_QCborStreamWriter::tags()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+
+ compare(QVariant::fromValue(Tag{1, input}), "\xc1" + output);
+}
+
+void tst_QCborStreamWriter::arrays()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+
+ compare(make_list(input), "\x81" + output);
+ if (QTest::currentTestFailed())
+ return;
+
+ compare(make_list(input, input), "\x82" + output + output);
+ if (QTest::currentTestFailed())
+ return;
+
+ // nested lists
+ compare(make_list(make_list(input)), "\x81\x81" + output);
+ if (QTest::currentTestFailed())
+ return;
+
+ compare(make_list(make_list(input), make_list(input)), "\x82\x81" + output + "\x81" + output);
+}
+
+void tst_QCborStreamWriter::maps()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+
+ compare(make_map({{1, input}}), "\xa1\1" + output);
+ if (QTest::currentTestFailed())
+ return;
+
+ compare(make_map({{1, input}, {input, 24}}), "\xa2\1" + output + output + "\x18\x18");
+}
+
+QTEST_MAIN(tst_QCborStreamWriter)
+
+#include "tst_qcborstreamwriter.moc"
diff --git a/tests/auto/corelib/serialization/qcborvalue/qcborvalue.pro b/tests/auto/corelib/serialization/qcborvalue/qcborvalue.pro
new file mode 100644
index 0000000000..9dd67da1f0
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborvalue/qcborvalue.pro
@@ -0,0 +1,11 @@
+QT = core testlib
+TARGET = tst_qcborvalue
+CONFIG += testcase
+SOURCES += \
+ tst_qcborvalue.cpp
+
+INCLUDEPATH += \
+ ../../../../../src/3rdparty/tinycbor/src \
+ ../../../../../src/3rdparty/tinycbor/tests/parser
+
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
new file mode 100644
index 0000000000..4b753eab6b
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
@@ -0,0 +1,1695 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qcborvalue.h>
+#include <QtTest>
+
+Q_DECLARE_METATYPE(QCborValue)
+Q_DECLARE_METATYPE(QCborValue::EncodingOptions)
+
+class tst_QCborValue : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void basics_data();
+ void basics();
+ void tagged_data() { basics_data(); }
+ void tagged();
+ void extendedTypes_data();
+ void extendedTypes();
+ void copyCompare_data() { basics_data(); }
+ void copyCompare();
+
+ void arrayDefaultInitialization();
+ void arrayEmptyInitializerList();
+ void arrayEmptyDetach();
+ void arrayInitializerList();
+ void arrayMutation();
+ void arrayPrepend();
+ void arrayInsertRemove_data() { basics_data(); }
+ void arrayInsertRemove();
+ void arrayInsertTagged_data() { basics_data(); }
+ void arrayInsertTagged();
+ void arrayStringElements();
+ void arraySelfAssign_data() { basics_data(); }
+ void arraySelfAssign();
+
+ void mapDefaultInitialization();
+ void mapEmptyInitializerList();
+ void mapEmptyDetach();
+ void mapSimpleInitializerList();
+ void mapMutation();
+ void mapStringValues();
+ void mapStringKeys();
+ void mapInsertRemove_data() { basics_data(); }
+ void mapInsertRemove();
+ void mapInsertTagged_data() { basics_data(); }
+ void mapInsertTagged();
+ void mapSelfAssign_data() { basics_data(); }
+ void mapSelfAssign();
+ void mapComplexKeys_data() { basics_data(); }
+ void mapComplexKeys();
+
+ void sorting();
+
+ void toCbor_data();
+ void toCbor();
+ void fromCbor_data();
+ void fromCbor();
+ void validation_data();
+ void validation();
+ void toDiagnosticNotation_data();
+ void toDiagnosticNotation();
+};
+
+// Get the validation data from TinyCBOR (see src/3rdparty/tinycbor/tests/parser/data.cpp)
+#include "data.cpp"
+
+struct SimpleTypeWrapper
+{
+ // QCborSimpleType is an enum, so QVariant knows how to convert it to
+ // integer and we don't want it to do that.
+ SimpleTypeWrapper(QCborSimpleType type = {}) : st(type) {}
+ QCborSimpleType st;
+};
+Q_DECLARE_METATYPE(SimpleTypeWrapper)
+
+void tst_QCborValue::basics_data()
+{
+ QTest::addColumn<QCborValue::Type>("type");
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<QVariant>("expectedValue");
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUuid uuid = QUuid::createUuid();
+
+ QMetaEnum me = QMetaEnum::fromType<QCborValue::Type>();
+ auto add = [me](QCborValue::Type t, const QCborValue &v, const QVariant &exp) {
+ auto addRow = [=]() -> QTestData & {
+ const char *typeString = me.valueToKey(t);
+ if (t == QCborValue::Integer)
+ return QTest::addRow("Integer:%lld", exp.toLongLong());
+ if (t == QCborValue::Double)
+ return QTest::addRow("Double:%g", exp.toDouble());
+ if (t == QCborValue::ByteArray || t == QCborValue::String)
+ return QTest::addRow("%s:%d", typeString, exp.toString().size());
+ return QTest::newRow(typeString);
+ };
+ addRow() << t << v << exp;
+ };
+ auto st = [](QCborSimpleType t) { return QVariant::fromValue<SimpleTypeWrapper>(t); };
+
+ add(QCborValue::Undefined, QCborValue(), st(QCborSimpleType::Undefined));
+ add(QCborValue::Null, QCborValue::Null, st(QCborSimpleType::Null));
+ QTest::newRow("nullptr") << QCborValue::Null << QCborValue(nullptr)
+ << st(QCborSimpleType::Null);
+ add(QCborValue::False, false, st(QCborSimpleType::False));
+ QTest::newRow("false") << QCborValue::False << QCborValue(QCborValue::False)
+ << st(QCborSimpleType::False);
+ add(QCborValue::True, true, st(QCborSimpleType::True));
+ QTest::newRow("true") << QCborValue::True << QCborValue(QCborValue::True)
+ << st(QCborSimpleType::True);
+ QTest::newRow("simpletype") << QCborValue::Type(QCborValue::SimpleType + 255)
+ << QCborValue(QCborSimpleType(255))
+ << st(QCborSimpleType(255));
+ add(QCborValue::Integer, 0, 0);
+ add(QCborValue::Integer, 1, 1);
+ add(QCborValue::Integer, -1, -1);
+ add(QCborValue::Integer, std::numeric_limits<qint64>::min(), std::numeric_limits<qint64>::min());
+ add(QCborValue::Integer, std::numeric_limits<qint64>::max(), std::numeric_limits<qint64>::max());
+ add(QCborValue::Double, 0., 0.);
+ add(QCborValue::Double, 1.25, 1.25);
+ add(QCborValue::Double, -1.25, -1.25);
+ add(QCborValue::Double, qInf(), qInf());
+ add(QCborValue::Double, -qInf(), -qInf());
+ add(QCborValue::Double, qQNaN(), qQNaN());
+ add(QCborValue::ByteArray, QByteArray("Hello"), QByteArray("Hello"));
+ add(QCborValue::ByteArray, QByteArray(), QByteArray());
+ add(QCborValue::String, "Hello", "Hello");
+ add(QCborValue::String, QLatin1String(), QString());
+ add(QCborValue::DateTime, QCborValue(dt), dt);
+ add(QCborValue::Url, QCborValue(QUrl("http://example.com")), QUrl("http://example.com"));
+ add(QCborValue::RegularExpression, QCborValue(QRegularExpression("^.*$")), QRegularExpression("^.*$"));
+ add(QCborValue::Uuid, QCborValue(uuid), uuid);
+
+ // empty arrays and maps
+ add(QCborValue::Array, QCborArray(), QVariantList());
+ add(QCborValue::Map, QCborMap(), QVariantMap());
+}
+
+static void basicTypeCheck(QCborValue::Type type, const QCborValue &v, const QVariant &expectedValue)
+{
+ bool isSimpleType = (expectedValue.userType() == qMetaTypeId<SimpleTypeWrapper>());
+ QCborSimpleType st = expectedValue.value<SimpleTypeWrapper>().st;
+
+ QCOMPARE(v.type(), type);
+ QCOMPARE(v.isInteger(), type == QCborValue::Integer);
+ QCOMPARE(v.isByteArray(), type == QCborValue::ByteArray);
+ QCOMPARE(v.isString(), type == QCborValue::String);
+ QCOMPARE(v.isArray(), type == QCborValue::Array);
+ QCOMPARE(v.isMap(), type == QCborValue::Map);
+ QCOMPARE(v.isFalse(), type == QCborValue::False);
+ QCOMPARE(v.isTrue(), type == QCborValue::True);
+ QCOMPARE(v.isBool(), type == QCborValue::False || type == QCborValue::True);
+ QCOMPARE(v.isNull(), type == QCborValue::Null);
+ QCOMPARE(v.isUndefined(), type == QCborValue::Undefined);
+ QCOMPARE(v.isDouble(), type == QCborValue::Double);
+ QCOMPARE(v.isDateTime(), type == QCborValue::DateTime);
+ QCOMPARE(v.isUrl(), type == QCborValue::Url);
+ QCOMPARE(v.isUuid(), type == QCborValue::Uuid);
+ QCOMPARE(v.isInvalid(), type == QCborValue::Invalid);
+ QCOMPARE(v.isContainer(), type == QCborValue::Array || type == QCborValue::Map);
+ QCOMPARE(v.isSimpleType(), isSimpleType);
+ QCOMPARE(v.isSimpleType(QCborSimpleType::False), st == QCborSimpleType::False);
+ QCOMPARE(v.isSimpleType(QCborSimpleType::True), st == QCborSimpleType::True);
+ QCOMPARE(v.isSimpleType(QCborSimpleType::Null), st == QCborSimpleType::Null);
+ QCOMPARE(v.isSimpleType(QCborSimpleType::Undefined), st == QCborSimpleType::Undefined);
+ QCOMPARE(v.isSimpleType(QCborSimpleType(255)), st == QCborSimpleType(255));
+
+ if (v.isInteger()) {
+ QCOMPARE(v.toInteger(), expectedValue.toLongLong());
+ QCOMPARE(v.toDouble(), 0. + expectedValue.toLongLong());
+ } else {
+ QCOMPARE(v.toInteger(), qint64(expectedValue.toDouble()));
+ QCOMPARE(v.toDouble(), expectedValue.toDouble());
+ }
+ QCOMPARE(v.toBool(true), st != QCborSimpleType::False);
+ QCOMPARE(v.toBool(), st == QCborSimpleType::True);
+ if (st == QCborSimpleType::Undefined)
+ QCOMPARE(v.toSimpleType(QCborSimpleType::Null), QCborSimpleType::Undefined);
+ else if (isSimpleType)
+ QCOMPARE(v.toSimpleType(), st);
+ else
+ QCOMPARE(v.toSimpleType(), QCborSimpleType::Undefined);
+
+#define CMP(expr, T, validexpr) \
+ if (expectedValue.userType() == qMetaTypeId<T>()) \
+ QCOMPARE(expr, expectedValue.value<T>()); \
+ else \
+ QVERIFY(validexpr)
+ CMP(v.toByteArray(), QByteArray, v.toByteArray().isNull());
+ CMP(v.toString(), QString, v.toString().isNull());
+ CMP(v.toDateTime(), QDateTime, !v.toDateTime().isValid());
+ CMP(v.toUrl(), QUrl, !v.toUrl().isValid());
+ CMP(v.toRegularExpression(), QRegularExpression, v.toRegularExpression().pattern().isNull());
+ CMP(v.toUuid(), QUuid, v.toUuid().isNull());
+#undef CMP
+
+ QVERIFY(v.toArray().isEmpty());
+ QVERIFY(v.toMap().isEmpty());
+
+ QVERIFY(v["Hello"].isUndefined());
+ QVERIFY(v[0].isUndefined());
+}
+
+void tst_QCborValue::basics()
+{
+ QFETCH(QCborValue::Type, type);
+ QFETCH(QCborValue, v);
+ QFETCH(QVariant, expectedValue);
+
+ basicTypeCheck(type, v, expectedValue);
+}
+
+void tst_QCborValue::tagged()
+{
+ QFETCH(QCborValue::Type, type);
+ QFETCH(QCborValue, v);
+ QFETCH(QVariant, expectedValue);
+
+ // make it tagged
+ QCborValue tagged(QCborKnownTags::Signature, v);
+ QVERIFY(tagged.isTag());
+ QCOMPARE(tagged.tag(), QCborTag(QCborKnownTags::Signature));
+
+ // shouldn't compare equal
+ QVERIFY(tagged != v);
+ QVERIFY(v != tagged);
+
+ // ensure we can reach the original value
+ basicTypeCheck(type, tagged.taggedValue(), expectedValue);
+ QVERIFY(tagged.taggedValue() == v);
+ QVERIFY(v == tagged.taggedValue());
+
+ // nested tagging should work too
+ QCborValue tagged2(QCborKnownTags::EncodedCbor, tagged);
+ QVERIFY(tagged2.isTag());
+ QCOMPARE(tagged2.tag(), QCborTag(QCborKnownTags::EncodedCbor));
+
+ QVERIFY(tagged2 != tagged);
+ QVERIFY(tagged != tagged2);
+
+ QVERIFY(tagged2.taggedValue() == tagged);
+ QVERIFY(tagged == tagged2.taggedValue());
+ QVERIFY(tagged2.taggedValue().taggedValue() == v);
+ QVERIFY(v == tagged2.taggedValue().taggedValue());
+}
+
+void tst_QCborValue::extendedTypes_data()
+{
+ QTest::addColumn<QCborValue>("extended");
+ QTest::addColumn<QCborValue>("tagged");
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUuid uuid = QUuid::createUuid();
+
+ QTest::newRow("DateTime") << QCborValue(dt)
+ << QCborValue(QCborKnownTags::DateTimeString, dt.toString(Qt::ISODateWithMs));
+ QTest::newRow("Url:Empty") << QCborValue(QUrl())
+ << QCborValue(QCborKnownTags::Url, QString());
+ QTest::newRow("Url:Authority") << QCborValue(QUrl("https://example.com"))
+ << QCborValue(QCborKnownTags::Url, "https://example.com");
+ QTest::newRow("Url:Path") << QCborValue(QUrl("file:///tmp/none"))
+ << QCborValue(QCborKnownTags::Url, "file:///tmp/none");
+ QTest::newRow("Url:QueryFragment") << QCborValue(QUrl("whatever:?a=b&c=d#e"))
+ << QCborValue(QCborKnownTags::Url, "whatever:?a=b&c=d#e");
+ QTest::newRow("Regex:Empty") << QCborValue(QRegularExpression())
+ << QCborValue(QCborKnownTags::RegularExpression, QString());
+ QTest::newRow("Regex") << QCborValue(QRegularExpression("^.*$"))
+ << QCborValue(QCborKnownTags::RegularExpression, QString("^.*$"));
+ QTest::newRow("Uuid") << QCborValue(uuid)
+ << QCborValue(QCborKnownTags::Uuid, uuid.toRfc4122());
+}
+
+void tst_QCborValue::extendedTypes()
+{
+ QFETCH(QCborValue, extended);
+ QFETCH(QCborValue, tagged);
+ QVERIFY(extended.isTag());
+ QVERIFY(tagged.isTag());
+ QVERIFY(extended == tagged);
+ QVERIFY(tagged == extended);
+
+ QCOMPARE(extended.tag(), tagged.tag());
+ QCOMPARE(extended.taggedValue(), tagged.taggedValue());
+}
+
+void tst_QCborValue::copyCompare()
+{
+ QFETCH(QCborValue, v);
+ QCborValue other = v;
+ other = v;
+ v = other;
+
+ QCOMPARE(v.compare(other), 0);
+ QCOMPARE(v, other);
+ QVERIFY(!(v != other));
+ QVERIFY(!(v < other));
+#if 0 && QT_HAS_INCLUDE(<compare>)
+ QVERIFY(v <= other);
+ QVERIFY(v >= other);
+ QVERIFY(!(v > other));
+#endif
+
+ if (v.isUndefined())
+ other = nullptr;
+ else
+ other = {};
+ QVERIFY(v.type() != other.type());
+ QVERIFY(!(v == other));
+ QVERIFY(v != other);
+
+ // they're different types, so they can't compare equal
+ QVERIFY(v.compare(other) != 0);
+ QVERIFY((v < other) || (other < v));
+}
+
+void tst_QCborValue::arrayDefaultInitialization()
+{
+ QCborArray a;
+ QVERIFY(a.isEmpty());
+ QCOMPARE(a.size(), 0);
+ QVERIFY(!a.contains(0));
+ QVERIFY(!a.contains(-1));
+ QVERIFY(!a.contains(false));
+ QVERIFY(!a.contains(true));
+ QVERIFY(!a.contains(nullptr));
+ QVERIFY(!a.contains({}));
+ QVERIFY(!a.contains(1.0));
+ QVERIFY(!a.contains(QByteArray("Hello")));
+ QVERIFY(!a.contains("Hello"));
+ QVERIFY(!a.contains(QCborArray()));
+ QVERIFY(!a.contains(QCborMap()));
+ QVERIFY(!a.contains(QCborValue(QDateTime::currentDateTimeUtc())));
+ QVERIFY(!a.contains(QCborValue(QUrl("http://example.com"))));
+ QVERIFY(!a.contains(QCborValue(QUuid::createUuid())));
+
+ QVERIFY(a.at(0).isUndefined());
+ QCOMPARE(a.constBegin(), a.constEnd());
+
+ QVERIFY(a == a);
+ QVERIFY(a == QCborArray());
+ QVERIFY(QCborArray() == a);
+
+ QCborValue v(a);
+ QVERIFY(v.isArray());
+ QVERIFY(!v.isMap());
+ QVERIFY(!v.isTag());
+ QVERIFY(v[0].isUndefined());
+
+ QCborArray a2 = v.toArray();
+ QVERIFY(a2.isEmpty());
+ QCOMPARE(a2, a);
+}
+
+void tst_QCborValue::mapDefaultInitialization()
+{
+ QCborMap m;
+ QVERIFY(m.isEmpty());
+ QCOMPARE(m.size(), 0);
+ QVERIFY(m.keys().isEmpty());
+ QVERIFY(!m.contains(0));
+ QVERIFY(!m.contains(-1));
+ QVERIFY(!m.contains(false));
+ QVERIFY(!m.contains(true));
+ QVERIFY(!m.contains(QCborValue::Null));
+ QVERIFY(!m.contains({}));
+ QVERIFY(!m.contains(1.0));
+ QVERIFY(!m.contains(QLatin1String("Hello")));
+ QVERIFY(!m.contains(QStringLiteral("Hello")));
+ QVERIFY(!m.contains(QCborValue(QByteArray("Hello"))));
+ QVERIFY(!m.contains(QCborArray()));
+ QVERIFY(!m.contains(QCborMap()));
+ QVERIFY(!m.contains(QCborValue(QDateTime::currentDateTimeUtc())));
+ QVERIFY(!m.contains(QCborValue(QUrl("http://example.com"))));
+ QVERIFY(!m.contains(QCborValue(QUuid::createUuid())));
+
+ QVERIFY(m.value(0).isUndefined());
+ QVERIFY(m.value(QLatin1String("Hello")).isUndefined());
+ QVERIFY(m.value(QStringLiteral("Hello")).isUndefined());
+ QVERIFY(m.value(QCborValue()).isUndefined());
+#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+ QVERIFY(m.value("Hello").isUndefined());
+#endif
+
+ QVERIFY(m == m);
+ QVERIFY(m == QCborMap{});
+ QVERIFY(QCborMap{} == m);
+
+ QCborValue v(m);
+ QVERIFY(v.isMap());
+ QVERIFY(!v.isArray());
+ QVERIFY(!v.isTag());
+ QVERIFY(v[0].isUndefined());
+ QVERIFY(v[QLatin1String("Hello")].isUndefined());
+ QVERIFY(v["Hello"].isUndefined());
+
+ QCborMap m2 = v.toMap();
+ QVERIFY(m2.isEmpty());
+ QCOMPARE(m2.size(), 0);
+ QCOMPARE(m2, m);
+}
+
+void tst_QCborValue::arrayEmptyInitializerList()
+{
+ QCborArray a{};
+ QVERIFY(a.isEmpty());
+ QCOMPARE(a.size(), 0);
+ QVERIFY(a == a);
+ QVERIFY(a == QCborArray());
+ QVERIFY(QCborArray() == a);
+}
+
+void tst_QCborValue::mapEmptyInitializerList()
+{
+ QCborMap m{};
+ QVERIFY(m.isEmpty());
+ QCOMPARE(m.size(), 0);
+ QVERIFY(m == m);
+ QVERIFY(m == QCborMap{});
+ QVERIFY(QCborMap{} == m);
+}
+
+void tst_QCborValue::arrayEmptyDetach()
+{
+ QCborArray a;
+ QCOMPARE(a.begin(), a.end());
+ QVERIFY(a.isEmpty());
+ QCOMPARE(a.size(), 0);
+
+ QVERIFY(a == a);
+ QVERIFY(a == QCborArray());
+ QVERIFY(QCborArray() == a);
+
+ QCborValue v(a);
+ QVERIFY(v.isArray());
+ QVERIFY(!v.isMap());
+ QVERIFY(!v.isTag());
+
+ QCborArray a2 = v.toArray();
+ QVERIFY(a2.isEmpty());
+ QCOMPARE(a2, a);
+}
+
+void tst_QCborValue::mapEmptyDetach()
+{
+ QCborMap m;
+ QCOMPARE(m.begin(), m.end());
+ QVERIFY(m.isEmpty());
+ QCOMPARE(m.size(), 0);
+
+ QVERIFY(m == m);
+ QVERIFY(m == QCborMap{});
+ QVERIFY(QCborMap{} == m);
+
+ QCborValue v(m);
+ QVERIFY(v.isMap());
+ QVERIFY(!v.isArray());
+ QVERIFY(!v.isTag());
+
+ QCborMap m2 = v.toMap();
+ QVERIFY(m2.isEmpty());
+ QCOMPARE(m2, m);
+}
+
+void tst_QCborValue::arrayInitializerList()
+{
+ QCborArray a{0, -1, false, true, nullptr, {}, 1.0};
+ QVERIFY(!a.isEmpty());
+ QCOMPARE(a.size(), 7);
+ QCOMPARE(a.at(0), QCborValue(0));
+ QCOMPARE(a.at(1), QCborValue(-1));
+ QCOMPARE(a.at(2), QCborValue(QCborValue::False));
+ QCOMPARE(a.at(3), QCborValue(QCborValue::True));
+ QCOMPARE(a.at(4), QCborValue(QCborValue::Null));
+ QCOMPARE(a.at(5), QCborValue(QCborValue::Undefined));
+ QCOMPARE(a.at(6), QCborValue(1.0));
+
+ QVERIFY(a == a);
+ QVERIFY(a != QCborArray{});
+ QVERIFY(QCborArray{} != a);
+ QVERIFY(a == QCborArray({0, -1, false, true, nullptr, {}, 1.0}));
+
+ QCborValue v = a;
+ QCOMPARE(v[0], QCborValue(0));
+ QCOMPARE(v[1], QCborValue(-1));
+ QCOMPARE(v[2], QCborValue(QCborValue::False));
+ QCOMPARE(v[3], QCborValue(QCborValue::True));
+ QCOMPARE(v[4], QCborValue(QCborValue::Null));
+ QCOMPARE(v[5], QCborValue(QCborValue::Undefined));
+ QCOMPARE(v[6], QCborValue(1.0));
+
+ QVERIFY(a.contains(0));
+ QVERIFY(a.contains(-1));
+ QVERIFY(a.contains(false));
+ QVERIFY(a.contains(true));
+ QVERIFY(a.contains(nullptr));
+ QVERIFY(a.contains({}));
+ QVERIFY(a.contains(1.0));
+ QVERIFY(!a.contains(QByteArray("Hello")));
+ QVERIFY(!a.contains("Hello"));
+ QVERIFY(!a.contains(QCborArray()));
+ QVERIFY(!a.contains(QCborMap()));
+ QVERIFY(!a.contains(QCborValue(QDateTime::currentDateTimeUtc())));
+ QVERIFY(!a.contains(QCborValue(QUrl("http://example.com"))));
+ QVERIFY(!a.contains(QCborValue(QUuid::createUuid())));
+
+ // iterators
+ auto it = a.constBegin();
+ auto end = a.constEnd();
+ QCOMPARE(end - it, 7);
+ QCOMPARE(it + 7, end);
+ QVERIFY(it->isInteger());
+ QCOMPARE(*it, QCborValue(0));
+ QCOMPARE(it[1], QCborValue(-1));
+ QCOMPARE(*(it + 2), QCborValue(false));
+ it += 3;
+ QCOMPARE(*it, QCborValue(true));
+ ++it;
+ QCOMPARE(*it, QCborValue(nullptr));
+ it++;
+ QCOMPARE(*it, QCborValue());
+ --end;
+ QCOMPARE(*end, QCborValue(1.0));
+ end--;
+ QCOMPARE(it, end);
+
+ // range for
+ int i = 0;
+ for (const QCborValue &v : qAsConst(a)) {
+ QVERIFY(!v.isInvalid());
+ QCOMPARE(v.isUndefined(), i == 5); // 6th element is Undefined
+ ++i;
+ }
+ QCOMPARE(i, a.size());
+}
+
+void tst_QCborValue::mapSimpleInitializerList()
+{
+ QCborMap m{{0, 0}, {1, 0}, {2, "Hello"}, {"Hello", 2}, {3, QLatin1String("World")}, {QLatin1String("World"), 3}};
+ QCOMPARE(m.size(), 6);
+ QVERIFY(m == m);
+ QVERIFY(m != QCborMap{});
+ QVERIFY(QCborMap{} != m);
+ QVERIFY(m == QCborMap({{0, 0}, {1, 0}, {2, "Hello"}, {"Hello", 2}, {3, QLatin1String("World")}, {QLatin1String("World"), 3}}));
+
+ QCborValue vmap = m;
+ {
+ QVERIFY(m.contains(0));
+ QCborValue v = m.value(0);
+ QVERIFY(v.isInteger());
+ QCOMPARE(v.toInteger(), 0);
+ QCOMPARE(vmap[0], v);
+ }
+ {
+ QVERIFY(m.contains(1));
+ QCborValue v = m.value(1);
+ QVERIFY(v.isInteger());
+ QCOMPARE(v.toInteger(), 0);
+ QCOMPARE(vmap[1], v);
+ }
+ {
+ QVERIFY(m.contains(2));
+ QCborValue v = m.value(2);
+ QVERIFY(v.isString());
+ QCOMPARE(v.toString(), "Hello");
+ QCOMPARE(vmap[2], v);
+ }
+ {
+ QVERIFY(m.contains(3));
+ QCborValue v = m.value(3);
+ QVERIFY(v.isString());
+ QCOMPARE(v.toString(), "World");
+ QCOMPARE(vmap[3], v);
+ }
+ {
+ QVERIFY(m.contains(QStringLiteral("Hello")));
+ QCborValue v = m.value(QLatin1String("Hello"));
+ QVERIFY(v.isInteger());
+ QCOMPARE(v.toInteger(), 2);
+ QCOMPARE(vmap[QStringLiteral("Hello")], v);
+ }
+ {
+ QVERIFY(m.contains(QLatin1String("World")));
+ QCborValue v = m.value(QStringLiteral("World"));
+ QVERIFY(v.isInteger());
+ QCOMPARE(v.toInteger(), 3);
+ QCOMPARE(vmap[QLatin1String("World")], v);
+ }
+
+ QVERIFY(!m.contains(QCborValue::Null));
+ QVERIFY(!m.contains(QCborValue()));
+ QVERIFY(!m.contains(QCborValue(1.0))); // Important: 1.0 does not match 1
+ QVERIFY(!m.contains(QCborValue(QByteArray("Hello"))));
+ QVERIFY(!m.contains(QCborArray()));
+ QVERIFY(!m.contains(QCborMap()));
+ QVERIFY(!m.contains(QCborValue(QDateTime::currentDateTimeUtc())));
+ QVERIFY(!m.contains(QCborValue(QUrl("http://example.com"))));
+ QVERIFY(!m.contains(QCborValue(QUuid::createUuid())));
+
+ // iterators (QCborMap is not sorted)
+ auto it = m.constBegin();
+ auto end = m.constEnd();
+ QCOMPARE(end - it, 6);
+ QCOMPARE(it + 6, end);
+ QCOMPARE(it.key(), QCborValue(0));
+ QCOMPARE(it.value(), QCborValue(0));
+ QVERIFY(it->isInteger());
+ ++it;
+ QCOMPARE(it.key(), QCborValue(1));
+ QCOMPARE(it.value(), QCborValue(0));
+ QCOMPARE((it + 1).key(), QCborValue(2));
+ QVERIFY((it + 1)->isString());
+ QCOMPARE((it + 1)->toString(), "Hello");
+ it += 2;
+ QCOMPARE(it.key(), QCborValue("Hello"));
+ QVERIFY(it->isInteger());
+ it++;
+ QCOMPARE(it.key(), QCborValue(3));
+ QVERIFY(it->isString());
+ QCOMPARE(it.value().toString(), "World");
+ --end;
+ QCOMPARE(end.key(), QCborValue("World"));
+ QCOMPARE(end.value(), QCborValue(3));
+ end--;
+ QCOMPARE(it, end);
+
+ // range for
+ int i = 0;
+ for (auto pair : qAsConst(m)) {
+ QVERIFY(!pair.first.isUndefined());
+ QVERIFY(!pair.second.isUndefined());
+ ++i;
+ }
+ QCOMPARE(i, m.size());
+}
+
+void tst_QCborValue::arrayMutation()
+{
+ QCborArray a{42};
+ {
+ QCborValueRef v = a[0];
+ QVERIFY(!a.isEmpty());
+ QVERIFY(v.isInteger());
+ QCOMPARE(v.toInteger(), 42);
+
+ // now mutate the list
+ v = true;
+ QVERIFY(v.isBool());
+ QVERIFY(v.isTrue());
+ QVERIFY(a.at(0).isTrue());
+ QVERIFY(a.at(0) == v);
+ QVERIFY(v == a.at(0));
+ }
+
+ QVERIFY(a == a);
+ QVERIFY(a == QCborArray{true});
+
+ QCborArray a2 = a;
+ a.append(nullptr);
+ QCOMPARE(a.size(), 2);
+ QCOMPARE(a2.size(), 1);
+
+ // self-insertion
+ a2.append(a2);
+ QCOMPARE(a2.size(), 2);
+ QCOMPARE(a2.last().toArray().size(), 1);
+
+ QCborValueRef v = a[0];
+ QVERIFY(v.isTrue());
+ v = 2.5;
+ QVERIFY(v.isDouble());
+ QVERIFY(a.first().isDouble());
+ QVERIFY(a.last().isNull());
+ QVERIFY(a2.first().isTrue());
+
+ a2 = a;
+ auto it = a.begin(); // detaches again
+ auto end = a.end();
+ QCOMPARE(end - it, 2);
+ QCOMPARE(it + 2, end);
+ QCOMPARE(*it, QCborValue(2.5));
+ QCOMPARE(*++it, QCborValue(nullptr));
+ QVERIFY(a2 == a);
+ QVERIFY(a == a2);
+
+ *it = -1;
+ QCOMPARE(*it, QCborValue(-1));
+ QCOMPARE(a.at(1), QCborValue(-1));
+ QCOMPARE(a2.at(1), QCborValue(nullptr));
+ QCOMPARE(++it, end);
+}
+
+void tst_QCborValue::mapMutation()
+{
+ QCborMap m;
+ QVERIFY(m.isEmpty());
+
+ {
+ QCborValueRef v = m[42];
+ QCOMPARE(m.size(), 1);
+ QVERIFY(v.isUndefined());
+
+ // now mutate the list
+ v = true;
+ QVERIFY(v.isBool());
+ QVERIFY(v.isTrue());
+ QVERIFY(m.begin()->isTrue());
+ QVERIFY(m.begin().value() == v);
+ QVERIFY(v == m.begin().value());
+ }
+
+ QVERIFY(m == QCborMap({{42, true}}));
+ QVERIFY(QCborMap({{42, true}}) == m);
+
+ QCborMap m2 = m;
+ m.insert({nullptr, nullptr});
+ QCOMPARE(m.size(), 2);
+ QCOMPARE(m2.size(), 1);
+
+ QCborValueRef v = m[42];
+ QVERIFY(v.isTrue());
+ v = 2.5;
+ QVERIFY(v.isDouble());
+ QVERIFY(m.begin()->isDouble());
+ QVERIFY((m.end() - 1)->isNull());
+ QVERIFY(m2.begin()->isTrue());
+
+ m2 = m;
+ auto it = m.begin(); // detaches again
+ auto end = m.end();
+ QCOMPARE(end - it, 2);
+ QCOMPARE(it + 2, end);
+ QCOMPARE(it.key(), QCborValue(42));
+ QCOMPARE(it.value(), QCborValue(2.5));
+ QCOMPARE((++it).value(), QCborValue(nullptr));
+ QCOMPARE(it.key(), QCborValue(nullptr));
+ QVERIFY(m2 == m);
+ QVERIFY(m == m2);
+
+ it.value() = -1;
+ QCOMPARE(it.key(), QCborValue(nullptr));
+ QCOMPARE(it.value(), QCborValue(-1));
+ QCOMPARE((m.end() - 1)->toInteger(), -1);
+ QVERIFY((m2.end() - 1)->isNull());
+ QCOMPARE(++it, end);
+}
+
+void tst_QCborValue::arrayPrepend()
+{
+ QCborArray a;
+ a.prepend(0);
+ a.prepend(nullptr);
+ QCOMPARE(a.at(1), QCborValue(0));
+ QCOMPARE(a.at(0), QCborValue(nullptr));
+ QCOMPARE(a.size(), 2);
+}
+
+void tst_QCborValue::arrayInsertRemove()
+{
+ QFETCH(QCborValue, v);
+ QCborArray a;
+ a.append(42);
+ a.append(v);
+ a.insert(1, QCborValue(nullptr));
+ QCOMPARE(a.at(0), QCborValue(42));
+ QCOMPARE(a.at(1), QCborValue(nullptr));
+ QCOMPARE(a.at(2), v);
+
+ // remove 42
+ a.removeAt(0);
+ QCOMPARE(a.size(), 2);
+ QCOMPARE(a.at(0), QCborValue(nullptr));
+ QCOMPARE(a.at(1), v);
+
+ auto it = a.begin();
+ it = a.erase(it); // removes nullptr
+ QCOMPARE(a.size(), 1);
+ QCOMPARE(a.at(0), v);
+
+ it = a.erase(it);
+ QVERIFY(a.isEmpty());
+ QCOMPARE(it, a.end());
+
+ // reinsert the element so we can take it
+ a.append(v);
+ QCOMPARE(a.takeAt(0), v);
+ QVERIFY(a.isEmpty());
+}
+
+void tst_QCborValue::arrayStringElements()
+{
+ QCborArray a{"Hello"};
+ a.append(QByteArray("Hello"));
+ a.append(QLatin1String("World"));
+ QVERIFY(a == a);
+ QVERIFY(a == QCborArray({QLatin1String("Hello"),
+ QByteArray("Hello"), QStringLiteral("World")}));
+
+ QCborValueRef r1 = a[0];
+ QCOMPARE(r1.toString(), "Hello");
+ QCOMPARE(r1.operator QCborValue(), QCborValue("Hello"));
+ QVERIFY(r1 == QCborValue("Hello"));
+
+ QCborValue v2 = a.at(1);
+ QCOMPARE(v2.toByteArray(), QByteArray("Hello"));
+ QCOMPARE(v2, QCborValue(QByteArray("Hello")));
+
+ // v2 must continue to be valid after the entry getting removed
+ a.removeAt(1);
+ QCOMPARE(v2.toByteArray(), QByteArray("Hello"));
+ QCOMPARE(v2, QCborValue(QByteArray("Hello")));
+
+ v2 = a.at(1);
+ QCOMPARE(v2.toString(), "World");
+ QCOMPARE(v2, QCborValue("World"));
+
+ QCOMPARE(a.takeAt(1).toString(), "World");
+ QCOMPARE(a.takeAt(0).toString(), "Hello");
+ QVERIFY(a.isEmpty());
+}
+
+void tst_QCborValue::mapStringValues()
+{
+ QCborMap m{{0, "Hello"}};
+ m.insert({1, QByteArray("Hello")});
+ m.insert({2, QLatin1String("World")});
+ QVERIFY(m == m);
+
+ QCborValueRef r1 = m[0];
+ QCOMPARE(r1.toString(), "Hello");
+ QCOMPARE(r1.operator QCborValue(), QCborValue("Hello"));
+ QVERIFY(r1 == QCborValue("Hello"));
+
+ QCborValue v2 = m.value(1);
+ QCOMPARE(v2.toByteArray(), QByteArray("Hello"));
+ QCOMPARE(v2, QCborValue(QByteArray("Hello")));
+
+ // v2 must continue to be valid after the entry getting removed
+ m.erase(m.constFind(1));
+ QCOMPARE(v2.toByteArray(), QByteArray("Hello"));
+ QCOMPARE(v2, QCborValue(QByteArray("Hello")));
+
+ v2 = (m.begin() + 1).value();
+ QCOMPARE(v2.toString(), "World");
+ QCOMPARE(v2, QCborValue("World"));
+
+ QCOMPARE(m.extract(m.begin() + 1).toString(), "World");
+ QCOMPARE(m.take(0).toString(), "Hello");
+ QVERIFY(m.isEmpty());
+}
+
+void tst_QCborValue::mapStringKeys()
+{
+ QCborMap m{{QLatin1String("Hello"), 1}, {QStringLiteral("World"), 2}};
+ QCOMPARE(m.value(QStringLiteral("Hello")), QCborValue(1));
+ QCOMPARE(m.value(QLatin1String("World")), QCborValue(2));
+
+ QCborMap m2 = m;
+ QVERIFY(m2 == m);
+ QVERIFY(m == m2);
+
+ m.insert({QByteArray("foo"), "bar"});
+ QCOMPARE(m.size(), 3);
+ QCOMPARE(m2.size(), 2);
+ QVERIFY(m2 != m);
+ QVERIFY(m != m2);
+
+ QVERIFY(m2.value(QCborValue(QByteArray("foo"))).isUndefined());
+ QVERIFY(m.value(QCborValue(QLatin1String("foo"))).isUndefined());
+ QCOMPARE(m.value(QCborValue(QByteArray("foo"))).toString(), "bar");
+}
+
+void tst_QCborValue::mapInsertRemove()
+{
+ QFETCH(QCborValue, v);
+ QCborMap m{{1, v}};
+
+ m.remove(1);
+ QVERIFY(m.isEmpty());
+ QVERIFY(!m.contains(1));
+
+ m.insert(2, v);
+ QVERIFY(m.contains(2));
+ QVERIFY(m[2] == v);
+ QVERIFY(v == m[2]);
+
+ auto it = m.find(2);
+ it = m.erase(it);
+ QVERIFY(m.isEmpty());
+
+ // creates m[2] and m[42] just by referencing them
+ m[2];
+ QCborValueRef r = m[42];
+ QCOMPARE(m.size(), 2);
+
+ r = v;
+ it = m.find(42);
+ QVERIFY(it.value() == v);
+ QVERIFY(v == it.value());
+ QVERIFY(it.value() == r);
+ QVERIFY(r == it.value());
+
+ QCOMPARE(m.extract(it), v);
+ QVERIFY(!m.contains(42));
+
+ m[2] = v;
+ QCOMPARE(m.take(2), v);
+ QVERIFY(m.take(2).isUndefined());
+ QVERIFY(m.isEmpty());
+}
+
+void tst_QCborValue::arrayInsertTagged()
+{
+ QFETCH(QCborValue, v);
+
+ // make it tagged
+ QCborValue tagged(QCborKnownTags::Signature, v);
+
+ QCborArray a{tagged};
+ a.insert(1, tagged);
+ QCOMPARE(a.size(), 2);
+ QCOMPARE(a.at(0), tagged);
+ QCOMPARE(a.at(1), tagged);
+ QCOMPARE(a.at(0).taggedValue(), v);
+ QCOMPARE(a.at(1).taggedValue(), v);
+ QCOMPARE(a.takeAt(0).taggedValue(), v);
+ QCOMPARE(a.takeAt(0).taggedValue(), v);
+ QVERIFY(a.isEmpty());
+}
+
+void tst_QCborValue::mapInsertTagged()
+{
+ QFETCH(QCborValue, v);
+
+ // make it tagged
+ QCborValue tagged(QCborKnownTags::Signature, v);
+
+ QCborMap m{{11, tagged}};
+ m.insert({-21, tagged});
+ QCOMPARE(m.size(), 2);
+ QCOMPARE(m.constBegin().value(), tagged);
+ QCOMPARE(m.value(-21), tagged);
+ QCOMPARE(m.value(11).taggedValue(), v);
+ QCOMPARE((m.end() - 1).value().taggedValue(), v);
+ QCOMPARE(m.extract(m.end() - 1).taggedValue(), v);
+ QVERIFY(!m.contains(-21));
+ QCOMPARE(m.take(11).taggedValue(), v);
+ QVERIFY(m.isEmpty());
+}
+
+void tst_QCborValue::arraySelfAssign()
+{
+ QFETCH(QCborValue, v);
+ QCborArray a;
+
+ a = {v};
+
+ // Test 1: QCborValue created first, so
+ // QCborArray::insert() detaches
+ {
+ a.append(a);
+ QCOMPARE(a.size(), 2);
+ QCOMPARE(a.last().toArray().size(), 1);
+ }
+
+ a = {v};
+
+ // Test 2: QCborValueRef created first
+ {
+ a.append(36);
+ auto it = a.end() - 1;
+ *it = a;
+
+ QCOMPARE(a.size(), 2);
+ QCOMPARE(it->toArray().size(), 2);
+ QCOMPARE(it->toArray().last(), QCborValue(36));
+ }
+}
+
+void tst_QCborValue::mapSelfAssign()
+{
+ QFETCH(QCborValue, v);
+ QCborMap m;
+
+ m = {{0, v}};
+ QCOMPARE(m.size(), 1);
+
+ // Test 1: create a QCborValue first
+ // in this case, QCborMap::operator[] detaches first
+ {
+ QCborValue vm = m;
+ m[1] = vm; // self-assign
+ QCOMPARE(m.size(), 2);
+ QCOMPARE(m.value(0), v);
+
+ QCborMap m2 = m.value(1).toMap();
+ // there mustn't be an element with key 1
+ QCOMPARE(m2.size(), 1);
+ QCOMPARE(m2.value(0), v);
+ QVERIFY(!m2.contains(1));
+ }
+
+ m = {{0, v}};
+
+ // Test 2: create the QCborValueRef first
+ // in this case, there's no opportunity to detach
+ {
+ QCborValueRef rv = m[1];
+ rv = m; // self-assign (implicit QCborValue creation)
+ QCOMPARE(m.size(), 2);
+ QCOMPARE(m.value(0), v);
+
+ QCborMap m2 = m.value(1).toMap();
+ // there must be an element with key 1
+ QCOMPARE(m2.size(), 2);
+ QCOMPARE(m2.value(0), v);
+ QVERIFY(m2.contains(1));
+ QCOMPARE(m2.value(1), QCborValue());
+ }
+
+ m = {{0, v}};
+
+ // Test 3: don't force creation of either before
+ // in this case, it's up to the compiler to choose
+ {
+ m[1] = m; // self-assign
+ QCOMPARE(m.size(), 2);
+
+ QCborMap m2 = m.value(1).toMap();
+ QVERIFY(m2.size() == 1 || m2.size() == 2);
+ }
+
+ m = {{0, v}};
+
+ // Test 4: self-assign as key
+ // in this scase, QCborMap::operator[] must detach
+ {
+ m[m] = v;
+ QCOMPARE(m.size(), 2);
+
+ auto it = m.constEnd() - 1;
+ QCOMPARE(it.value(), v);
+ QCOMPARE(it.key(), QCborMap({{0, v}}));
+ }
+}
+
+void tst_QCborValue::mapComplexKeys()
+{
+ QFETCH(QCborValue, v);
+ QCborValue tagged(QCborKnownTags::Signature, v);
+
+ QCborMap m{{42, true}, {v, 42}, {-3, nullptr}};
+ QCOMPARE(m.size(), 3);
+ QVERIFY(m.contains(42));
+ QVERIFY(m.contains(-3));
+ QVERIFY(m.contains(v));
+ QVERIFY(!m.contains(tagged));
+
+ auto it = m.constFind(v);
+ QVERIFY(it != m.constEnd());
+ QVERIFY(it.key() == v);
+ QVERIFY(v == it.key());
+ QCOMPARE(it.value().toInteger(), 42);
+
+ QCborArray a{0, 1, 2, 3, v};
+ m[a] = 1;
+ QCOMPARE(m.size(), 4);
+ QCOMPARE((m.constEnd() - 1).value(), QCborValue(1));
+ if (v != QCborValue(QCborValue::Array))
+ QVERIFY(!m.contains(QCborArray{}));
+ QVERIFY(!m.contains(QCborArray{0}));
+ QVERIFY(!m.contains(QCborArray{0, 1}));
+ QVERIFY(!m.contains(QCborArray{0, 1, 2}));
+ QVERIFY(!m.contains(QCborArray{0, 1, 2, 4}));
+ QVERIFY(!m.contains(QCborArray{0, 1, 2, 3, v, 4}));
+
+ it = m.constFind(QCborArray{0, 1, 2, 3, v});
+ QVERIFY(it != m.constEnd());
+ QCOMPARE(it.key(), a);
+ QCOMPARE(it.value(), QCborValue(1));
+
+ m[m] = 1; // assign itself as a key -- this necessarily detaches before
+ QCOMPARE(m.size(), 5);
+ QCOMPARE((m.end() - 1).value(), 1);
+ QCOMPARE((m.end() - 1).key().toMap().size(), 4);
+
+ QCborValue mv(m);
+ if (v.isInteger()) {
+ // we should be able to find using the overloads too
+ QCOMPARE(m[v.toInteger()].toInteger(), 42);
+ QCOMPARE(mv[v.toInteger()].toInteger(), 42);
+ } else if (v.isString()) {
+ // ditto
+ QCOMPARE(m[v.toString()].toInteger(), 42);
+ QCOMPARE(mv[v.toString()].toInteger(), 42);
+
+ // basics_data() strings are Latin1
+ QByteArray latin1 = v.toString().toLatin1();
+ Q_ASSERT(v.toString() == QString::fromLatin1(latin1));
+ QCOMPARE(m[QLatin1String(latin1)].toInteger(), 42);
+ }
+
+ m.remove(v);
+ QVERIFY(!m.contains(v));
+ QVERIFY(!m.contains(tagged));
+
+ QCborValueRef r = m[tagged];
+ QVERIFY(!m.contains(v));
+ QVERIFY(m.contains(tagged));
+ r = 47;
+ QCOMPARE(m[tagged].toInteger(), 47);
+ QCOMPARE(m.take(tagged).toInteger(), 47);
+ QVERIFY(!m.contains(tagged));
+}
+
+void tst_QCborValue::sorting()
+{
+ QCborValue vundef, vnull(nullptr);
+ QCborValue vtrue(true), vfalse(false);
+ QCborValue vint1(1), vint2(2);
+ QCborValue vneg1(-1), vneg2(-2);
+ QCborValue vba2(QByteArray("Hello")), vba3(QByteArray("World")), vba1(QByteArray("foo"));
+ QCborValue vs2("Hello"), vs3("World"), vs1("foo");
+ QCborValue va1(QCborValue::Array), va2(QCborArray{1}), va3(QCborArray{0, 0});
+ QCborValue vm1(QCborValue::Map), vm2(QCborMap{{1, 0}}), vm3(QCborMap{{0, 0}, {1, 0}});
+ QCborValue vdt1(QDateTime::fromMSecsSinceEpoch(0, Qt::UTC)), vdt2(QDateTime::currentDateTimeUtc());
+ QCborValue vtagged1(QCborKnownTags::UnixTime_t, 0), vtagged2(QCborKnownTags::UnixTime_t, 0.0),
+ vtagged3(QCborKnownTags::Signature, 0), vtagged4(QCborTag(-2), 0), vtagged5(QCborTag(-1), 0);
+ QCborValue vurl1(QUrl("https://example.net")), vurl2(QUrl("https://example.com/"));
+ QCborValue vuuid1{QUuid()}, vuuid2(QUuid::createUuid());
+ QCborValue vsimple1(QCborSimpleType(1)), vsimple32(QCborSimpleType(32)), vsimple255(QCborSimpleType(255));
+ QCborValue vdouble1(1.5), vdouble2(qInf());
+ QCborValue vndouble1(-1.5), vndouble2(-qInf());
+
+#define CHECK_ORDER(v1, v2) \
+ QVERIFY(v1 < v2); \
+ QVERIFY(!(v2 < v2))
+
+ // intra-type comparisons
+ CHECK_ORDER(vfalse, vtrue);
+ CHECK_ORDER(vsimple1, vsimple32);
+ CHECK_ORDER(vsimple32, vsimple255);
+ CHECK_ORDER(vint1, vint2);
+ CHECK_ORDER(vdouble1, vdouble2);
+ CHECK_ORDER(vndouble1, vndouble2);
+ // note: shorter length sorts first
+ CHECK_ORDER(vba1, vba2);
+ CHECK_ORDER(vba2, vba3);
+ CHECK_ORDER(vs1, vs2);
+ CHECK_ORDER(vs2, vs3);
+ CHECK_ORDER(va1, va2);
+ CHECK_ORDER(va2, va3);
+ CHECK_ORDER(vm1, vm2);
+ CHECK_ORDER(vm2, vm3);
+ CHECK_ORDER(vdt1, vdt2);
+ CHECK_ORDER(vtagged1, vtagged2);
+ CHECK_ORDER(vtagged2, vtagged3);
+ CHECK_ORDER(vtagged3, vtagged4);
+ CHECK_ORDER(vtagged4, vtagged5);
+ CHECK_ORDER(vurl1, vurl2);
+ CHECK_ORDER(vuuid1, vuuid2);
+
+ // surprise 1: CBOR sorts integrals by absolute value
+ CHECK_ORDER(vneg1, vneg2);
+
+ // surprise 2: CBOR sorts negatives after positives (sign+magnitude)
+ CHECK_ORDER(vint2, vneg1);
+ QVERIFY(vint2.toInteger() > vneg1.toInteger());
+ CHECK_ORDER(vdouble2, vndouble1);
+ QVERIFY(vdouble2.toDouble() > vndouble1.toDouble());
+
+ // inter-type comparisons
+ CHECK_ORDER(vneg2, vba1);
+ CHECK_ORDER(vba3, vs1);
+ CHECK_ORDER(vs3, va1);
+ CHECK_ORDER(va2, vm1);
+ CHECK_ORDER(vm2, vdt1);
+ CHECK_ORDER(vdt2, vtagged1);
+ CHECK_ORDER(vtagged2, vurl1);
+ CHECK_ORDER(vurl1, vuuid1);
+ CHECK_ORDER(vuuid2, vtagged3);
+ CHECK_ORDER(vtagged4, vsimple1);
+ CHECK_ORDER(vsimple1, vfalse);
+ CHECK_ORDER(vtrue, vnull);
+ CHECK_ORDER(vnull, vundef);
+ CHECK_ORDER(vundef, vsimple32);
+ CHECK_ORDER(vsimple255, vdouble1);
+
+ // which shows all doubles sorted after integrals
+ CHECK_ORDER(vint2, vdouble1);
+ QVERIFY(vint2.toInteger() > vdouble1.toDouble());
+#undef CHECK_ORDER
+}
+
+static void addCommonCborData()
+{
+ // valid for both decoding and encoding
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<QByteArray>("result");
+ QTest::addColumn<QCborValue::EncodingOptions>("options");
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUuid uuid = QUuid::createUuid();
+ QCborValue::EncodingOptions noxfrm = QCborValue::NoTransformation;
+
+ // integrals
+ QTest::newRow("Integer:0") << QCborValue(0) << raw("\x00") << noxfrm;
+ QTest::newRow("Integer:1") << QCborValue(1) << raw("\x01") << noxfrm;
+ QTest::newRow("Integer:-1") << QCborValue(-1) << raw("\x20") << noxfrm;
+ QTest::newRow("Integer:INT64_MAX") << QCborValue(std::numeric_limits<qint64>::max())
+ << raw("\x1b\x7f\xff\xff\xff""\xff\xff\xff\xff")
+ << noxfrm;
+ QTest::newRow("Integer:INT64_MIN") << QCborValue(std::numeric_limits<qint64>::min())
+ << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff")
+ << noxfrm;
+
+ QTest::newRow("simple0") << QCborValue(QCborValue::SimpleType) << raw("\xe0") << noxfrm;
+ QTest::newRow("simple1") << QCborValue(QCborSimpleType(1)) << raw("\xe1") << noxfrm;
+ QTest::newRow("simple255") << QCborValue(QCborSimpleType(255)) << raw("\xf8\xff") << noxfrm;
+ QTest::newRow("Undefined") << QCborValue() << raw("\xf7") << noxfrm;
+ QTest::newRow("Null") << QCborValue(nullptr) << raw("\xf6") << noxfrm;
+ QTest::newRow("True") << QCborValue(true) << raw("\xf5") << noxfrm;
+ QTest::newRow("False") << QCborValue(false) << raw("\xf4") << noxfrm;
+ QTest::newRow("simple32") << QCborValue(QCborSimpleType(32)) << raw("\xf8\x20") << noxfrm;
+ QTest::newRow("simple255") << QCborValue(QCborSimpleType(255)) << raw("\xf8\xff") << noxfrm;
+
+ QTest::newRow("Double:0") << QCborValue(0.) << raw("\xfb\0\0\0\0""\0\0\0\0") << noxfrm;
+ QTest::newRow("Double:1.5") << QCborValue(1.5) << raw("\xfb\x3f\xf8\0\0""\0\0\0\0") << noxfrm;
+ QTest::newRow("Double:-1.5") << QCborValue(-1.5) << raw("\xfb\xbf\xf8\0\0""\0\0\0\0") << noxfrm;
+ QTest::newRow("Double:INT64_MAX+1") << QCborValue(std::numeric_limits<qint64>::max() + 1.)
+ << raw("\xfb\x43\xe0\0\0""\0\0\0\0") << noxfrm;
+ QTest::newRow("Double:maxintegralfp") << QCborValue(18446744073709551616.0 - 2048)
+ << raw("\xfb\x43\xef\xff\xff""\xff\xff\xff\xff")
+ << noxfrm;
+ QTest::newRow("Double:minintegralfp") << QCborValue(-18446744073709551616.0 + 2048)
+ << raw("\xfb\xc3\xef\xff\xff""\xff\xff\xff\xff")
+ << noxfrm;
+ QTest::newRow("Double:inf") << QCborValue(qInf()) << raw("\xfb\x7f\xf0\0\0""\0\0\0\0") << noxfrm;
+ QTest::newRow("Double:-inf") << QCborValue(-qInf()) << raw("\xfb\xff\xf0\0""\0\0\0\0\0") << noxfrm;
+ QTest::newRow("Double:nan") << QCborValue(qQNaN()) << raw("\xfb\x7f\xf8\0\0""\0\0\0\0") << noxfrm;
+
+ QTest::newRow("Float:0") << QCborValue(0.) << raw("\xfa\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+ QTest::newRow("Float:1.5") << QCborValue(1.5) << raw("\xfa\x3f\xc0\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+ QTest::newRow("Float:-1.5") << QCborValue(-1.5) << raw("\xfa\xbf\xc0\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+ QTest::newRow("Float:inf") << QCborValue(qInf()) << raw("\xfa\x7f\x80\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+ QTest::newRow("Float:-inf") << QCborValue(-qInf()) << raw("\xfa\xff\x80\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+ QTest::newRow("Float:nan") << QCborValue(qQNaN()) << raw("\xfa\x7f\xc0\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+
+ QTest::newRow("Float16:0") << QCborValue(0.) << raw("\xf9\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+ QTest::newRow("Float16:1.5") << QCborValue(1.5) << raw("\xf9\x3e\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+ QTest::newRow("Float16:-1.5") << QCborValue(-1.5) << raw("\xf9\xbe\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+ QTest::newRow("Float16:inf") << QCborValue(qInf()) << raw("\xf9\x7c\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+ QTest::newRow("Float16:-inf") << QCborValue(-qInf()) << raw("\xf9\xfc\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+ QTest::newRow("Float16:nan") << QCborValue(qQNaN()) << raw("\xf9\x7e\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+
+ // out of range of qint64, but in range for CBOR, so these do get converted
+ // to integrals on write and back to double on read
+ QTest::newRow("UseInteger:INT64_MAX+1") << QCborValue(std::numeric_limits<qint64>::max() + 1.)
+ << raw("\x1b\x80\0\0\0""\0\0\0\0")
+ << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:maxintegralfp") << QCborValue(18446744073709551616.0 - 2048)
+ << raw("\x1b\xff\xff\xff\xff""\xff\xff\xf8\0")
+ << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:minintegralfp") << QCborValue(-18446744073709551616.0 + 2048)
+ << raw("\x3b\xff\xff\xff\xff""\xff\xff\xf7\xff")
+ << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+
+ QTest::newRow("ByteArray:Empty") << QCborValue(QByteArray()) << raw("\x40") << noxfrm;
+ QTest::newRow("ByteArray") << QCborValue(QByteArray("Hello")) << raw("\x45Hello") << noxfrm;
+ QTest::newRow("ByteArray:WithNull") << QCborValue(raw("\0\1\2\xff")) << raw("\x44\0\1\2\xff") << noxfrm;
+
+ QTest::newRow("String:Empty") << QCborValue(QString()) << raw("\x60") << noxfrm;
+ QTest::newRow("String:UsAscii") << QCborValue("Hello") << raw("\x65Hello") << noxfrm;
+ QTest::newRow("String:Latin1") << QCborValue(QLatin1String("R\xe9sum\xe9"))
+ << raw("\x68R\xc3\xa9sum\xc3\xa9") << noxfrm;
+ QTest::newRow("String:Unicode") << QCborValue(QStringLiteral(u"éś α €"))
+ << raw("\x6b\xc3\xa9\xc5\x9b \xce\xb1 \xe2\x82\xac") << noxfrm;
+
+ QTest::newRow("DateTime") << QCborValue(dt) // this is UTC
+ << "\xc0\x78\x18" + dt.toString(Qt::ISODateWithMs).toLatin1()
+ << noxfrm;
+ QTest::newRow("DateTime-UTC") << QCborValue(QDateTime({2018, 1, 1}, {9, 0, 0}, Qt::UTC))
+ << raw("\xc0\x78\x18" "2018-01-01T09:00:00.000Z")
+ << noxfrm;
+ QTest::newRow("DateTime-Local") << QCborValue(QDateTime({2018, 1, 1}, {9, 0, 0}, Qt::LocalTime))
+ << raw("\xc0\x77" "2018-01-01T09:00:00.000")
+ << noxfrm;
+ QTest::newRow("DateTime+01:00") << QCborValue(QDateTime({2018, 1, 1}, {9, 0, 0}, Qt::OffsetFromUTC, 3600))
+ << raw("\xc0\x78\x1d" "2018-01-01T09:00:00.000+01:00")
+ << noxfrm;
+ QTest::newRow("Url:Empty") << QCborValue(QUrl()) << raw("\xd8\x20\x60") << noxfrm;
+ QTest::newRow("Url") << QCborValue(QUrl("HTTPS://example.com/{%30%31}?q=%3Ca+b%20%C2%A9%3E&%26"))
+ << raw("\xd8\x20\x78\x27" "https://example.com/{01}?q=<a+b \xC2\xA9>&%26")
+ << noxfrm;
+ QTest::newRow("Regex:Empty") << QCborValue(QRegularExpression()) << raw("\xd8\x23\x60") << noxfrm;
+ QTest::newRow("Regex") << QCborValue(QRegularExpression("^.*$"))
+ << raw("\xd8\x23\x64" "^.*$") << noxfrm;
+ QTest::newRow("Uuid") << QCborValue(uuid) << raw("\xd8\x25\x50") + uuid.toRfc4122() << noxfrm;
+
+ // empty arrays and maps
+ QTest::newRow("Array") << QCborValue(QCborArray()) << raw("\x80") << noxfrm;
+ QTest::newRow("Map") << QCborValue(QCborMap()) << raw("\xa0") << noxfrm;
+
+ QTest::newRow("Tagged:ByteArray") << QCborValue(QCborKnownTags::PositiveBignum, raw("\1\0\0\0\0""\0\0\0\0"))
+ << raw("\xc2\x49\1\0\0\0\0""\0\0\0\0") << noxfrm;
+ QTest::newRow("Tagged:Array") << QCborValue(QCborKnownTags::Decimal, QCborArray{-2, 27315})
+ << raw("\xc4\x82\x21\x19\x6a\xb3") << noxfrm;
+}
+
+void tst_QCborValue::toCbor_data()
+{
+ addCommonCborData();
+
+ // The rest of these tests are conversions whose decoding does not yield
+ // back the same QCborValue.
+
+ // Signalling NaN get normalized to quiet ones
+ QTest::newRow("Double:snan") << QCborValue(qSNaN()) << raw("\xfb\x7f\xf8\0""\0\0\0\0\0") << QCborValue::EncodingOptions();
+ QTest::newRow("Float:snan") << QCborValue(qSNaN()) << raw("\xfa\x7f\xc0\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+ QTest::newRow("Float16:snan") << QCborValue(qSNaN()) << raw("\xf9\x7e\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+
+ // Floating point written as integers are read back as integers
+ QTest::newRow("UseInteger:0") << QCborValue(0.) << raw("\x00") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:1") << QCborValue(1.) << raw("\x01") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:-1") << QCborValue(-1.) << raw("\x20") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:INT64_MIN") << QCborValue(std::numeric_limits<qint64>::min() + 0.)
+ << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff")
+ << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+
+ // but obviously non-integral or out of range floating point stay FP
+ QTest::newRow("UseInteger:1.5") << QCborValue(1.5) << raw("\xfb\x3f\xf8\0\0""\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:-1.5") << QCborValue(-1.5) << raw("\xfb\xbf\xf8\0\0""\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:inf") << QCborValue(qInf()) << raw("\xfb\x7f\xf0\0\0""\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:-inf") << QCborValue(-qInf()) << raw("\xfb\xff\xf0\0""\0\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:nan") << QCborValue(qQNaN()) << raw("\xfb\x7f\xf8\0\0""\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:2^64") << QCborValue(18446744073709551616.0) << raw("\xfb\x43\xf0\0\0""\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:-2^65") << QCborValue(-2 * 18446744073709551616.0) << raw("\xfb\xc4\0\0\0""\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+}
+
+void tst_QCborValue::toCbor()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QByteArray, result);
+ QFETCH(QCborValue::EncodingOptions, options);
+
+ QCOMPARE(v.toCbor(options), result);
+
+ // in maps and arrays
+ QCOMPARE(QCborArray{v}.toCborValue().toCbor(options), "\x81" + result);
+ QCOMPARE(QCborArray({v, v}).toCborValue().toCbor(options),
+ "\x82" + result + result);
+ QCOMPARE(QCborMap({{1, v}}).toCborValue().toCbor(options),
+ "\xa1\x01" + result);
+
+ // tagged
+ QCborValue t(QCborKnownTags::Signature, v);
+ QCOMPARE(t.toCbor(options), "\xd9\xd9\xf7" + result);
+ QCOMPARE(QCborArray({t, t}).toCborValue().toCbor(options),
+ "\x82\xd9\xd9\xf7" + result + "\xd9\xd9\xf7" + result);
+ QCOMPARE(QCborMap({{1, t}}).toCborValue().toCbor(options),
+ "\xa1\x01\xd9\xd9\xf7" + result);
+}
+
+void tst_QCborValue::fromCbor_data()
+{
+ addCommonCborData();
+
+ // chunked strings
+ QTest::newRow("ByteArray:Chunked") << QCborValue(QByteArray("Hello"))
+ << raw("\x5f\x43Hel\x42lo\xff");
+ QTest::newRow("ByteArray:Chunked:Empty") << QCborValue(QByteArray()) << raw("\x5f\xff");
+ QTest::newRow("String:Chunked") << QCborValue("Hello")
+ << raw("\x7f\x63Hel\x62lo\xff");
+ QTest::newRow("String:Chunked:Empty") << QCborValue(QString())
+ << raw("\x7f\xff");
+
+ QTest::newRow("DateTime:NoMilli") << QCborValue(QDateTime::fromSecsSinceEpoch(1515565477, Qt::UTC))
+ << raw("\xc0\x74" "2018-01-10T06:24:37Z");
+ QTest::newRow("UnixTime_t:Integer") << QCborValue(QDateTime::fromSecsSinceEpoch(1515565477, Qt::UTC))
+ << raw("\xc1\x1a\x5a\x55\xb1\xa5");
+ QTest::newRow("UnixTime_t:Double") << QCborValue(QDateTime::fromMSecsSinceEpoch(1515565477125, Qt::UTC))
+ << raw("\xc1\xfb\x41\xd6\x95\x6c""\x69\x48\x00\x00");
+
+ QTest::newRow("Url:NotNormalized") << QCborValue(QUrl("https://example.com/\xc2\xa9 "))
+ << raw("\xd8\x20\x78\x1dHTTPS://EXAMPLE.COM/%c2%a9%20");
+
+ QTest::newRow("Uuid:Zero") << QCborValue(QUuid()) << raw("\xd8\x25\x40");
+ QTest::newRow("Uuid:TooShort") << QCborValue(QUuid::fromRfc4122(raw("\1\2\3\4""\4\3\2\0""\0\0\0\0""\0\0\0\0")))
+ << raw("\xd8\x25\x47" "\1\2\3\4\4\3\2");
+ QTest::newRow("Uuid:TooLong") << QCborValue(QUuid::fromRfc4122(raw("\1\2\3\4""\4\3\2\0""\0\0\0\0""\0\0\0\1")))
+ << raw("\xd8\x25\x51" "\1\2\3\4""\4\3\2\0""\0\0\0\0""\0\0\0\1""\2");
+}
+
+void tst_QCborValue::fromCbor()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QByteArray, result);
+
+ auto doCheck = [](const QCborValue &v, const QByteArray &result) {
+ QCborParserError error;
+ QCborValue decoded = QCborValue::fromCbor(result, &error);
+ QVERIFY2(error.error == QCborError(), qPrintable(error.errorString()));
+ QCOMPARE(error.offset, result.size());
+ QVERIFY(decoded == v);
+ QVERIFY(v == decoded);
+ };
+
+ doCheck(v, result);
+ if (QTest::currentTestFailed())
+ return;
+
+ // in an array
+ doCheck(QCborArray{v}, "\x81" + result);
+ if (QTest::currentTestFailed())
+ return;
+
+ doCheck(QCborArray{v, v}, "\x82" + result + result);
+ if (QTest::currentTestFailed())
+ return;
+
+ // in a map
+ doCheck(QCborMap{{1, v}}, "\xa1\1" + result);
+ if (QTest::currentTestFailed())
+ return;
+
+ // undefined-length arrays and maps
+ doCheck(QCborArray{v}, "\x9f" + result + "\xff");
+ if (QTest::currentTestFailed())
+ return;
+ doCheck(QCborArray{v, v}, "\x9f" + result + result + "\xff");
+ if (QTest::currentTestFailed())
+ return;
+ doCheck(QCborMap{{1, v}}, "\xbf\1" + result + "\xff");
+ if (QTest::currentTestFailed())
+ return;
+
+ // tagged
+ QCborValue t(QCborKnownTags::Signature, v);
+ doCheck(t, "\xd9\xd9\xf7" + result);
+ if (QTest::currentTestFailed())
+ return;
+
+ // in an array
+ doCheck(QCborArray{t}, "\x81\xd9\xd9\xf7" + result);
+ if (QTest::currentTestFailed())
+ return;
+
+ doCheck(QCborArray{t, t}, "\x82\xd9\xd9\xf7" + result + "\xd9\xd9\xf7" + result);
+ if (QTest::currentTestFailed())
+ return;
+
+ // in a map
+ doCheck(QCborMap{{1, t}}, "\xa1\1\xd9\xd9\xf7" + result);
+ if (QTest::currentTestFailed())
+ return;
+}
+
+void tst_QCborValue::validation_data()
+{
+ addValidationColumns();
+ addValidationData();
+
+ // These tests say we have arrays and maps with very large item counts.
+ // They are meant to ensure we don't pre-allocate a lot of memory
+ // unnecessarily and possibly crash the application. The actual number of
+ // elements in the stream is only 2, so we should get an unexpected EOF
+ // error. QCborValue internally uses 16 bytes per element, so we get to
+ // 2 GB at 2^27 elements.
+ QTest::addRow("very-large-array-no-overflow") << raw("\x9a\x07\xff\xff\xff" "\0\0");
+ QTest::addRow("very-large-array-overflow1") << raw("\x9a\x40\0\0\0" "\0\0");
+
+ // this makes sure we don't accidentally clip to 32-bit: sending 2^32+2 elements
+ QTest::addRow("very-large-array-overflow2") << raw("\x9b\0\0\0\1""\0\0\0\2" "\0\0");
+}
+
+void tst_QCborValue::validation()
+{
+ QFETCH(QByteArray, data);
+
+ QCborParserError error;
+ QCborValue decoded = QCborValue::fromCbor(data, &error);
+ QVERIFY(error.error != QCborError{});
+
+ if (data.startsWith('\x81')) {
+ // decode without the array prefix
+ decoded = QCborValue::fromCbor(data.mid(1), &error);
+ QVERIFY(error.error != QCborError{});
+ }
+}
+
+void tst_QCborValue::toDiagnosticNotation_data()
+{
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<int>("opts");
+ QTest::addColumn<QString>("expected");
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUuid uuid = QUuid::createUuid();
+
+ QMetaEnum me = QMetaEnum::fromType<QCborValue::Type>();
+ auto add = [me](const QCborValue &v, const QString &exp) {
+ auto addRow = [=](const char *prefix) -> QTestData & {
+ QCborValue::Type t = v.type();
+ if (t == QCborValue::Integer)
+ return QTest::addRow("%sInteger:%lld", prefix, v.toInteger());
+ if (t == QCborValue::Double)
+ return QTest::addRow("%sDouble:%g", prefix, v.toDouble());
+ if (t == QCborValue::ByteArray)
+ return QTest::addRow("%sByteArray:%d", prefix, v.toByteArray().size());
+ if (t == QCborValue::String)
+ return QTest::addRow("%sString:%d", prefix, v.toString().size());
+
+ QByteArray typeString = me.valueToKey(t);
+ Q_ASSERT(!typeString.isEmpty());
+ return QTest::newRow(prefix + typeString);
+ };
+ addRow("") << v << int(QCborValue::DiagnosticNotationOptions{}) << exp;
+ addRow("LW:") << v << int(QCborValue::LineWrapped) << exp;
+ addRow("Array:") << QCborValue(QCborArray{v}) << int(QCborValue::DiagnosticNotationOptions{}) << '[' + exp + ']';
+ addRow("Mapped:") << QCborValue(QCborMap{{2, v}}) << int(QCborValue::DiagnosticNotationOptions{}) << "{2: " + exp + '}';
+ addRow("Mapping:") << QCborValue(QCborMap{{v, 2}}) << int(QCborValue::DiagnosticNotationOptions{}) << '{' + exp + ": 2}";
+ };
+
+ // empty arrays and maps
+ QTest::newRow("EmptyArray")
+ << QCborValue(QCborArray()) << int(QCborValue::DiagnosticNotationOptions{})
+ << "[]";
+ QTest::newRow("EmptyMap")
+ << QCborValue(QCborMap()) << int(QCborValue::DiagnosticNotationOptions{})
+ << "{}";
+
+ add(QCborValue(), "undefined");
+ add(QCborValue::Null, "null");
+ add(false, "false");
+ add(true, "true");
+ add(QCborSimpleType(0), "simple(0)");
+ QTest::newRow("SimpleType-255")
+ << QCborValue(QCborSimpleType(255)) << int(QCborValue::DiagnosticNotationOptions{})
+ << "simple(255)";
+ add(0, "0");
+ add(1, "1");
+ add(-1, "-1");
+ add(std::numeric_limits<qint64>::min(), QString::number(std::numeric_limits<qint64>::min()));
+ add(std::numeric_limits<qint64>::max(), QString::number(std::numeric_limits<qint64>::max()));
+ add(0., "0.0");
+ add(1.25, "1.25");
+ add(-1.25, "-1.25");
+ add(qInf(), "inf");
+ add(-qInf(), "-inf");
+ add(qQNaN(), "nan");
+ add(QByteArray(), "h''");
+ add(QByteArray("Hello"), "h'48656c6c6f'");
+ add(QLatin1String(), QLatin1String("\"\""));
+ add("Hello", "\"Hello\"");
+ add("\"Hello\\World\"", "\"\\\"Hello\\\\World\\\"\"");
+ add(QCborValue(dt), "0(\"" + dt.toString(Qt::ISODateWithMs) + "\")");
+ add(QCborValue(QUrl("http://example.com")), "32(\"http://example.com\")");
+ add(QCborValue(QRegularExpression("^.*$")), "35(\"^.*$\")");
+ add(QCborValue(uuid), "37(h'" + uuid.toString(QUuid::Id128) + "')");
+
+ // arrays and maps with more than one element
+ QTest::newRow("2Array")
+ << QCborValue(QCborArray{0, 1}) << int(QCborValue::DiagnosticNotationOptions{})
+ << "[0, 1]";
+ QTest::newRow("2Map")
+ << QCborValue(QCborMap{{0, 1}, {"foo", "bar"}}) << int(QCborValue::DiagnosticNotationOptions{})
+ << "{0: 1, \"foo\": \"bar\"}";
+
+ // line wrapping in arrays and maps
+ QTest::newRow("LW:EmptyArray")
+ << QCborValue(QCborArray()) << int(QCborValue::LineWrapped)
+ << "[\n]";
+ QTest::newRow("LW:EmptyMap")
+ << QCborValue(QCborMap()) << int(QCborValue::LineWrapped)
+ << "{\n}";
+ QTest::newRow("LW:Array:Integer:0")
+ << QCborValue(QCborArray{0}) << int(QCborValue::LineWrapped)
+ << "[\n 0\n]";
+ QTest::newRow("LW:Array:String:5")
+ << QCborValue(QCborArray{"Hello"}) << int(QCborValue::LineWrapped)
+ << "[\n \"Hello\"\n]";
+ QTest::newRow("LW:Map:0-0")
+ << QCborValue(QCborMap{{0, 0}}) << int(QCborValue::LineWrapped)
+ << "{\n 0: 0\n}";
+ QTest::newRow("LW:Map:String:5")
+ << QCborValue(QCborMap{{0, "Hello"}}) << int(QCborValue::LineWrapped)
+ << "{\n 0: \"Hello\"\n}";
+ QTest::newRow("LW:2Array")
+ << QCborValue(QCborArray{0, 1}) << int(QCborValue::LineWrapped)
+ << "[\n 0,\n 1\n]";
+ QTest::newRow("LW:2Map")
+ << QCborValue(QCborMap{{0, 0}, {"foo", "bar"}}) << int(QCborValue::LineWrapped)
+ << "{\n 0: 0,\n \"foo\": \"bar\"\n}";
+
+ // nested arrays and maps
+ QTest::newRow("Array:EmptyArray")
+ << QCborValue(QCborArray() << QCborArray()) << int(QCborValue::DiagnosticNotationOptions{})
+ << "[[]]";
+ QTest::newRow("Array:EmptyMap")
+ << QCborValue(QCborArray() << QCborMap()) << int(QCborValue::DiagnosticNotationOptions{})
+ << "[{}]";
+ QTest::newRow("LW:Array:EmptyArray")
+ << QCborValue(QCborArray() << QCborArray()) << int(QCborValue::LineWrapped)
+ << "[\n [\n ]\n]";
+ QTest::newRow("LW:Array:EmptyMap")
+ << QCborValue(QCborArray() << QCborMap()) << int(QCborValue::LineWrapped)
+ << "[\n {\n }\n]";
+ QTest::newRow("LW:Array:2Array")
+ << QCborValue(QCborArray() << QCborArray{0, 1}) << int(QCborValue::LineWrapped)
+ << "[\n [\n 0,\n 1\n ]\n]";
+ QTest::newRow("LW:Map:2Array")
+ << QCborValue(QCborMap{{0, QCborArray{0, 1}}}) << int(QCborValue::LineWrapped)
+ << "{\n 0: [\n 0,\n 1\n ]\n}";
+ QTest::newRow("LW:Map:2Map")
+ << QCborValue(QCborMap{{-1, QCborMap{{0, 0}, {"foo", "bar"}}}}) << int(QCborValue::LineWrapped)
+ << "{\n -1: {\n 0: 0,\n \"foo\": \"bar\"\n }\n}";
+
+ // string escaping
+ QTest::newRow("String:escaping")
+ << QCborValue("\1\a\b\t\f\r\n\v\x1f\x7f \"\xc2\xa0\xe2\x82\xac\xf0\x90\x80\x80\\\"")
+ << int(QCborValue::DiagnosticNotationOptions{})
+ << "\"\\u0001\\a\\b\\t\\f\\r\\n\\v\\u001F\\u007F \\\"\\u00A0\\u20AC\\U00010000\\\\\\\"\"";
+
+ // extended formatting for byte arrays
+ QTest::newRow("Extended:ByteArray:0")
+ << QCborValue(QByteArray()) << int(QCborValue::ExtendedFormat)
+ << "h''";
+ QTest::newRow("Extended:ByteArray:5")
+ << QCborValue(QByteArray("Hello")) << int(QCborValue::ExtendedFormat)
+ << "h'48 65 6c 6c 6f'";
+ QTest::newRow("Extended:ByteArray:Base64url")
+ << QCborValue(QCborKnownTags::ExpectedBase64url, QByteArray("\xff\xef"))
+ << int(QCborValue::ExtendedFormat) << "21(b64'_-8')";
+ QTest::newRow("Extended:ByteArray:Base64")
+ << QCborValue(QCborKnownTags::ExpectedBase64, QByteArray("\xff\xef"))
+ << int(QCborValue::ExtendedFormat) << "22(b64'/+8=')";
+
+ // formatting applies through arrays too
+ QTest::newRow("Extended:Array:ByteArray:Base64url")
+ << QCborValue(QCborKnownTags::ExpectedBase64url, QCborArray{QByteArray("\xff\xef")})
+ << int(QCborValue::ExtendedFormat) << "21([b64'_-8'])";
+ // and only the innermost applies
+ QTest::newRow("ByteArray:multiple-tags")
+ << QCborValue(QCborKnownTags::ExpectedBase64url,
+ QCborArray{QCborValue(QCborKnownTags::ExpectedBase16, QByteArray("Hello")),
+ QByteArray("\xff\xef")})
+ << int(QCborValue::ExtendedFormat) << "21([23(h'48 65 6c 6c 6f'), b64'_-8'])";
+}
+
+void tst_QCborValue::toDiagnosticNotation()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QString, expected);
+ QFETCH(int, opts);
+
+ QString result = v.toDiagnosticNotation(QCborValue::DiagnosticNotationOptions(opts));
+ QCOMPARE(result, expected);
+}
+
+QTEST_MAIN(tst_QCborValue)
+
+#include "tst_qcborvalue.moc"
diff --git a/tests/auto/corelib/serialization/qcborvalue_json/qcborvalue_json.pro b/tests/auto/corelib/serialization/qcborvalue_json/qcborvalue_json.pro
new file mode 100644
index 0000000000..c11000b7c2
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborvalue_json/qcborvalue_json.pro
@@ -0,0 +1,7 @@
+QT = core testlib
+TARGET = tst_qcborvalue_json
+CONFIG += testcase
+SOURCES += \
+ tst_qcborvalue_json.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
diff --git a/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp b/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp
new file mode 100644
index 0000000000..56245a7173
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qcborvalue.h>
+#include <QtTest>
+
+Q_DECLARE_METATYPE(QCborValue)
+
+class tst_QCborValue_Json : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void toVariant_data();
+ void toVariant();
+ void toJson_data() { toVariant_data(); }
+ void toJson();
+ void taggedByteArrayToJson_data();
+ void taggedByteArrayToJson();
+
+ void fromVariant_data() { toVariant_data(); }
+ void fromVariant();
+ void fromJson_data();
+ void fromJson();
+
+ void nonStringKeysInMaps_data();
+ void nonStringKeysInMaps();
+};
+
+void tst_QCborValue_Json::toVariant_data()
+{
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<QVariant>("variant");
+ QTest::addColumn<QJsonValue>("json");
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUuid uuid = QUuid::createUuid();
+
+ QMetaEnum me = QMetaEnum::fromType<QCborValue::Type>();
+ auto add = [me](const QCborValue &v, const QVariant &exp, const QJsonValue &json) {
+ auto addRow = [=]() -> QTestData & {
+ const char *typeString = me.valueToKey(v.type());
+ if (v.type() == QCborValue::Integer)
+ return QTest::addRow("Integer:%lld", exp.toLongLong());
+ if (v.type() == QCborValue::Double)
+ return QTest::addRow("Double:%g", exp.toDouble());
+ if (v.type() == QCborValue::ByteArray || v.type() == QCborValue::String)
+ return QTest::addRow("%s:%d", typeString, exp.toString().size());
+ if (v.type() >= 0x10000)
+ return QTest::newRow(exp.typeName());
+ return QTest::newRow(typeString);
+ };
+ addRow() << v << exp << json;
+ };
+
+ // good JSON matching:
+ add(QCborValue(), QVariant(), QJsonValue::Undefined);
+ add(nullptr, QVariant::fromValue(nullptr), QJsonValue::Null);
+ add(false, false, false);
+ add(true, true, true);
+ add(0, 0, 0);
+ add(1, 1, 1);
+ add(-1, -1, -1);
+ add(0., 0., 0.);
+ add(1.25, 1.25, 1.25);
+ add(-1.25, -1.25, -1.25);
+ add("Hello", "Hello", "Hello");
+
+ // converts to string in JSON:
+ add(QByteArray("Hello"), QByteArray("Hello"), "SGVsbG8");
+ add(QCborValue(dt), dt, dt.toString(Qt::ISODateWithMs));
+ add(QCborValue(QUrl("http://example.com/{q}")), QUrl("http://example.com/{q}"),
+ "http://example.com/%7Bq%7D"); // note the encoded form in JSON
+ add(QCborValue(QRegularExpression(".")), QRegularExpression("."), ".");
+ add(QCborValue(uuid), uuid, uuid.toString(QUuid::WithoutBraces));
+
+ // not valid in JSON
+ QTest::newRow("simpletype") << QCborValue(QCborSimpleType(255))
+ << QVariant::fromValue(QCborSimpleType(255))
+ << QJsonValue("simple(255)");
+ QTest::newRow("Double:inf") << QCborValue(qInf())
+ << QVariant(qInf())
+ << QJsonValue();
+ QTest::newRow("Double:-inf") << QCborValue(-qInf())
+ << QVariant(-qInf())
+ << QJsonValue();
+ QTest::newRow("Double:nan") << QCborValue(qQNaN())
+ << QVariant(qQNaN())
+ << QJsonValue();
+
+ // large integral values lose precision in JSON
+ QTest::newRow("Integer:max") << QCborValue(std::numeric_limits<qint64>::max())
+ << QVariant(std::numeric_limits<qint64>::max())
+ << QJsonValue(std::numeric_limits<qint64>::max());
+ QTest::newRow("Integer:min") << QCborValue(std::numeric_limits<qint64>::min())
+ << QVariant(std::numeric_limits<qint64>::min())
+ << QJsonValue(std::numeric_limits<qint64>::min());
+
+ // empty arrays and maps
+ add(QCborArray(), QVariantList(), QJsonArray());
+ add(QCborMap(), QVariantMap(), QJsonObject());
+}
+
+void tst_QCborValue_Json::toVariant()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QVariant, variant);
+
+ if (qIsNaN(variant.toDouble())) {
+ // because NaN != NaN, QVariant(NaN) != QVariant(NaN), so we
+ // only need to compare the classification
+ QVERIFY(qIsNaN(v.toVariant().toDouble()));
+
+ // the rest of this function depends on the variant comparison
+ return;
+ }
+
+ QCOMPARE(v.toVariant(), variant);
+ if (variant.isValid()) {
+ QVariant variant2 = QVariant::fromValue(v);
+ QVERIFY(variant2.canConvert(variant.userType()));
+ QVERIFY(variant2.convert(variant.userType()));
+ QCOMPARE(variant2, variant);
+ }
+
+ // tags get ignored:
+ QCOMPARE(QCborValue(QCborKnownTags::Signature, v).toVariant(), variant);
+
+ // make arrays with this item
+ QCOMPARE(QCborArray({v}).toVariantList(), QVariantList({variant}));
+ QCOMPARE(QCborArray({v, v}).toVariantList(), QVariantList({variant, variant}));
+
+ // and maps
+ QCOMPARE(QCborMap({{"foo", v}}).toVariantMap(), QVariantMap({{"foo", variant}}));
+ QCOMPARE(QCborMap({{"foo", v}}).toVariantHash(), QVariantHash({{"foo", variant}}));
+
+ // finally, mixed
+ QCOMPARE(QCborArray{QCborMap({{"foo", v}})}.toVariantList(),
+ QVariantList{QVariantMap({{"foo", variant}})});
+}
+
+void tst_QCborValue_Json::toJson()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QJsonValue, json);
+
+ QCOMPARE(v.toJsonValue(), json);
+ QCOMPARE(QVariant::fromValue(v).toJsonValue(), json);
+
+ // most tags get ignored:
+ QCOMPARE(QCborValue(QCborKnownTags::Signature, v).toJsonValue(), json);
+
+ // make arrays with this item
+ QCOMPARE(QCborArray({v}).toJsonArray(), QJsonArray({json}));
+ QCOMPARE(QCborArray({v, v}).toJsonArray(), QJsonArray({json, json}));
+
+ // and maps
+ QCOMPARE(QCborMap({{"foo", v}}).toJsonObject(), QJsonObject({{"foo", json}}));
+
+ // finally, mixed
+ QCOMPARE(QCborArray{QCborMap({{"foo", v}})}.toJsonArray(),
+ QJsonArray{QJsonObject({{"foo", json}})});
+}
+
+void tst_QCborValue_Json::taggedByteArrayToJson_data()
+{
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<QJsonValue>("json");
+
+ QByteArray data("\xff\x01");
+ QTest::newRow("base64url") << QCborValue(QCborKnownTags::ExpectedBase64url, data) << QJsonValue("_wE");
+ QTest::newRow("base64") << QCborValue(QCborKnownTags::ExpectedBase64, data) << QJsonValue("/wE=");
+ QTest::newRow("hex") << QCborValue(QCborKnownTags::ExpectedBase16, data) << QJsonValue("ff01");
+}
+
+void tst_QCborValue_Json::taggedByteArrayToJson()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QJsonValue, json);
+
+ QCOMPARE(v.toJsonValue(), json);
+ QCOMPARE(QCborArray({v}).toJsonArray(), QJsonArray({json}));
+}
+
+void tst_QCborValue_Json::fromVariant()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QVariant, variant);
+
+ QCOMPARE(QCborValue::fromVariant(variant), v);
+ QCOMPARE(variant.value<QCborValue>(), v);
+
+ // try arrays
+ QCOMPARE(QCborArray::fromVariantList({variant}), QCborArray{v});
+ QCOMPARE(QCborArray::fromVariantList({variant, variant}), QCborArray({v, v}));
+
+ if (variant.type() == QVariant::String) {
+ QString s = variant.toString();
+ QCOMPARE(QCborArray::fromStringList({s}), QCborArray{v});
+ QCOMPARE(QCborArray::fromStringList({s, s}), QCborArray({v, v}));
+ }
+
+ // maps...
+ QVariantMap map{{"foo", variant}};
+ QCOMPARE(QCborMap::fromVariantMap(map), QCborMap({{"foo", v}}));
+ QCOMPARE(QCborMap::fromVariantHash({{"foo", variant}}), QCborMap({{"foo", v}}));
+
+ // nested
+ QVariantMap outer{{"bar", QVariantList{0, map, true}}};
+ QCOMPARE(QCborMap::fromVariantMap(outer),
+ QCborMap({{"bar", QCborArray{0, QCborMap{{"foo", v}}, true}}}));
+}
+
+void tst_QCborValue_Json::fromJson_data()
+{
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<QJsonValue>("json");
+
+ QTest::newRow("null") << QCborValue(QCborValue::Null) << QJsonValue(QJsonValue::Null);
+ QTest::newRow("false") << QCborValue(false) << QJsonValue(false);
+ QTest::newRow("true") << QCborValue(true) << QJsonValue(true);
+ QTest::newRow("0") << QCborValue(0) << QJsonValue(0.);
+ QTest::newRow("1") << QCborValue(1) << QJsonValue(1);
+ QTest::newRow("1.5") << QCborValue(1.5) << QJsonValue(1.5);
+ QTest::newRow("string") << QCborValue("Hello") << QJsonValue("Hello");
+ QTest::newRow("array") << QCborValue(QCborValue::Array) << QJsonValue(QJsonValue::Array);
+ QTest::newRow("map") << QCborValue(QCborValue::Map) << QJsonValue(QJsonValue::Object);
+}
+
+void tst_QCborValue_Json::fromJson()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QJsonValue, json);
+
+ QCOMPARE(QCborValue::fromJsonValue(json), v);
+ QCOMPARE(QVariant(json).value<QCborValue>(), v);
+ QCOMPARE(QCborArray::fromJsonArray({json}), QCborArray({v}));
+ QCOMPARE(QCborArray::fromJsonArray({json, json}), QCborArray({v, v}));
+ QCOMPARE(QCborMap::fromJsonObject({{"foo", json}}), QCborMap({{"foo", v}}));
+
+ // confirm we can roundtrip back to JSON
+ QCOMPARE(QCborValue::fromJsonValue(json).toJsonValue(), json);
+}
+
+void tst_QCborValue_Json::nonStringKeysInMaps_data()
+{
+ QTest::addColumn<QCborValue>("key");
+ QTest::addColumn<QString>("converted");
+
+ auto add = [](const char *str, const QCborValue &v) {
+ QTest::newRow(str) << v << str;
+ };
+ add("0", 0);
+ add("-1", -1);
+ add("false", false);
+ add("true", true);
+ add("null", nullptr);
+ add("undefined", {}); // should this be ""?
+ add("simple(255)", QCborSimpleType(255));
+ add("2.5", 2.5);
+
+ QByteArray data("\xff\x01");
+ QTest::newRow("bytearray") << QCborValue(data) << "_wE";
+ QTest::newRow("base64url") << QCborValue(QCborKnownTags::ExpectedBase64url, data) << "_wE";
+ QTest::newRow("base64") << QCborValue(QCborKnownTags::ExpectedBase64, data) << "/wE=";
+ QTest::newRow("hex") << QCborValue(QCborKnownTags::ExpectedBase16, data) << "ff01";
+
+ QTest::newRow("emptyarray") << QCborValue(QCborValue::Array) << "[]";
+ QTest::newRow("emptymap") << QCborValue(QCborValue::Map) << "{}";
+ QTest::newRow("array") << QCborValue(QCborArray{1, true, 2.5, "Hello"})
+ << "[1, true, 2.5, \"Hello\"]";
+ QTest::newRow("map") << QCborValue(QCborMap{{"Hello", 0}, {0, "Hello"}})
+ << "{\"Hello\": 0, 0: \"Hello\"}";
+
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUrl url("https://example.com");
+ QUuid uuid = QUuid::createUuid();
+ QTest::newRow("QDateTime") << QCborValue(dt) << dt.toString(Qt::ISODateWithMs);
+ QTest::newRow("QUrl") << QCborValue(url) << url.toString(QUrl::FullyEncoded);
+ QTest::newRow("QRegularExpression") << QCborValue(QRegularExpression(".*")) << ".*";
+ QTest::newRow("QUuid") << QCborValue(uuid) << uuid.toString(QUuid::WithoutBraces);
+}
+
+void tst_QCborValue_Json::nonStringKeysInMaps()
+{
+ QFETCH(QCborValue, key);
+ QFETCH(QString, converted);
+
+ QCborMap m;
+ m.insert(key, 0);
+
+ {
+ QVariantMap vm = m.toVariantMap();
+ auto it = vm.begin();
+ QVERIFY(it != vm.end());
+ QCOMPARE(it.key(), converted);
+ QCOMPARE(it.value(), 0);
+ QCOMPARE(++it, vm.end());
+ }
+
+ {
+ QJsonObject o = m.toJsonObject();
+ auto it = o.begin();
+ QVERIFY(it != o.end());
+ QCOMPARE(it.key(), converted);
+ QCOMPARE(it.value(), 0);
+ QCOMPARE(++it, o.end());
+ }
+}
+
+QTEST_MAIN(tst_QCborValue_Json)
+
+#include "tst_qcborvalue_json.moc"
diff --git a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
index 14a2528cc6..011a0e1a85 100644
--- a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
+++ b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
@@ -260,16 +260,16 @@ static int NColorRoles[] = {
QPalette::HighlightedText + 1, // Qt_4_0, Qt_4_1
QPalette::HighlightedText + 1, // Qt_4_2
QPalette::AlternateBase + 1, // Qt_4_3
- QPalette::ToolTipText + 1, // Qt_4_4
- QPalette::ToolTipText + 1, // Qt_4_5
- QPalette::ToolTipText + 1, // Qt_4_6
- QPalette::ToolTipText + 1, // Qt_5_0
- QPalette::ToolTipText + 1, // Qt_5_1
- QPalette::ToolTipText + 1, // Qt_5_2
- QPalette::ToolTipText + 1, // Qt_5_3
- QPalette::ToolTipText + 1, // Qt_5_4
- QPalette::ToolTipText + 1, // Qt_5_5
- QPalette::ToolTipText + 1, // Qt_5_6
+ QPalette::PlaceholderText + 1, // Qt_4_4
+ QPalette::PlaceholderText + 1, // Qt_4_5
+ QPalette::PlaceholderText + 1, // Qt_4_6
+ QPalette::PlaceholderText + 1, // Qt_5_0
+ QPalette::PlaceholderText + 1, // Qt_5_1
+ QPalette::PlaceholderText + 1, // Qt_5_2
+ QPalette::PlaceholderText + 1, // Qt_5_3
+ QPalette::PlaceholderText + 1, // Qt_5_4
+ QPalette::PlaceholderText + 1, // Qt_5_5
+ QPalette::PlaceholderText + 1, // Qt_5_6
0 // add the correct value for Qt_5_7 here later
};
@@ -2139,7 +2139,7 @@ void tst_QDataStream::setVersion()
*/
// revise the test if new color roles or color groups are added
- QVERIFY(QPalette::NColorRoles == QPalette::ToolTipText + 1);
+ QVERIFY(QPalette::NColorRoles == QPalette::PlaceholderText + 1);
QCOMPARE(int(QPalette::NColorGroups), 3);
QByteArray ba2;
@@ -2211,25 +2211,22 @@ void tst_QDataStream::setVersion()
}
}
-class SequentialBuffer : public QBuffer
+class SequentialBuffer : public QIODevice
{
public:
- SequentialBuffer(QByteArray *data) : QBuffer(data) { offset = 0; }
+ SequentialBuffer(QByteArray *data) : QIODevice() { buf.setBuffer(data); }
- bool isSequential() const { return true; }
- bool seek(qint64 pos) { offset = pos; return QBuffer::seek(pos); }
- qint64 pos() const { return qint64(offset); }
+ bool isSequential() const override { return true; }
+ bool open(OpenMode mode) override { return buf.open(mode) && QIODevice::open(mode | QIODevice::Unbuffered); }
+ void close() override { buf.close(); QIODevice::close(); }
+ qint64 bytesAvailable() const override { return QIODevice::bytesAvailable() + buf.bytesAvailable(); }
protected:
- qint64 readData(char *data, qint64 maxSize)
- {
- qint64 ret = QBuffer::readData(data, maxSize);
- offset += ret;
- return ret;
- }
+ qint64 readData(char *data, qint64 maxSize) override { return buf.read(data, maxSize); }
+ qint64 writeData(const char *data, qint64 maxSize) override { return buf.write(data, maxSize); }
private:
- int offset;
+ QBuffer buf;
};
void tst_QDataStream::skipRawData_data()
@@ -3329,15 +3326,21 @@ void tst_QDataStream::transaction_data()
QTest::addColumn<bool>("bData");
QTest::addColumn<float>("fData");
QTest::addColumn<double>("dData");
+ QTest::addColumn<QImage>("imgData");
QTest::addColumn<QByteArray>("strData");
QTest::addColumn<QByteArray>("rawData");
+ QImage img1(open_xpm);
+ QImage img2;
+ QImage img3(50, 50, QImage::Format_ARGB32);
+ img3.fill(qRgba(12, 34, 56, 78));
+
QTest::newRow("1") << qint8(1) << qint16(2) << qint32(3) << qint64(4) << true << 5.0f
- << double(6.0) << QByteArray("Hello world!") << QByteArray("Qt rocks!");
+ << double(6.0) << img1 << QByteArray("Hello world!") << QByteArray("Qt rocks!");
QTest::newRow("2") << qint8(1 << 6) << qint16(1 << 14) << qint32(1 << 30) << qint64Data(3) << false << 123.0f
- << double(234.0) << stringData(5).toUtf8() << stringData(6).toUtf8();
+ << double(234.0) << img2 << stringData(5).toUtf8() << stringData(6).toUtf8();
QTest::newRow("3") << qint8(-1) << qint16(-2) << qint32(-3) << qint64(-4) << true << -123.0f
- << double(-234.0) << stringData(3).toUtf8() << stringData(4).toUtf8();
+ << double(-234.0) << img3 << stringData(3).toUtf8() << stringData(4).toUtf8();
}
void tst_QDataStream::transaction()
@@ -3351,6 +3354,7 @@ void tst_QDataStream::transaction()
QFETCH(bool, bData);
QFETCH(float, fData);
QFETCH(double, dData);
+ QFETCH(QImage, imgData);
QFETCH(QByteArray, strData);
QFETCH(QByteArray, rawData);
@@ -3358,12 +3362,13 @@ void tst_QDataStream::transaction()
QDataStream stream(&testBuffer, QIODevice::WriteOnly);
stream << i8Data << i16Data << i32Data << i64Data
- << bData << fData << dData << strData.constData();
+ << bData << fData << dData << imgData << strData.constData();
stream.writeRawData(rawData.constData(), rawData.size());
}
for (int splitPos = 0; splitPos <= testBuffer.size(); ++splitPos) {
QByteArray readBuffer(testBuffer.left(splitPos));
+
SequentialBuffer dev(&readBuffer);
dev.open(QIODevice::ReadOnly);
QDataStream stream(&dev);
@@ -3375,12 +3380,13 @@ void tst_QDataStream::transaction()
bool b;
float f;
double d;
+ QImage img;
char *str;
QByteArray raw(rawData.size(), 0);
forever {
stream.startTransaction();
- stream >> i8 >> i16 >> i32 >> i64 >> b >> f >> d >> str;
+ stream >> i8 >> i16 >> i32 >> i64 >> b >> f >> d >> img >> str;
stream.readRawData(raw.data(), raw.size());
if (stream.commitTransaction())
@@ -3402,6 +3408,7 @@ void tst_QDataStream::transaction()
QCOMPARE(b, bData);
QCOMPARE(f, fData);
QCOMPARE(d, dData);
+ QCOMPARE(img, imgData);
QVERIFY(strData == str);
delete [] str;
QCOMPARE(raw, rawData);
diff --git a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp
index df8746e518..edea4713a1 100644
--- a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp
+++ b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp
@@ -161,6 +161,7 @@ private slots:
void string_write_operator_ToDevice();
void latin1String_write_operator_ToDevice();
void stringref_write_operator_ToDevice();
+ void stringview_write_operator_ToDevice();
// other
void skipWhiteSpace_data();
@@ -2573,6 +2574,17 @@ void tst_QTextStream::stringref_write_operator_ToDevice()
QCOMPARE(buf.buffer().constData(), "No explicit lengthExplicit length");
}
+void tst_QTextStream::stringview_write_operator_ToDevice()
+{
+ QBuffer buf;
+ buf.open(QBuffer::WriteOnly);
+ QTextStream stream(&buf);
+ const QStringView expected = QStringViewLiteral("expectedStringView");
+ stream << expected;
+ stream.flush();
+ QCOMPARE(buf.buffer().constData(), "expectedStringView");
+}
+
// ------------------------------------------------------------------------------
void tst_QTextStream::useCase1()
{
diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
index 16a4200b5d..8fdf91b090 100644
--- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
+++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
@@ -577,6 +577,8 @@ private slots:
void invalidStringCharacters() const;
void hasError() const;
void readBack() const;
+ void roundTrip() const;
+ void roundTrip_data() const;
private:
static QByteArray readFile(const QString &filename);
@@ -1741,5 +1743,35 @@ void tst_QXmlStream::readBack() const
}
}
+void tst_QXmlStream::roundTrip_data() const
+{
+ QTest::addColumn<QString>("in");
+
+ QTest::newRow("QTBUG-63434") <<
+ "<?xml version=\"1.0\"?>"
+ "<root>"
+ "<father>"
+ "<child xmlns:unknown=\"http://mydomain\">Text</child>"
+ "</father>"
+ "</root>\n";
+}
+
+void tst_QXmlStream::roundTrip() const
+{
+ QFETCH(QString, in);
+ QString out;
+
+ QXmlStreamReader reader(in);
+ QXmlStreamWriter writer(&out);
+
+ while (!reader.atEnd()) {
+ reader.readNext();
+ QVERIFY(!reader.hasError());
+ writer.writeCurrentToken(reader);
+ QVERIFY(!writer.hasError());
+ }
+ QCOMPARE(out, in);
+}
+
#include "tst_qxmlstream.moc"
// vim: et:ts=4:sw=4:sts=4
diff --git a/tests/auto/corelib/serialization/serialization.pro b/tests/auto/corelib/serialization/serialization.pro
index afb9c5b61c..9187de1bc5 100644
--- a/tests/auto/corelib/serialization/serialization.pro
+++ b/tests/auto/corelib/serialization/serialization.pro
@@ -1,6 +1,10 @@
TEMPLATE = subdirs
SUBDIRS = \
json \
+ qcborstreamreader \
+ qcborstreamwriter \
+ qcborvalue \
+ qcborvalue_json \
qdatastream \
qtextstream \
qxmlstream
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index d4a3ee6054..b8c82c2ea0 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -1021,6 +1021,8 @@ void tst_QFuture::iterators()
QCOMPARE(i2, c2);
QCOMPARE(c2, i2);
QCOMPARE(c2, c2);
+ QCOMPARE(1 + i1, i1 + 1);
+ QCOMPARE(1 + c1, c1 + 1);
QVERIFY(i1 != i2);
QVERIFY(i1 != c2);
@@ -1070,6 +1072,8 @@ void tst_QFuture::iterators()
QCOMPARE(i2, c2);
QCOMPARE(c2, i2);
QCOMPARE(c2, c2);
+ QCOMPARE(1 + i1, i1 + 1);
+ QCOMPARE(1 + c1, c1 + 1);
QVERIFY(i1 != i2);
QVERIFY(i1 != c2);
diff --git a/tests/auto/corelib/thread/qsemaphore/BLACKLIST b/tests/auto/corelib/thread/qsemaphore/BLACKLIST
index eb83b03556..0786f50417 100644
--- a/tests/auto/corelib/thread/qsemaphore/BLACKLIST
+++ b/tests/auto/corelib/thread/qsemaphore/BLACKLIST
@@ -1,6 +1,8 @@
[tryAcquireWithTimeout:0.2s]
windows
osx-10.12
+osx-10.13
[tryAcquireWithTimeout:2s]
windows
osx-10.12
+osx-10.13
diff --git a/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp b/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp
index 9179750218..d27884197a 100644
--- a/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp
+++ b/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp
@@ -30,7 +30,6 @@
#include "qplatformdefs.h"
#include "qthreadonce.h"
-#ifndef QT_NO_THREAD
#include "qmutex.h"
Q_GLOBAL_STATIC_WITH_ARGS(QMutex, onceInitializationMutex, (QMutex::Recursive))
@@ -104,5 +103,3 @@ void QOnceControl::done()
{
extra &= ~MustRunCode;
}
-
-#endif // QT_NO_THREAD
diff --git a/tests/auto/corelib/thread/qthreadonce/qthreadonce.h b/tests/auto/corelib/thread/qthreadonce/qthreadonce.h
index 71e830ca16..e5918b8fa5 100644
--- a/tests/auto/corelib/thread/qthreadonce/qthreadonce.h
+++ b/tests/auto/corelib/thread/qthreadonce/qthreadonce.h
@@ -34,8 +34,6 @@
#include <QtCore/qatomic.h>
-#ifndef QT_NO_THREAD
-
class QOnceControl
{
public:
@@ -91,6 +89,4 @@ public:
inline operator T*() { return value(); }
};
-#endif // QT_NO_THREAD
-
#endif
diff --git a/tests/auto/corelib/thread/qthreadstorage/crashonexit/crashonexit.pro b/tests/auto/corelib/thread/qthreadstorage/crashonexit/crashonexit.pro
index 94a0a01e94..d5c09ebc84 100644
--- a/tests/auto/corelib/thread/qthreadstorage/crashonexit/crashonexit.pro
+++ b/tests/auto/corelib/thread/qthreadstorage/crashonexit/crashonexit.pro
@@ -1,5 +1,13 @@
SOURCES += crashOnExit.cpp
-DESTDIR = ./
+debug_and_release {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/crashOnExit_helper
+ } else {
+ TARGET = ../../release/crashOnExit_helper
+ }
+} else {
+ TARGET = ../crashOnExit_helper
+}
QT = core
CONFIG -= app_bundle
CONFIG += console
diff --git a/tests/auto/corelib/thread/qthreadstorage/test/test.pro b/tests/auto/corelib/thread/qthreadstorage/test/test.pro
index d7190f7e7b..d2f21f48f0 100644
--- a/tests/auto/corelib/thread/qthreadstorage/test/test.pro
+++ b/tests/auto/corelib/thread/qthreadstorage/test/test.pro
@@ -1,9 +1,16 @@
CONFIG += testcase
-TARGET = ../tst_qthreadstorage
-CONFIG -= debug_and_release_target
+debug_and_release {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/tst_qthreadstorage
+ !android:!winrt: TEST_HELPER_INSTALLS = ../../debug/crashonexit_helper
+ } else {
+ TARGET = ../../release/tst_qthreadstorage
+ !android:!winrt: TEST_HELPER_INSTALLS = ../../release/crashonexit_helper
+ }
+} else {
+ TARGET = ../tst_qthreadstorage
+ !android:!winrt: TEST_HELPER_INSTALLS = ../crashonexit_helper
+}
CONFIG += console
QT = core testlib
SOURCES = ../tst_qthreadstorage.cpp
-
-!android:!winrt: TEST_HELPER_INSTALLS = ../crashonexit/crashonexit
-
diff --git a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
index 403e28b07b..ef5d3452d5 100644
--- a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
+++ b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
@@ -48,7 +48,6 @@ class tst_QThreadStorage : public QObject
{
Q_OBJECT
private slots:
- void initTestCase();
void hasLocalData();
void localData();
void localData_const();
@@ -60,9 +59,6 @@ private slots:
void leakInDestructor();
void resetInDestructor();
void valueBased();
-
-private:
- QString m_crashOnExit;
};
class Pointer
@@ -74,22 +70,6 @@ public:
};
int Pointer::count = 0;
-void tst_QThreadStorage::initTestCase()
-{
-#if QT_CONFIG(process)
- const QString crashOnExitDir = QFINDTESTDATA("crashonexit");
- QVERIFY2(!crashOnExitDir.isEmpty(),
- qPrintable(QString::fromLatin1("Could not find 'crashonexit' starting from '%1'")
- .arg(QDir::toNativeSeparators(QDir::currentPath()))));
- m_crashOnExit = crashOnExitDir + QStringLiteral("/crashonexit");
-#ifdef Q_OS_WIN
- m_crashOnExit += QStringLiteral(".exe");
-#endif
- QVERIFY2(QFileInfo(m_crashOnExit).isExecutable(),
- qPrintable(QDir::toNativeSeparators(m_crashOnExit) + QStringLiteral(" does not exist or is not executable.")));
-#endif
-}
-
void tst_QThreadStorage::hasLocalData()
{
QThreadStorage<Pointer *> pointers;
@@ -329,7 +309,7 @@ void tst_QThreadStorage::crashOnExit()
QSKIP("No qprocess support", SkipAll);
#else
QString errorMessage;
- QVERIFY2(runCrashOnExit(m_crashOnExit, &errorMessage),
+ QVERIFY2(runCrashOnExit("crashOnExit_helper", &errorMessage),
qPrintable(errorMessage));
#endif
}
diff --git a/tests/auto/corelib/thread/thread.pro b/tests/auto/corelib/thread/thread.pro
index d3c669859b..90b8d6806e 100644
--- a/tests/auto/corelib/thread/thread.pro
+++ b/tests/auto/corelib/thread/thread.pro
@@ -1,22 +1,25 @@
TEMPLATE=subdirs
-SUBDIRS=\
- qatomicint \
- qatomicinteger \
- qatomicpointer \
- qresultstore \
- qfuture \
- qfuturesynchronizer \
- qmutex \
- qmutexlocker \
- qreadlocker \
- qreadwritelock \
- qsemaphore \
- qthread \
- qthreadonce \
- qthreadpool \
- qthreadstorage \
- qwaitcondition \
- qwritelocker
+
+qtConfig(thread) {
+ SUBDIRS=\
+ qatomicint \
+ qatomicinteger \
+ qatomicpointer \
+ qresultstore \
+ qfuture \
+ qfuturesynchronizer \
+ qmutex \
+ qmutexlocker \
+ qreadlocker \
+ qreadwritelock \
+ qsemaphore \
+ qthread \
+ qthreadonce \
+ qthreadpool \
+ qthreadstorage \
+ qwaitcondition \
+ qwritelocker
+}
qtHaveModule(concurrent) {
SUBDIRS += \
diff --git a/tests/auto/corelib/tools/collections/tst_collections.cpp b/tests/auto/corelib/tools/collections/tst_collections.cpp
index 38366e86ff..b40b1f0624 100644
--- a/tests/auto/corelib/tools/collections/tst_collections.cpp
+++ b/tests/auto/corelib/tools/collections/tst_collections.cpp
@@ -2620,6 +2620,8 @@ void testLinkedListLikeStlIterators()
QVERIFY(i2 == c2);
QVERIFY(c2 == i2);
QVERIFY(c2 == c2);
+ QVERIFY(1 + i1 == i1 + 1);
+ QVERIFY(1 + c1 == c1 + 1);
QVERIFY(i1 != i2);
QVERIFY(i1 != c2);
@@ -2731,6 +2733,8 @@ void testMapLikeStlIterators()
QVERIFY(i2 == c2);
QVERIFY(c2 == i2);
QVERIFY(c2 == c2);
+ QVERIFY(1 + i1 == i1 + 1);
+ QVERIFY(1 + c1 == c1 + 1);
QVERIFY(i1 != i2);
QVERIFY(i1 != c2);
diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
index 338adaabf7..1ed41793dc 100644
--- a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
+++ b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
@@ -106,6 +106,8 @@ private slots:
void number();
void toInt_data();
void toInt();
+ void toDouble_data();
+ void toDouble();
void blockSizeCalculations();
void resizeAfterFromRawData();
@@ -141,6 +143,8 @@ private slots:
#endif
void toUpperLower_data();
void toUpperLower();
+ void isUpper();
+ void isLower();
void macTypes();
@@ -856,15 +860,38 @@ void tst_QByteArray::qstricmp()
if ( actual != 0 ) {
actual = (actual < 0 ? -1 : 1);
}
- QCOMPARE(expected, actual);
+ QCOMPARE(actual, expected);
+
+ actual = ::qstricmp("012345679abcd" + str1.toLatin1(), "012345679AbCd" + str2.toLatin1());
+ if ( actual != 0 ) {
+ actual = (actual < 0 ? -1 : 1);
+ }
+ QCOMPARE(actual, expected);
+
+ actual = str1.toLatin1().compare(str2.toLatin1(), Qt::CaseInsensitive);
+ if ( actual != 0 ) {
+ actual = (actual < 0 ? -1 : 1);
+ }
+ QCOMPARE(actual, expected);
+
+ actual = str1.toLatin1().compare(str2.toLatin1().constData(), Qt::CaseInsensitive);
+ if ( actual != 0 ) {
+ actual = (actual < 0 ? -1 : 1);
+ }
+ QCOMPARE(actual, expected);
}
void tst_QByteArray::qstricmp_singularities()
{
QCOMPARE(::qstricmp(0, 0), 0);
- QVERIFY(::qstricmp(0, "a") != 0);
- QVERIFY(::qstricmp("a", 0) != 0);
+ QVERIFY(::qstricmp(0, "a") < 0);
+ QVERIFY(::qstricmp("a", 0) > 0);
QCOMPARE(::qstricmp("", ""), 0);
+ QCOMPARE(QByteArray().compare(nullptr, Qt::CaseInsensitive), 0);
+ QCOMPARE(QByteArray().compare("", Qt::CaseInsensitive), 0);
+ QVERIFY(QByteArray("a").compare(nullptr, Qt::CaseInsensitive) > 0);
+ QVERIFY(QByteArray("a").compare("", Qt::CaseInsensitive) > 0);
+ QVERIFY(QByteArray().compare("a", Qt::CaseInsensitive) < 0);
}
void tst_QByteArray::qstrnicmp_singularities()
@@ -874,6 +901,9 @@ void tst_QByteArray::qstrnicmp_singularities()
QVERIFY(::qstrnicmp("a", 0, 123) != 0);
QCOMPARE(::qstrnicmp("", "", 123), 0);
QCOMPARE(::qstrnicmp("a", "B", 0), 0);
+ QCOMPARE(QByteArray().compare(QByteArray(), Qt::CaseInsensitive), 0);
+ QVERIFY(QByteArray().compare(QByteArray("a"), Qt::CaseInsensitive) < 0);
+ QVERIFY(QByteArray("a").compare(QByteArray(), Qt::CaseInsensitive) > 0);
}
void tst_QByteArray::chop_data()
@@ -1289,6 +1319,11 @@ void tst_QByteArray::toInt_data()
QTest::newRow("base 0-3") << QByteArray("010") << 0 << int(8) << true;
QTest::newRow("empty") << QByteArray() << 0 << int(0) << false;
+ QTest::newRow("leading space") << QByteArray(" 100") << 10 << int(100) << true;
+ QTest::newRow("trailing space") << QByteArray("100 ") << 10 << int(100) << true;
+ QTest::newRow("leading junk") << QByteArray("x100") << 10 << int(0) << false;
+ QTest::newRow("trailing junk") << QByteArray("100x") << 10 << int(0) << false;
+
// using fromRawData
QTest::newRow("raw1") << QByteArray::fromRawData("1", 1) << 10 << 1 << true;
QTest::newRow("raw2") << QByteArray::fromRawData("1foo", 1) << 10 << 1 << true;
@@ -1313,6 +1348,34 @@ void tst_QByteArray::toInt()
QCOMPARE( number, expectednumber );
}
+void tst_QByteArray::toDouble_data()
+{
+ QTest::addColumn<QByteArray>("string");
+ QTest::addColumn<double>("expectedNumber");
+ QTest::addColumn<bool>("expectedOk");
+
+ QTest::newRow("decimal") << QByteArray("1.2345") << 1.2345 << true;
+ QTest::newRow("exponent lowercase") << QByteArray("1.2345e+01") << 12.345 << true;
+ QTest::newRow("exponent uppercase") << QByteArray("1.2345E+02") << 123.45 << true;
+ QTest::newRow("leading spaces") << QByteArray(" \n\r\t1.2345") << 1.2345 << true;
+ QTest::newRow("trailing spaces") << QByteArray("1.2345 \n\r\t") << 1.2345 << true;
+ QTest::newRow("leading junk") << QByteArray("x1.2345") << 0.0 << false;
+ QTest::newRow("trailing junk") << QByteArray("1.2345x") << 0.0 << false;
+}
+
+void tst_QByteArray::toDouble()
+{
+ QFETCH(QByteArray, string);
+ QFETCH(double, expectedNumber);
+ QFETCH(bool, expectedOk);
+
+ bool ok;
+ const double number = string.toDouble(&ok);
+
+ QCOMPARE(ok, expectedOk);
+ QCOMPARE(number, expectedNumber);
+}
+
void tst_QByteArray::toULong_data()
{
QTest::addColumn<QByteArray>("str");
@@ -1326,6 +1389,11 @@ void tst_QByteArray::toULong_data()
QTest::newRow("empty") << QByteArray("") << 10 << 0UL << false;
QTest::newRow("ulong1") << QByteArray("3234567890") << 10 << 3234567890UL << true;
QTest::newRow("ulong2") << QByteArray("fFFfFfFf") << 16 << 0xFFFFFFFFUL << true;
+
+ QTest::newRow("leading spaces") << QByteArray(" \n\r\t100") << 10 << 100UL << true;
+ QTest::newRow("trailing spaces") << QByteArray("100 \n\r\t") << 10 << 100UL << true;
+ QTest::newRow("leading junk") << QByteArray("x100") << 10 << 0UL << false;
+ QTest::newRow("trailing junk") << QByteArray("100x") << 10 << 0UL << false;
}
void tst_QByteArray::toULong()
@@ -1351,6 +1419,10 @@ void tst_QByteArray::toULongLong_data()
QTest::newRow("default") << QByteArray() << 10 << (qulonglong)0 << false;
QTest::newRow("out of base bound") << QByteArray("c") << 10 << (qulonglong)0 << false;
+ QTest::newRow("leading spaces") << QByteArray(" \n\r\t100") << 10 << qulonglong(100) << true;
+ QTest::newRow("trailing spaces") << QByteArray("100 \n\r\t") << 10 << qulonglong(100) << true;
+ QTest::newRow("leading junk") << QByteArray("x100") << 10 << qulonglong(0) << false;
+ QTest::newRow("trailing junk") << QByteArray("100x") << 10 << qulonglong(0) << false;
}
void tst_QByteArray::toULongLong()
@@ -1757,6 +1829,12 @@ void tst_QByteArray::compare()
const bool isLess = result < 0;
const bool isGreater = result > 0;
+ int cmp = str1.compare(str2);
+ if (cmp)
+ cmp = (cmp < 0 ? -1 : 1);
+
+ QCOMPARE(cmp, result);
+
// basic tests:
QCOMPARE(str1 == str2, isEqual);
QCOMPARE(str1 < str2, isLess);
@@ -2188,6 +2266,51 @@ void tst_QByteArray::toUpperLower()
QCOMPARE(qMove(copy).toUpper(), upper);
}
+void tst_QByteArray::isUpper()
+{
+ QVERIFY(!QByteArray().isUpper());
+ QVERIFY(!QByteArray("").isUpper());
+ QVERIFY(QByteArray("TEXT").isUpper());
+ QVERIFY(QByteArray("\xD0\xDE").isUpper());
+ QVERIFY(!QByteArray("\xD7").isUpper()); // multiplication sign is not upper
+ QVERIFY(!QByteArray("\xDF").isUpper()); // sz ligature is not upper
+ QVERIFY(!QByteArray("text").isUpper());
+ QVERIFY(!QByteArray("Text").isUpper());
+ QVERIFY(!QByteArray("tExt").isUpper());
+ QVERIFY(!QByteArray("teXt").isUpper());
+ QVERIFY(!QByteArray("texT").isUpper());
+ QVERIFY(!QByteArray("TExt").isUpper());
+ QVERIFY(!QByteArray("teXT").isUpper());
+ QVERIFY(!QByteArray("tEXt").isUpper());
+ QVERIFY(!QByteArray("tExT").isUpper());
+ QVERIFY(!QByteArray("@ABYZ[").isUpper());
+ QVERIFY(!QByteArray("@abyz[").isUpper());
+ QVERIFY(!QByteArray("`ABYZ{").isUpper());
+ QVERIFY(!QByteArray("`abyz{").isUpper());
+}
+
+void tst_QByteArray::isLower()
+{
+ QVERIFY(!QByteArray().isLower());
+ QVERIFY(!QByteArray("").isLower());
+ QVERIFY(QByteArray("text").isLower());
+ QVERIFY(QByteArray("\xE0\xFF").isLower());
+ QVERIFY(!QByteArray("\xF7").isLower()); // division sign is not lower
+ QVERIFY(!QByteArray("Text").isLower());
+ QVERIFY(!QByteArray("tExt").isLower());
+ QVERIFY(!QByteArray("teXt").isLower());
+ QVERIFY(!QByteArray("texT").isLower());
+ QVERIFY(!QByteArray("TExt").isLower());
+ QVERIFY(!QByteArray("teXT").isLower());
+ QVERIFY(!QByteArray("tEXt").isLower());
+ QVERIFY(!QByteArray("tExT").isLower());
+ QVERIFY(!QByteArray("TEXT").isLower());
+ QVERIFY(!QByteArray("@ABYZ[").isLower());
+ QVERIFY(!QByteArray("@abyz[").isLower());
+ QVERIFY(!QByteArray("`ABYZ{").isLower());
+ QVERIFY(!QByteArray("`abyz{").isLower());
+}
+
void tst_QByteArray::macTypes()
{
#ifndef Q_OS_MAC
diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
index 4b362a9825..62c29229e1 100644
--- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
+++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
@@ -100,7 +100,7 @@ void tst_QCommandLineParser::testInvalidOptions()
QCoreApplication app(empty_argc, empty_argv);
QCommandLineParser parser;
QTest::ignoreMessage(QtWarningMsg, "QCommandLineOption: Option names cannot start with a '-'");
- parser.addOption(QCommandLineOption(QStringLiteral("-v"), QStringLiteral("Displays version information.")));
+ QVERIFY(!parser.addOption(QCommandLineOption(QStringLiteral("-v"), QStringLiteral("Displays version information."))));
}
void tst_QCommandLineParser::testPositionalArguments()
@@ -336,7 +336,7 @@ void tst_QCommandLineParser::testDoubleDash()
QCoreApplication app(empty_argc, empty_argv);
QCommandLineParser parser;
- parser.addOption(QCommandLineOption(QStringList() << "o" << "output", QStringLiteral("Output file"), QStringLiteral("filename")));
+ QVERIFY(parser.addOption(QCommandLineOption(QStringList() << "o" << "output", QStringLiteral("Output file"), QStringLiteral("filename"))));
parser.setSingleDashWordOptionMode(parsingMode);
QVERIFY(parser.parse(QStringList() << "tst_qcommandlineparser" << "--output" << "foo"));
QCOMPARE(parser.value("output"), QString("foo"));
@@ -382,7 +382,7 @@ void tst_QCommandLineParser::testMissingOptionValue()
{
QCoreApplication app(empty_argc, empty_argv);
QCommandLineParser parser;
- parser.addOption(QCommandLineOption(QStringLiteral("option"), QStringLiteral("An option"), "value"));
+ QVERIFY(parser.addOption(QCommandLineOption(QStringLiteral("option"), QStringLiteral("An option"), "value")));
QVERIFY(!parser.parse(QStringList() << "argv0" << "--option")); // the user forgot to pass a value for --option
QCOMPARE(parser.value("option"), QString());
QCOMPARE(parser.errorText(), QString("Missing value after '--option'."));
@@ -400,8 +400,8 @@ void tst_QCommandLineParser::testStdinArgument()
QCoreApplication app(empty_argc, empty_argv);
QCommandLineParser parser;
parser.setSingleDashWordOptionMode(parsingMode);
- parser.addOption(QCommandLineOption(QStringList() << "i" << "input", QStringLiteral("Input file."), QStringLiteral("filename")));
- parser.addOption(QCommandLineOption("b", QStringLiteral("Boolean option.")));
+ QVERIFY(parser.addOption(QCommandLineOption(QStringList() << "i" << "input", QStringLiteral("Input file."), QStringLiteral("filename"))));
+ QVERIFY(parser.addOption(QCommandLineOption("b", QStringLiteral("Boolean option."))));
QVERIFY(parser.parse(QStringList() << "tst_qcommandlineparser" << "--input" << "-"));
QCOMPARE(parser.value("input"), QString("-"));
QCOMPARE(parser.positionalArguments(), QStringList());
@@ -471,14 +471,14 @@ void tst_QCommandLineParser::testSingleDashWordOptionModes()
QCoreApplication app(empty_argc, empty_argv);
QCommandLineParser parser;
parser.setSingleDashWordOptionMode(parsingMode);
- parser.addOption(QCommandLineOption("a", QStringLiteral("a option.")));
- parser.addOption(QCommandLineOption("b", QStringLiteral("b option.")));
- parser.addOption(QCommandLineOption(QStringList() << "c" << "abc", QStringLiteral("c option."), QStringLiteral("value")));
- parser.addOption(QCommandLineOption("nn", QStringLiteral("nn option.")));
+ QVERIFY(parser.addOption(QCommandLineOption("a", QStringLiteral("a option."))));
+ QVERIFY(parser.addOption(QCommandLineOption("b", QStringLiteral("b option."))));
+ QVERIFY(parser.addOption(QCommandLineOption(QStringList() << "c" << "abc", QStringLiteral("c option."), QStringLiteral("value"))));
+ QVERIFY(parser.addOption(QCommandLineOption("nn", QStringLiteral("nn option."))));
QCommandLineOption forceShort(QStringLiteral("I"), QStringLiteral("always short option"),
QStringLiteral("path"), QStringLiteral("default"));
forceShort.setFlags(QCommandLineOption::ShortOptionStyle);
- parser.addOption(forceShort);
+ QVERIFY(parser.addOption(forceShort));
QVERIFY(parser.parse(commandLine));
QCOMPARE(parser.optionNames(), expectedOptionNames);
for (int i = 0; i < expectedOptionValues.count(); ++i)
@@ -493,11 +493,11 @@ void tst_QCommandLineParser::testCpp11StyleInitialization()
QCommandLineParser parser;
// primarily check that this compiles:
- parser.addOptions({
+ QVERIFY(parser.addOptions({
{ "a", "The A option." },
{ { "v", "verbose" }, "The verbose option." },
{ { "i", "infile" }, "The input file.", "value" },
- });
+ }));
// but do a very basic functionality test, too:
QVERIFY(parser.parse({"tst_QCommandLineParser", "-a", "-vvv", "--infile=in.txt"}));
QCOMPARE(parser.optionNames(), (QStringList{"a", "v", "v", "v", "infile"}));
diff --git a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp
index 17a0f3edd9..3eef7631c8 100644
--- a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp
+++ b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp
@@ -29,6 +29,7 @@
#include <QtCore/QCoreApplication>
#include <QtTest/QtTest>
+#include <QtCore/QMetaEnum>
Q_DECLARE_METATYPE(QCryptographicHash::Algorithm)
@@ -45,6 +46,7 @@ private slots:
void sha3();
void files_data();
void files();
+ void hashLength();
};
void tst_QCryptographicHash::repeated_result_data()
@@ -291,6 +293,15 @@ void tst_QCryptographicHash::files()
}
}
+void tst_QCryptographicHash::hashLength()
+{
+ auto metaEnum = QMetaEnum::fromType<QCryptographicHash::Algorithm>();
+ for (int i = 0, value = metaEnum.value(i); value != -1; value = metaEnum.value(++i)) {
+ auto algorithm = QCryptographicHash::Algorithm(value);
+ QByteArray output = QCryptographicHash::hash(QByteArrayLiteral("test"), algorithm);
+ QCOMPARE(QCryptographicHash::hashLength(algorithm), output.length());
+ }
+}
QTEST_MAIN(tst_QCryptographicHash)
#include "tst_qcryptographichash.moc"
diff --git a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
index 79309f960d..0196dd2d23 100644
--- a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
+++ b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
@@ -423,7 +423,12 @@ void tst_QEasingCurve::setCustomType()
QCOMPARE(curve.valueForProgress(0.15), 0.1);
QCOMPARE(curve.valueForProgress(0.20), 0.2);
QCOMPARE(curve.valueForProgress(0.25), 0.2);
+ // QTBUG-69947, MinGW 7.3 returns 0.2
+#if defined(Q_CC_MINGW)
+#if !defined(__GNUC__) || __GNUC__ != 7 || __GNUC_MINOR__ < 3
QCOMPARE(curve.valueForProgress(0.30), 0.3);
+#endif
+#endif
QCOMPARE(curve.valueForProgress(0.35), 0.3);
QCOMPARE(curve.valueForProgress(0.999999), 0.9);
diff --git a/tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp b/tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp
index f545ead1f1..e89e634841 100644
--- a/tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp
+++ b/tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp
@@ -159,6 +159,8 @@ void tst_QExplicitlySharedDataPointer::data() const
{
QExplicitlySharedDataPointer<const MyClass> pointer;
QCOMPARE(pointer.data(), static_cast<const MyClass *>(0));
+ QVERIFY(pointer == nullptr);
+ QVERIFY(nullptr == pointer);
}
/* On const pointer. Must not mutate the pointer. */
@@ -168,6 +170,9 @@ void tst_QExplicitlySharedDataPointer::data() const
/* Check that this cast is possible. */
static_cast<const MyClass *>(pointer.data());
+
+ QVERIFY(! (pointer == nullptr));
+ QVERIFY(! (nullptr == pointer));
}
/* On mutatable pointer. Must not mutate the pointer. */
diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
index b7cb8a1bdc..261689d401 100644
--- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
@@ -78,6 +78,7 @@ private slots:
#endif
void ctor();
+ void emptyCtor_data();
void emptyCtor();
void consistentC();
void matchingLocales();
@@ -118,8 +119,10 @@ private slots:
void monthName();
void standaloneMonthName();
- void defaultNumeringSystem();
+ void defaultNumberingSystem_data();
+ void defaultNumberingSystem();
+ void ampm_data();
void ampm();
void currency();
void quoteString();
@@ -127,6 +130,7 @@ private slots:
void weekendDays();
void listPatterns();
+ void measurementSystems_data();
void measurementSystems();
void QTBUG_26035_positivesign();
@@ -135,6 +139,7 @@ private slots:
void formattedDataSize_data();
void formattedDataSize();
+ void bcp47Name_data();
void bcp47Name();
void systemLocale_data();
@@ -145,6 +150,7 @@ private slots:
// QLocale::setDefault() *must* appear *after* all other tests !
void defaulted_ctor(); // This one must be the first of these.
void legacyNames();
+ void unixLocaleName_data();
void unixLocaleName();
void testNames_data();
void testNames();
@@ -152,6 +158,7 @@ private slots:
private:
QString m_decimal, m_thousand, m_sdate, m_ldate, m_time;
QString m_sysapp;
+ QStringList cleanEnv;
bool europeanTimeZone;
};
@@ -184,6 +191,14 @@ void tst_QLocale::initTestCase()
QVERIFY2(fi.exists() && fi.isExecutable(),
qPrintable(QDir::toNativeSeparators(m_sysapp)
+ QStringLiteral(" does not exist or is not executable.")));
+
+ // Get an environment free of any locale-related variables
+ cleanEnv.clear();
+ foreach (QString const& entry, QProcess::systemEnvironment()) {
+ if (entry.startsWith("LANG=") || entry.startsWith("LC_") || entry.startsWith("LANGUAGE="))
+ continue;
+ cleanEnv << entry;
+ }
#endif // QT_CONFIG(process)
}
@@ -214,32 +229,48 @@ void tst_QLocale::ctor()
}
// Exact matches
- TEST_CTOR(Chinese, SimplifiedHanScript, China, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
- TEST_CTOR(Chinese, TraditionalHanScript, Taiwan, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
- TEST_CTOR(Chinese, TraditionalHanScript, HongKong, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::HongKong);
+ TEST_CTOR(Chinese, SimplifiedHanScript, China,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, TraditionalHanScript, Taiwan,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, TraditionalHanScript, HongKong,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::HongKong);
// Best match for AnyCountry
- TEST_CTOR(Chinese, SimplifiedHanScript, AnyCountry, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
- TEST_CTOR(Chinese, TraditionalHanScript, AnyCountry, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, SimplifiedHanScript, AnyCountry,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, TraditionalHanScript, AnyCountry,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
// Best match for AnyScript (and change country to supported one, if necessary)
- TEST_CTOR(Chinese, AnyScript, China, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
- TEST_CTOR(Chinese, AnyScript, Taiwan, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
- TEST_CTOR(Chinese, AnyScript, HongKong, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::HongKong);
- TEST_CTOR(Chinese, AnyScript, UnitedStates, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, AnyScript, China,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, AnyScript, Taiwan,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, AnyScript, HongKong,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::HongKong);
+ TEST_CTOR(Chinese, AnyScript, UnitedStates,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
// Fully-specified not found; find best alternate country
- TEST_CTOR(Chinese, SimplifiedHanScript, Taiwan, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
- TEST_CTOR(Chinese, SimplifiedHanScript, UnitedStates, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
- TEST_CTOR(Chinese, TraditionalHanScript, China, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
- TEST_CTOR(Chinese, TraditionalHanScript, UnitedStates, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, SimplifiedHanScript, Taiwan,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, SimplifiedHanScript, UnitedStates,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, TraditionalHanScript, China,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, TraditionalHanScript, UnitedStates,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
// Fully-specified not found; find best alternate script
- TEST_CTOR(Chinese, LatinScript, China, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
- TEST_CTOR(Chinese, LatinScript, Taiwan, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, LatinScript, China,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, LatinScript, Taiwan,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
// Fully-specified not found; find best alternate country and script
- TEST_CTOR(Chinese, LatinScript, UnitedStates, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, LatinScript, UnitedStates,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
#undef TEST_CTOR
}
@@ -278,7 +309,8 @@ void tst_QLocale::defaulted_ctor()
TEST_CTOR(French, France, QLocale::French, QLocale::France)
TEST_CTOR(C, France, QLocale::C, QLocale::AnyCountry)
- TEST_CTOR(Spanish, LatinAmericaAndTheCaribbean, QLocale::Spanish, QLocale::LatinAmericaAndTheCaribbean)
+ TEST_CTOR(Spanish, LatinAmerica, QLocale::Spanish,
+ QLocale::LatinAmerica)
QLocale::setDefault(QLocale(QLocale::English, QLocale::France));
@@ -370,8 +402,9 @@ void tst_QLocale::defaulted_ctor()
QVERIFY2(l.language() == QLocale::exp_lang \
&& l.country() == QLocale::exp_country, \
QString("requested: \"" + QString(req_lc) + "\", got: " \
- + QLocale::languageToString(l.language()) \
- + QLatin1Char('/') + QLocale::countryToString(l.country())).toLatin1().constData()); \
+ + QLocale::languageToString(l.language()) \
+ + QLatin1Char('/') \
+ + QLocale::countryToString(l.country())).toLatin1().constData()); \
QCOMPARE(l, QLocale(QLocale::exp_lang, QLocale::exp_country)); \
QCOMPARE(qHash(l), qHash(QLocale(QLocale::exp_lang, QLocale::exp_country))); \
}
@@ -405,6 +438,8 @@ void tst_QLocale::defaulted_ctor()
TEST_CTOR("en_GB@bla", English, UnitedKingdom)
TEST_CTOR("en-GB", English, UnitedKingdom)
TEST_CTOR("en-GB@bla", English, UnitedKingdom)
+ TEST_CTOR("eo", Esperanto, World)
+ TEST_CTOR("yi", Yiddish, World)
QVERIFY(QLocale::Norwegian == QLocale::NorwegianBokmal);
TEST_CTOR("no", Norwegian, Norway)
@@ -414,8 +449,8 @@ void tst_QLocale::defaulted_ctor()
TEST_CTOR("nb_NO", Norwegian, Norway)
TEST_CTOR("nn_NO", NorwegianNynorsk, Norway)
TEST_CTOR("es_ES", Spanish, Spain)
- TEST_CTOR("es_419", Spanish, LatinAmericaAndTheCaribbean)
- TEST_CTOR("es-419", Spanish, LatinAmericaAndTheCaribbean)
+ TEST_CTOR("es_419", Spanish, LatinAmerica)
+ TEST_CTOR("es-419", Spanish, LatinAmerica)
TEST_CTOR("fr_MA", French, Morocco)
// test default countries for languages
@@ -464,7 +499,8 @@ static inline bool runSysApp(const QString &binary,
process.start(binary);
process.closeWriteChannel();
if (!process.waitForStarted()) {
- *errorMessage = QString::fromLatin1("Cannot start '%1': %2").arg(binary, process.errorString());
+ *errorMessage = QLatin1String("Cannot start '") + binary
+ + QLatin1String("': ") + process.errorString();
return false;
}
if (!process.waitForFinished()) {
@@ -488,94 +524,121 @@ static inline bool runSysAppTest(const QString &binary,
return false;
if (output.isEmpty()) {
- *errorMessage = QString::fromLatin1("Empty output received for requested '%1' (expected '%2')").
- arg(requestedLocale, expectedOutput);
+ *errorMessage = QLatin1String("Empty output received for requested '") + requestedLocale
+ + QLatin1String("' (expected '") + expectedOutput + QLatin1String("')");
return false;
}
if (output != expectedOutput) {
- *errorMessage = QString::fromLatin1("Output mismatch for requested '%1': Expected '%2', got '%3'").
- arg(requestedLocale, expectedOutput, output);
+ *errorMessage = QLatin1String("Output mismatch for requested '") + requestedLocale
+ + QLatin1String("': Expected '") + expectedOutput + QLatin1String("', got '")
+ + output + QLatin1String("'");
return false;
}
return true;
}
#endif
-void tst_QLocale::emptyCtor()
+void tst_QLocale::emptyCtor_data()
{
#if !QT_CONFIG(process)
QSKIP("No qprocess support", SkipAll);
-#else
+#endif
#ifdef Q_OS_ANDROID
QSKIP("This test crashes on Android");
#endif
-#define TEST_CTOR(req_lc, exp_str) \
- { \
- /* Test constructor without arguments. Needs separate process */ \
- /* because of caching of the system locale. */ \
- QString errorMessage; \
- QVERIFY2(runSysAppTest(m_sysapp, env, QLatin1String(req_lc), QLatin1String(exp_str), &errorMessage), \
- qPrintable(errorMessage)); \
- }
- // Get an environment free of any locale-related variables
- QStringList env;
- foreach (QString const& entry, QProcess::systemEnvironment()) {
- if (entry.startsWith("LANG=") || entry.startsWith("LC_") || entry.startsWith("LANGUAGE="))
- continue;
- env << entry;
- }
+ QTest::addColumn<QString>("expected");
+
+#define ADD_CTOR_TEST(give, expect) QTest::newRow(give) << QStringLiteral(expect);
+
+ // For format and meaning, see:
+ // http://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html
+ // Note that the accepted values for fields are implementation-dependent;
+ // the template is language[_territory][.codeset][@modifier]
+
+ // Vanilla:
+ ADD_CTOR_TEST("C", "C");
+
+ // Standard forms:
+ ADD_CTOR_TEST("en", "en_US");
+ ADD_CTOR_TEST("en_GB", "en_GB");
+ ADD_CTOR_TEST("de", "de_DE");
+ // Norsk has some quirks:
+ ADD_CTOR_TEST("no", "nb_NO");
+ ADD_CTOR_TEST("nb", "nb_NO");
+ ADD_CTOR_TEST("nn", "nn_NO");
+ ADD_CTOR_TEST("no_NO", "nb_NO");
+ ADD_CTOR_TEST("nb_NO", "nb_NO");
+ ADD_CTOR_TEST("nn_NO", "nn_NO");
+
+ // Not too fussy about case:
+ ADD_CTOR_TEST("DE", "de_DE");
+ ADD_CTOR_TEST("EN", "en_US");
+
+ // Invalid fields
+ ADD_CTOR_TEST("bla", "C");
+ ADD_CTOR_TEST("zz", "C");
+ ADD_CTOR_TEST("zz_zz", "C");
+ ADD_CTOR_TEST("zz...", "C");
+ ADD_CTOR_TEST("en.bla", "en_US");
+#if !(defined(Q_OS_DARWIN) && QT_HAS_FEATURE(address_sanitizer))
+ // See QTBUG-69875
+ ADD_CTOR_TEST("en@bla", "en_US");
+#endif
+ ADD_CTOR_TEST("en_blaaa", "en_US");
+ ADD_CTOR_TEST("en_zz", "en_US");
+ ADD_CTOR_TEST("en_GB.bla", "en_GB");
+ ADD_CTOR_TEST("en_GB@.bla", "en_GB");
+ ADD_CTOR_TEST("en_GB@bla", "en_GB");
+
+ // Empty optional fields, but with punctuators supplied
+ ADD_CTOR_TEST("en.", "en_US");
+#if !(defined(Q_OS_DARWIN) && QT_HAS_FEATURE(address_sanitizer))
+ // See QTBUG-69875
+ ADD_CTOR_TEST("en@", "en_US");
+#endif
+ ADD_CTOR_TEST("en.@", "en_US");
+ ADD_CTOR_TEST("en_", "en_US");
+ ADD_CTOR_TEST("en_.", "en_US");
+ ADD_CTOR_TEST("en_.@", "en_US");
+#undef ADD_CTOR_TEST
+#if QT_CONFIG(process) // for runSysApp
// Get default locale.
QString defaultLoc;
QString errorMessage;
- QVERIFY2(runSysApp(m_sysapp, env, &defaultLoc, &errorMessage),
- qPrintable(errorMessage));
-
- TEST_CTOR("C", "C")
- TEST_CTOR("bla", "C")
- TEST_CTOR("zz", "C")
- TEST_CTOR("zz_zz", "C")
- TEST_CTOR("zz...", "C")
- TEST_CTOR("en", "en_US")
- TEST_CTOR("en", "en_US")
- TEST_CTOR("en.", "en_US")
- TEST_CTOR("en@", "en_US")
- TEST_CTOR("en.@", "en_US")
- TEST_CTOR("en_", "en_US")
- TEST_CTOR("en_.", "en_US")
- TEST_CTOR("en_.@", "en_US")
- TEST_CTOR("en.bla", "en_US")
- TEST_CTOR("en@bla", "en_US")
- TEST_CTOR("en_blaaa", "en_US")
- TEST_CTOR("en_zz", "en_US")
- TEST_CTOR("en_GB", "en_GB")
- TEST_CTOR("en_GB.bla", "en_GB")
- TEST_CTOR("en_GB@.bla", "en_GB")
- TEST_CTOR("en_GB@bla", "en_GB")
- TEST_CTOR("de", "de_DE")
-
- QVERIFY(QLocale::Norwegian == QLocale::NorwegianBokmal);
- TEST_CTOR("no", "nb_NO")
- TEST_CTOR("nb", "nb_NO")
- TEST_CTOR("nn", "nn_NO")
- TEST_CTOR("no_NO", "nb_NO")
- TEST_CTOR("nb_NO", "nb_NO")
- TEST_CTOR("nn_NO", "nn_NO")
+ if (runSysApp(m_sysapp, cleanEnv, &defaultLoc, &errorMessage)) {
+#define ADD_CTOR_TEST(give) QTest::newRow(give) << defaultLoc;
+ ADD_CTOR_TEST("en/");
+ ADD_CTOR_TEST("asdfghj");
+ ADD_CTOR_TEST("123456");
+#undef ADD_CTOR_TEST
+ } else {
+ qDebug() << "Skipping tests based on default locale" << qPrintable(errorMessage);
+ }
+#endif // process
+}
- TEST_CTOR("DE", "de_DE");
- TEST_CTOR("EN", "en_US");
+void tst_QLocale::emptyCtor()
+{
+#if QT_CONFIG(process) // for runSysAppTest
+ QLatin1String request(QTest::currentDataTag());
+ QFETCH(QString, expected);
- TEST_CTOR("en/", defaultLoc.toLatin1())
- TEST_CTOR("asdfghj", defaultLoc.toLatin1());
- TEST_CTOR("123456", defaultLoc.toLatin1());
+ // Test constructor without arguments (see syslocaleapp/syslocaleapp.cpp)
+ // Needs separate process because of caching of the system locale.
+ QString errorMessage;
+ QVERIFY2(runSysAppTest(m_sysapp, cleanEnv, request, expected, &errorMessage),
+ qPrintable(errorMessage));
-#undef TEST_CTOR
-#endif
+#else
+ // This won't be called, as _data() skipped out early.
+#endif // process
}
void tst_QLocale::legacyNames()
{
+ QVERIFY(QLocale::Norwegian == QLocale::NorwegianBokmal);
QLocale::setDefault(QLocale(QLocale::C));
#define TEST_CTOR(req_lang, req_country, exp_lang, exp_country) \
@@ -598,8 +661,9 @@ void tst_QLocale::legacyNames()
QVERIFY2(l.language() == QLocale::exp_lang \
&& l.country() == QLocale::exp_country, \
QString("requested: \"" + QString(req_lc) + "\", got: " \
- + QLocale::languageToString(l.language()) \
- + QLatin1Char('/') + QLocale::countryToString(l.country())).toLatin1().constData()); \
+ + QLocale::languageToString(l.language()) \
+ + QLatin1Char('/') \
+ + QLocale::countryToString(l.country())).toLatin1().constData()); \
}
TEST_CTOR("mo_MD", Romanian, Moldova)
@@ -649,22 +713,32 @@ void tst_QLocale::matchingLocales()
QVERIFY(locales.contains(ru_RU));
}
+void tst_QLocale::unixLocaleName_data()
+{
+ QTest::addColumn<QLocale::Language>("lang");
+ QTest::addColumn<QLocale::Country>("land");
+ QTest::addColumn<QString>("expect");
+
+#define ADDROW(nom, lang, land, name) \
+ QTest::newRow(nom) << QLocale::lang << QLocale::land << QStringLiteral(name)
+
+ ADDROW("C_any", C, AnyCountry, "C");
+ ADDROW("en_any", English, AnyCountry, "en_US");
+ ADDROW("en_GB", English, UnitedKingdom, "en_GB");
+ ADDROW("ay_GB", Aymara, UnitedKingdom, "C");
+#undef ADDROW
+}
+
void tst_QLocale::unixLocaleName()
{
-#define TEST_NAME(req_lang, req_country, exp_name) \
- { \
- QLocale l(QLocale::req_lang, QLocale::req_country); \
- QCOMPARE(l.name(), QString(exp_name)); \
- }
+ QFETCH(QLocale::Language, lang);
+ QFETCH(QLocale::Country, land);
+ QFETCH(QString, expect);
QLocale::setDefault(QLocale(QLocale::C));
- TEST_NAME(C, AnyCountry, "C")
- TEST_NAME(English, AnyCountry, "en_US")
- TEST_NAME(English, UnitedKingdom, "en_GB")
- TEST_NAME(Aymara, UnitedKingdom, "C")
-
-#undef TEST_NAME
+ QLocale locale(lang, land);
+ QCOMPARE(locale.name(), expect);
}
void tst_QLocale::stringToDouble_data()
@@ -1282,7 +1356,8 @@ void tst_QLocale::formatDate_data()
QTest::newRow("26") << QDate(1974, 12, 1) << "\"yy\"" << "\"74\"";
QTest::newRow("27") << QDate(1974, 12, 1) << "'\"yy\"'" << "\"yy\"";
QTest::newRow("28") << QDate() << "'\"yy\"'" << "";
- QTest::newRow("29") << QDate(1974, 12, 1) << "hh:mm:ss.zzz ap d'd'dd/M/yy" << "hh:mm:ss.zzz ap 1d01/12/74";
+ QTest::newRow("29")
+ << QDate(1974, 12, 1) << "hh:mm:ss.zzz ap d'd'dd/M/yy" << "hh:mm:ss.zzz ap 1d01/12/74";
QTest::newRow("dd MMMM yyyy") << QDate(1, 1, 1) << "dd MMMM yyyy" << "01 January 0001";
}
@@ -1298,7 +1373,6 @@ void tst_QLocale::formatDate()
QCOMPARE(l.toString(date, QStringView(format)), result);
}
-
void tst_QLocale::formatTime_data()
{
QTest::addColumn<QTime>("time");
@@ -1577,7 +1651,8 @@ void tst_QLocale::formatTimeZone()
QDateTime::currentDateTime().timeZoneAbbreviation());
// Time on its own will always be current local time zone
- QCOMPARE(enUS.toString(QTime(1, 2, 3), "t"), QDateTime::currentDateTime().timeZoneAbbreviation());
+ QCOMPARE(enUS.toString(QTime(1, 2, 3), "t"),
+ QDateTime::currentDateTime().timeZoneAbbreviation());
}
void tst_QLocale::toDateTime_data()
@@ -1614,7 +1689,8 @@ void tst_QLocale::toDateTime_data()
QTest::newRow("bad-hour-C") << "C" << QDateTime() << "d-MMM-yy hh:m" << "4-Jun-11 1:2";
QTest::newRow("bad-min-C") << "C" << QDateTime() << "d-MMM-yy h:mm" << "4-Jun-11 1:2";
QTest::newRow("bad-sec-C") << "C" << QDateTime() << "d-MMM-yy h:m:ss" << "4-Jun-11 1:2:3";
- QTest::newRow("bad-milli-C") << "C" << QDateTime() << "d-MMM-yy h:m:s.zzz" << "4-Jun-11 1:2:3.4";
+ QTest::newRow("bad-milli-C")
+ << "C" << QDateTime() << "d-MMM-yy h:m:s.zzz" << "4-Jun-11 1:2:3.4";
QTest::newRow("ok-C") << "C" << QDateTime(QDate(1911, 6, 4), QTime(1, 2, 3, 400))
<< "d-MMM-yy h:m:s.z" << "4-Jun-11 1:2:3.4";
@@ -1637,11 +1713,13 @@ void tst_QLocale::toDateTime_data()
QTest::newRow("12no_NO") << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 0, 0))
<< "d'd'dd/M/yyh" << "1d01/12/7415";
- QTest::newRow("RFC-1123") << "C" << QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30))
- << "ddd, dd MMM yyyy hh:mm:ss 'GMT'" << "Thu, 01 Nov 2007 18:08:30 GMT";
+ QTest::newRow("RFC-1123")
+ << "C" << QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30))
+ << "ddd, dd MMM yyyy hh:mm:ss 'GMT'" << "Thu, 01 Nov 2007 18:08:30 GMT";
- QTest::newRow("longFormat") << "en_US" << QDateTime(QDate(2009, 1, 5), QTime(11, 48, 32))
- << "dddd, MMMM d, yyyy h:mm:ss AP " << "Monday, January 5, 2009 11:48:32 AM ";
+ QTest::newRow("longFormat")
+ << "en_US" << QDateTime(QDate(2009, 1, 5), QTime(11, 48, 32))
+ << "dddd, MMMM d, yyyy h:mm:ss AP " << "Monday, January 5, 2009 11:48:32 AM ";
}
void tst_QLocale::toDateTime()
@@ -1716,36 +1794,40 @@ void tst_QLocale::macDefaultLocale()
// To run this test make sure "Curreny" is US Dollar in System Preferences->Language & Region->Advanced.
if (locale.currencySymbol() == QString("$")) {
- QCOMPARE(locale.toCurrencyString(qulonglong(1234)), systemLocaleFormatNumber(QString("$1,234.00")));
- QCOMPARE(locale.toCurrencyString(double(1234.56)), systemLocaleFormatNumber(QString("$1,234.56")));
+ QCOMPARE(locale.toCurrencyString(qulonglong(1234)),
+ systemLocaleFormatNumber(QString("$1,234.00")));
+ QCOMPARE(locale.toCurrencyString(double(1234.56)),
+ systemLocaleFormatNumber(QString("$1,234.56")));
}
// Depending on the configured time zone, the time string might not
// contain a GMT specifier. (Sometimes it just names the zone, like "CEST")
- if (timeString.contains(QString("GMT"))) {
- QString expectedGMTSpecifierBase("GMT");
- if (diff >= 0)
- expectedGMTSpecifierBase.append(QLatin1Char('+'));
- else
- expectedGMTSpecifierBase.append(QLatin1Char('-'));
-
- QString expectedGMTSpecifier = expectedGMTSpecifierBase + QString("%1").arg(qAbs(diff));
- QString expectedGMTSpecifierZeroExtended = expectedGMTSpecifierBase + QString("0%1").arg(qAbs(diff));
-
- QVERIFY2(timeString.contains(expectedGMTSpecifier)
- || timeString.contains(expectedGMTSpecifierZeroExtended),
- qPrintable(QString("timeString `%1', expectedGMTSpecifier `%2' or `%3'")
- .arg(timeString)
- .arg(expectedGMTSpecifier)
- .arg(expectedGMTSpecifierZeroExtended)
- ));
+ QLatin1String gmt("GMT");
+ if (timeString.contains(gmt) && diff) {
+ QLatin1Char sign(diff < 0 ? '-' : '+');
+ QString number(QString::number(qAbs(diff)));
+ const QString expect = gmt + sign + number;
+
+ if (diff < 10) {
+ const QString zeroed = gmt + sign + QLatin1Char('0') + number;
+
+ QVERIFY2(timeString.contains(expect) || timeString.contains(zeroed),
+ qPrintable(QString("timeString `%1', expected GMT specifier `%2' or `%3'")
+ .arg(timeString).arg(expect).arg(zeroed)));
+ } else {
+ QVERIFY2(timeString.contains(expect),
+ qPrintable(QString("timeString `%1', expected GMT specifier `%2'")
+ .arg(timeString).arg(expect)));
+ }
}
QCOMPARE(locale.dayName(1), QString("Monday"));
QCOMPARE(locale.dayName(7), QString("Sunday"));
QCOMPARE(locale.monthName(1), QString("January"));
QCOMPARE(locale.monthName(12), QString("December"));
- QCOMPARE(locale.quoteString("string"), QString::fromUtf8("\xe2\x80\x9c" "string" "\xe2\x80\x9d"));
- QCOMPARE(locale.quoteString("string", QLocale::AlternateQuotation), QString::fromUtf8("\xe2\x80\x98" "string" "\xe2\x80\x99"));
+ QCOMPARE(locale.quoteString("string"),
+ QString::fromUtf8("\xe2\x80\x9c" "string" "\xe2\x80\x9d"));
+ QCOMPARE(locale.quoteString("string", QLocale::AlternateQuotation),
+ QString::fromUtf8("\xe2\x80\x98" "string" "\xe2\x80\x99"));
QList<Qt::DayOfWeek> days;
days << Qt::Monday << Qt::Tuesday << Qt::Wednesday << Qt::Thursday << Qt::Friday;
@@ -1787,12 +1869,6 @@ static void setWinLocaleInfo(LCTYPE type, const QString &value)
# define LOCALE_SSHORTTIME 0x00000079
#endif
-static inline LCTYPE shortTimeType()
-{
- return (QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) && QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7 ?
- LOCALE_SSHORTTIME : LOCALE_STIMEFORMAT;
-}
-
class RestoreLocaleHelper {
public:
RestoreLocaleHelper() {
@@ -1800,7 +1876,7 @@ public:
m_thousand = getWinLocaleInfo(LOCALE_STHOUSAND);
m_sdate = getWinLocaleInfo(LOCALE_SSHORTDATE);
m_ldate = getWinLocaleInfo(LOCALE_SLONGDATE);
- m_time = getWinLocaleInfo(shortTimeType());
+ m_time = getWinLocaleInfo(LOCALE_SSHORTTIME);
}
~RestoreLocaleHelper() {
@@ -1809,7 +1885,7 @@ public:
setWinLocaleInfo(LOCALE_STHOUSAND, m_thousand);
setWinLocaleInfo(LOCALE_SSHORTDATE, m_sdate);
setWinLocaleInfo(LOCALE_SLONGDATE, m_ldate);
- setWinLocaleInfo(shortTimeType(), m_time);
+ setWinLocaleInfo(LOCALE_SSHORTTIME, m_time);
// make sure QLocale::system() gets updated
QLocalePrivate::updateSystemPrivate();
@@ -1819,14 +1895,9 @@ public:
};
-#endif // Q_OS_WIN
-
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
-
void tst_QLocale::windowsDefaultLocale()
{
RestoreLocaleHelper systemLocale;
- const bool win7OrLater = (QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) && QSysInfo::windowsVersion();
// set weird system defaults and make sure we're using them
setWinLocaleInfo(LOCALE_SDECIMAL, QLatin1String("@"));
setWinLocaleInfo(LOCALE_STHOUSAND, QLatin1String("?"));
@@ -1835,7 +1906,7 @@ void tst_QLocale::windowsDefaultLocale()
const QString longDateFormat = QStringLiteral("d@M@yyyy");
setWinLocaleInfo(LOCALE_SLONGDATE, longDateFormat);
const QString shortTimeFormat = QStringLiteral("h^m^s");
- setWinLocaleInfo(shortTimeType(), shortTimeFormat);
+ setWinLocaleInfo(LOCALE_SSHORTTIME, shortTimeFormat);
// make sure QLocale::system() gets updated
QLocalePrivate::updateSystemPrivate();
@@ -1847,21 +1918,24 @@ void tst_QLocale::windowsDefaultLocale()
QCOMPARE(locale.dateFormat(QLocale::ShortFormat), shortDateFormat);
QCOMPARE(locale.dateFormat(QLocale::LongFormat), longDateFormat);
QCOMPARE(locale.timeFormat(QLocale::ShortFormat), shortTimeFormat);
- QCOMPARE(locale.dateTimeFormat(QLocale::ShortFormat), shortDateFormat + QLatin1Char(' ') + shortTimeFormat);
- const QString expectedLongDateTimeFormat = longDateFormat + QLatin1Char(' ')
- + (win7OrLater ? QStringLiteral("h:mm:ss AP") : shortTimeFormat);
+ QCOMPARE(locale.dateTimeFormat(QLocale::ShortFormat),
+ shortDateFormat + QLatin1Char(' ') + shortTimeFormat);
+ const QString expectedLongDateTimeFormat
+ = longDateFormat + QLatin1Char(' ') + QStringLiteral("h:mm:ss AP");
QCOMPARE(locale.dateTimeFormat(QLocale::LongFormat), expectedLongDateTimeFormat);
// make sure we are using the system to parse them
QCOMPARE(locale.toString(1234.56), QString("1?234@56"));
QCOMPARE(locale.toString(QDate(1974, 12, 1), QLocale::ShortFormat), QString("1*12*1974"));
- QCOMPARE(locale.toString(QDate(1974, 12, 1), QLocale::NarrowFormat), locale.toString(QDate(1974, 12, 1), QLocale::ShortFormat));
+ QCOMPARE(locale.toString(QDate(1974, 12, 1), QLocale::NarrowFormat),
+ locale.toString(QDate(1974, 12, 1), QLocale::ShortFormat));
QCOMPARE(locale.toString(QDate(1974, 12, 1), QLocale::LongFormat), QString("1@12@1974"));
const QString expectedFormattedShortTimeSeconds = QStringLiteral("1^2^3");
- const QString expectedFormattedShortTime = win7OrLater ? QStringLiteral("1^2") : expectedFormattedShortTimeSeconds;
+ const QString expectedFormattedShortTime = QStringLiteral("1^2");
QCOMPARE(locale.toString(QTime(1,2,3), QLocale::ShortFormat), expectedFormattedShortTime);
- QCOMPARE(locale.toString(QTime(1,2,3), QLocale::NarrowFormat), locale.toString(QTime(1,2,3), QLocale::ShortFormat));
- const QString expectedFormattedLongTime = win7OrLater ? QStringLiteral("1:02:03 AM") : expectedFormattedShortTimeSeconds;
+ QCOMPARE(locale.toString(QTime(1,2,3), QLocale::NarrowFormat),
+ locale.toString(QTime(1,2,3), QLocale::ShortFormat));
+ const QString expectedFormattedLongTime = QStringLiteral("1:02:03 AM");
QCOMPARE(locale.toString(QTime(1,2,3), QLocale::LongFormat), expectedFormattedLongTime);
QCOMPARE(locale.toString(QDateTime(QDate(1974, 12, 1), QTime(1,2,3)), QLocale::ShortFormat),
QStringLiteral("1*12*1974 ") + expectedFormattedShortTime);
@@ -1871,7 +1945,7 @@ void tst_QLocale::windowsDefaultLocale()
QStringLiteral("1@12@1974 ") + expectedFormattedLongTime);
QCOMPARE(locale.toString(QTime(1,2,3), QLocale::LongFormat), expectedFormattedLongTime);
}
-#endif // #ifdef Q_OS_WIN
+#endif // Q_OS_WIN but !Q_OS_WINRT
void tst_QLocale::numberOptions()
{
@@ -2056,17 +2130,23 @@ void tst_QLocale::dayName_data()
QTest::addColumn<int>("day");
QTest::addColumn<QLocale::FormatType>("format");
- QTest::newRow("no_NO") << QString("no_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
- QTest::newRow("nb_NO") << QString("nb_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
- QTest::newRow("nn_NO") << QString("nn_NO") << QString("tysdag") << 2 << QLocale::LongFormat;
+ QTest::newRow("no_NO") << QString("no_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
+ QTest::newRow("nb_NO") << QString("nb_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
+ QTest::newRow("nn_NO") << QString("nn_NO") << QString("tysdag") << 2 << QLocale::LongFormat;
- QTest::newRow("C long") << QString("C") << QString("Sunday") << 7 << QLocale::LongFormat;
- QTest::newRow("C short") << QString("C") << QString("Sun") << 7 << QLocale::ShortFormat;
- QTest::newRow("C narrow") << QString("C") << QString("7") << 7 << QLocale::NarrowFormat;
+ QTest::newRow("C long") << QString("C") << QString("Sunday") << 7 << QLocale::LongFormat;
+ QTest::newRow("C short") << QString("C") << QString("Sun") << 7 << QLocale::ShortFormat;
+ QTest::newRow("C narrow") << QString("C") << QString("7") << 7 << QLocale::NarrowFormat;
- QTest::newRow("ru_RU long") << QString("ru_RU") << QString::fromUtf8("\320\262\320\276\321\201\320\272\321\200\320\265\321\201\320\265\320\275\321\214\320\265") << 7 << QLocale::LongFormat;
- QTest::newRow("ru_RU short") << QString("ru_RU") << QString::fromUtf8("\320\262\321\201") << 7 << QLocale::ShortFormat;
- QTest::newRow("ru_RU narrow") << QString("ru_RU") << QString::fromUtf8("\320\262\321\201") << 7 << QLocale::NarrowFormat;
+ QTest::newRow("ru_RU long")
+ << QString("ru_RU")
+ << QString::fromUtf8("\320\262\320\276\321\201\320\272\321\200\320"
+ "\265\321\201\320\265\320\275\321\214\320\265")
+ << 7 << QLocale::LongFormat;
+ QTest::newRow("ru_RU short")
+ << QString("ru_RU") << QString::fromUtf8("\320\262\321\201") << 7 << QLocale::ShortFormat;
+ QTest::newRow("ru_RU narrow")
+ << QString("ru_RU") << QString::fromUtf8("\320\262\321\201") << 7 << QLocale::NarrowFormat;
}
void tst_QLocale::dayName()
@@ -2096,24 +2176,30 @@ void tst_QLocale::standaloneDayName_data()
QTest::addColumn<int>("day");
QTest::addColumn<QLocale::FormatType>("format");
- QTest::newRow("no_NO") << QString("no_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
- QTest::newRow("nb_NO") << QString("nb_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
- QTest::newRow("nn_NO") << QString("nn_NO") << QString("tysdag") << 2 << QLocale::LongFormat;
+ QTest::newRow("no_NO") << QString("no_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
+ QTest::newRow("nb_NO") << QString("nb_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
+ QTest::newRow("nn_NO") << QString("nn_NO") << QString("tysdag") << 2 << QLocale::LongFormat;
- QTest::newRow("C invalid: 0 long") << QString("C") << QString() << 0 << QLocale::LongFormat;
- QTest::newRow("C invalid: 0 short") << QString("C") << QString() << 0 << QLocale::ShortFormat;
- QTest::newRow("C invalid: 0 narrow") << QString("C") << QString() << 0 << QLocale::NarrowFormat;
- QTest::newRow("C invalid: 8 long") << QString("C") << QString() << 8 << QLocale::LongFormat;
- QTest::newRow("C invalid: 8 short") << QString("C") << QString() << 8 << QLocale::ShortFormat;
- QTest::newRow("C invalid: 8 narrow") << QString("C") << QString() << 8 << QLocale::NarrowFormat;
+ QTest::newRow("C invalid: 0 long") << QString("C") << QString() << 0 << QLocale::LongFormat;
+ QTest::newRow("C invalid: 0 short") << QString("C") << QString() << 0 << QLocale::ShortFormat;
+ QTest::newRow("C invalid: 0 narrow") << QString("C") << QString() << 0 << QLocale::NarrowFormat;
+ QTest::newRow("C invalid: 8 long") << QString("C") << QString() << 8 << QLocale::LongFormat;
+ QTest::newRow("C invalid: 8 short") << QString("C") << QString() << 8 << QLocale::ShortFormat;
+ QTest::newRow("C invalid: 8 narrow") << QString("C") << QString() << 8 << QLocale::NarrowFormat;
- QTest::newRow("C long") << QString("C") << QString("Sunday") << 7 << QLocale::LongFormat;
- QTest::newRow("C short") << QString("C") << QString("Sun") << 7 << QLocale::ShortFormat;
- QTest::newRow("C narrow") << QString("C") << QString("S") << 7 << QLocale::NarrowFormat;
+ QTest::newRow("C long") << QString("C") << QString("Sunday") << 7 << QLocale::LongFormat;
+ QTest::newRow("C short") << QString("C") << QString("Sun") << 7 << QLocale::ShortFormat;
+ QTest::newRow("C narrow") << QString("C") << QString("S") << 7 << QLocale::NarrowFormat;
- QTest::newRow("ru_RU long") << QString("ru_RU") << QString::fromUtf8("\320\262\320\276\321\201\320\272\321\200\320\265\321\201\320\265\320\275\321\214\320\265") << 7 << QLocale::LongFormat;
- QTest::newRow("ru_RU short") << QString("ru_RU") << QString::fromUtf8("\320\262\321\201") << 7 << QLocale::ShortFormat;
- QTest::newRow("ru_RU narrow") << QString("ru_RU") << QString::fromUtf8("\320\222") << 7 << QLocale::NarrowFormat;
+ QTest::newRow("ru_RU long")
+ << QString("ru_RU")
+ << QString::fromUtf8("\320\262\320\276\321\201\320\272\321\200\320"
+ "\265\321\201\320\265\320\275\321\214\320\265")
+ << 7 << QLocale::LongFormat;
+ QTest::newRow("ru_RU short")
+ << QString("ru_RU") << QString::fromUtf8("\320\262\321\201") << 7 << QLocale::ShortFormat;
+ QTest::newRow("ru_RU narrow")
+ << QString("ru_RU") << QString::fromUtf8("\320\222") << 7 << QLocale::NarrowFormat;
}
void tst_QLocale::standaloneDayName()
@@ -2129,9 +2215,7 @@ void tst_QLocale::standaloneDayName()
void tst_QLocale::underflowOverflow()
{
- QString
-a(QLatin1String("0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e10"));
-
+ QString a(QLatin1String("0.") + QString(546, QLatin1Char('0')) + QLatin1String("1e10"));
bool ok = false;
double d = a.toDouble(&ok);
QVERIFY(!ok);
@@ -2160,75 +2244,56 @@ a(QLatin1String("0.0000000000000000000000000000000000000000000000000000000000000
QVERIFY(!ok);
}
-void tst_QLocale::defaultNumeringSystem()
+void tst_QLocale::defaultNumberingSystem_data()
{
- QLocale sk("sk_SK");
- QCOMPARE(sk.toString(123), QLatin1String("123"));
+ QTest::addColumn<QString>("expect");
- QLocale ta("ta_IN");
- QCOMPARE(ta.toString(123), QLatin1String("123"));
-
- QLocale te("te_IN");
- QCOMPARE(te.toString(123), QLatin1String("123"));
-
- QLocale hi("hi_IN");
- QCOMPARE(hi.toString(123), QLatin1String("123"));
-
- QLocale gu("gu_IN");
- QCOMPARE(gu.toString(123), QLatin1String("123"));
-
- QLocale kn("kn_IN");
- QCOMPARE(kn.toString(123), QLatin1String("123"));
-
- QLocale pa("pa_IN");
- QCOMPARE(pa.toString(123), QLatin1String("123"));
-
- QLocale ne("ne_IN");
- QCOMPARE(ne.toString(123), QString::fromUtf8("१२३"));
+ QTest::newRow("sk_SK") << QStringLiteral("123");
+ QTest::newRow("ta_IN") << QStringLiteral("123");
+ QTest::newRow("te_IN") << QStringLiteral("123");
+ QTest::newRow("hi_IN") << QStringLiteral("123");
+ QTest::newRow("gu_IN") << QStringLiteral("123");
+ QTest::newRow("kn_IN") << QStringLiteral("123");
+ QTest::newRow("pa_IN") << QStringLiteral("123");
+ QTest::newRow("ne_IN") << QString::fromUtf8("१२३");
+ QTest::newRow("mr_IN") << QString::fromUtf8("१२३");
+ QTest::newRow("ml_IN") << QStringLiteral("123");
+ QTest::newRow("kok_IN") << QStringLiteral("123");
+}
- QLocale mr("mr_IN");
- QCOMPARE(mr.toString(123), QString::fromUtf8("१२३"));
+void tst_QLocale::defaultNumberingSystem()
+{
+ QFETCH(QString, expect);
+ QLatin1String name(QTest::currentDataTag());
+ QLocale locale(name);
+ QCOMPARE(locale.toString(123), expect);
+}
- QLocale ml("ml_IN");
- QCOMPARE(ml.toString(123), QLatin1String("123"));
+void tst_QLocale::ampm_data()
+{
+ QTest::addColumn<QString>("morn");
+ QTest::addColumn<QString>("even");
- QLocale kok("kok_IN");
- QCOMPARE(kok.toString(123), QLatin1String("123"));
+ QTest::newRow("C") << QStringLiteral("AM") << QStringLiteral("PM");
+ QTest::newRow("de_DE") << QStringLiteral("AM") << QStringLiteral("PM");
+ QTest::newRow("sv_SE") << QStringLiteral("fm") << QStringLiteral("em");
+ QTest::newRow("nl_NL") << QStringLiteral("a.m.") << QStringLiteral("p.m.");
+ QTest::newRow("uk_UA") << QString::fromUtf8("\320\264\320\277")
+ << QString::fromUtf8("\320\277\320\277");
+ QTest::newRow("tr_TR") << QString::fromUtf8("\303\226\303\226")
+ << QString::fromUtf8("\303\226\123");
+ QTest::newRow("id_ID") << QStringLiteral("AM") << QStringLiteral("PM");
+ QTest::newRow("ta_LK") << QString::fromUtf8("முற்பகல்") << QString::fromUtf8("பிற்பகல்");
}
void tst_QLocale::ampm()
{
- QLocale c(QLocale::C);
- QCOMPARE(c.amText(), QLatin1String("AM"));
- QCOMPARE(c.pmText(), QLatin1String("PM"));
-
- QLocale de("de_DE");
- QCOMPARE(de.amText(), QLatin1String("vorm."));
- QCOMPARE(de.pmText(), QLatin1String("nachm."));
-
- QLocale sv("sv_SE");
- QCOMPARE(sv.amText(), QLatin1String("fm"));
- QCOMPARE(sv.pmText(), QLatin1String("em"));
-
- QLocale nn("nl_NL");
- QCOMPARE(nn.amText(), QLatin1String("a.m."));
- QCOMPARE(nn.pmText(), QLatin1String("p.m."));
-
- QLocale ua("uk_UA");
- QCOMPARE(ua.amText(), QString::fromUtf8("\320\264\320\277"));
- QCOMPARE(ua.pmText(), QString::fromUtf8("\320\277\320\277"));
-
- QLocale tr("tr_TR");
- QCOMPARE(tr.amText(), QString::fromUtf8("\303\226\303\226"));
- QCOMPARE(tr.pmText(), QString::fromUtf8("\303\226\123"));
-
- QLocale id("id_ID");
- QCOMPARE(id.amText(), QLatin1String("AM"));
- QCOMPARE(id.pmText(), QLatin1String("PM"));
-
- QLocale ta("ta_LK");
- QCOMPARE(ta.amText(), QString::fromUtf8("முற்பகல்"));
- QCOMPARE(ta.pmText(), QString::fromUtf8("பிற்பகல்"));
+ QFETCH(QString, morn);
+ QFETCH(QString, even);
+ QLatin1String name(QTest::currentDataTag());
+ QLocale locale(name == QLatin1String("C") ? QLocale(QLocale::C) : QLocale(name));
+ QCOMPARE(locale.amText(), morn);
+ QCOMPARE(locale.pmText(), even);
}
void tst_QLocale::dateFormat()
@@ -2310,8 +2375,10 @@ void tst_QLocale::monthName()
QCOMPARE(de.monthName(12, QLocale::NarrowFormat), QLatin1String("D"));
QLocale ru("ru_RU");
- QCOMPARE(ru.monthName(1, QLocale::LongFormat), QString::fromUtf8("\321\217\320\275\320\262\320\260\321\200\321\217"));
- QCOMPARE(ru.monthName(1, QLocale::ShortFormat), QString::fromUtf8("\321\217\320\275\320\262\56"));
+ QCOMPARE(ru.monthName(1, QLocale::LongFormat),
+ QString::fromUtf8("\321\217\320\275\320\262\320\260\321\200\321\217"));
+ QCOMPARE(ru.monthName(1, QLocale::ShortFormat),
+ QString::fromUtf8("\321\217\320\275\320\262\56"));
QCOMPARE(ru.monthName(1, QLocale::NarrowFormat), QString::fromUtf8("\320\257"));
QLocale ir("ga_IE");
@@ -2340,13 +2407,16 @@ void tst_QLocale::standaloneMonthName()
// For de_DE locale Unicode CLDR database doesn't contain standalone long months
// so just checking if the return value is the same as in monthName().
QCOMPARE(de.standaloneMonthName(12, QLocale::LongFormat), QLatin1String("Dezember"));
- QCOMPARE(de.standaloneMonthName(12, QLocale::LongFormat), de.monthName(12, QLocale::LongFormat));
+ QCOMPARE(de.standaloneMonthName(12, QLocale::LongFormat),
+ de.monthName(12, QLocale::LongFormat));
QCOMPARE(de.standaloneMonthName(12, QLocale::ShortFormat), QLatin1String("Dez"));
QCOMPARE(de.standaloneMonthName(12, QLocale::NarrowFormat), QLatin1String("D"));
QLocale ru("ru_RU");
- QCOMPARE(ru.standaloneMonthName(1, QLocale::LongFormat), QString::fromUtf8("\xd1\x8f\xd0\xbd\xd0\xb2\xd0\xb0\xd1\x80\xd1\x8c"));
- QCOMPARE(ru.standaloneMonthName(1, QLocale::ShortFormat), QString::fromUtf8("\xd1\x8f\xd0\xbd\xd0\xb2."));
+ QCOMPARE(ru.standaloneMonthName(1, QLocale::LongFormat),
+ QString::fromUtf8("\xd1\x8f\xd0\xbd\xd0\xb2\xd0\xb0\xd1\x80\xd1\x8c"));
+ QCOMPARE(ru.standaloneMonthName(1, QLocale::ShortFormat),
+ QString::fromUtf8("\xd1\x8f\xd0\xbd\xd0\xb2."));
QCOMPARE(ru.standaloneMonthName(1, QLocale::NarrowFormat), QString::fromUtf8("\xd0\xaf"));
}
@@ -2371,19 +2441,30 @@ void tst_QLocale::currency()
QCOMPARE(en_US.toCurrencyString(double(-1234.56), NULL, 4), QString("$-1,234.5600"));
const QLocale ru_RU("ru_RU");
- QCOMPARE(ru_RU.toCurrencyString(qulonglong(1234)), QString::fromUtf8("1" "\xc2\xa0" "234\xc2\xa0\xe2\x82\xbd"));
- QCOMPARE(ru_RU.toCurrencyString(qlonglong(-1234)), QString::fromUtf8("-1" "\xc2\xa0" "234\xc2\xa0\xe2\x82\xbd"));
- QCOMPARE(ru_RU.toCurrencyString(double(1234.56)), QString::fromUtf8("1" "\xc2\xa0" "234,56\xc2\xa0\xe2\x82\xbd"));
- QCOMPARE(ru_RU.toCurrencyString(double(-1234.56)), QString::fromUtf8("-1" "\xc2\xa0" "234,56\xc2\xa0\xe2\x82\xbd"));
+ QCOMPARE(ru_RU.toCurrencyString(qulonglong(1234)),
+ QString::fromUtf8("1" "\xc2\xa0" "234\xc2\xa0\xe2\x82\xbd"));
+ QCOMPARE(ru_RU.toCurrencyString(qlonglong(-1234)),
+ QString::fromUtf8("-1" "\xc2\xa0" "234\xc2\xa0\xe2\x82\xbd"));
+ QCOMPARE(ru_RU.toCurrencyString(double(1234.56)),
+ QString::fromUtf8("1" "\xc2\xa0" "234,56\xc2\xa0\xe2\x82\xbd"));
+ QCOMPARE(ru_RU.toCurrencyString(double(-1234.56)),
+ QString::fromUtf8("-1" "\xc2\xa0" "234,56\xc2\xa0\xe2\x82\xbd"));
const QLocale de_DE("de_DE");
- QCOMPARE(de_DE.toCurrencyString(qulonglong(1234)), QString::fromUtf8("1.234\xc2\xa0\xe2\x82\xac"));
- QCOMPARE(de_DE.toCurrencyString(qulonglong(1234), QLatin1String("BAZ")), QString::fromUtf8("1.234\xc2\xa0" "BAZ"));
- QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234)), QString::fromUtf8("-1.234\xc2\xa0\xe2\x82\xac"));
- QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234), QLatin1String("BAZ")), QString::fromUtf8("-1.234\xc2\xa0" "BAZ"));
- QCOMPARE(de_DE.toCurrencyString(double(1234.56)), QString::fromUtf8("1.234,56\xc2\xa0\xe2\x82\xac"));
- QCOMPARE(de_DE.toCurrencyString(double(-1234.56)), QString::fromUtf8("-1.234,56\xc2\xa0\xe2\x82\xac"));
- QCOMPARE(de_DE.toCurrencyString(double(-1234.56), QLatin1String("BAZ")), QString::fromUtf8("-1.234,56\xc2\xa0" "BAZ"));
+ QCOMPARE(de_DE.toCurrencyString(qulonglong(1234)),
+ QString::fromUtf8("1.234\xc2\xa0\xe2\x82\xac"));
+ QCOMPARE(de_DE.toCurrencyString(qulonglong(1234), QLatin1String("BAZ")),
+ QString::fromUtf8("1.234\xc2\xa0" "BAZ"));
+ QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234)),
+ QString::fromUtf8("-1.234\xc2\xa0\xe2\x82\xac"));
+ QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234), QLatin1String("BAZ")),
+ QString::fromUtf8("-1.234\xc2\xa0" "BAZ"));
+ QCOMPARE(de_DE.toCurrencyString(double(1234.56)),
+ QString::fromUtf8("1.234,56\xc2\xa0\xe2\x82\xac"));
+ QCOMPARE(de_DE.toCurrencyString(double(-1234.56)),
+ QString::fromUtf8("-1.234,56\xc2\xa0\xe2\x82\xac"));
+ QCOMPARE(de_DE.toCurrencyString(double(-1234.56), QLatin1String("BAZ")),
+ QString::fromUtf8("-1.234,56\xc2\xa0" "BAZ"));
const QLocale es_CR(QLocale::Spanish, QLocale::CostaRica);
QCOMPARE(es_CR.toCurrencyString(double(1565.25)),
@@ -2398,11 +2479,13 @@ void tst_QLocale::quoteString()
const QString someText("text");
const QLocale c(QLocale::C);
QCOMPARE(c.quoteString(someText), QString::fromUtf8("\x22" "text" "\x22"));
- QCOMPARE(c.quoteString(someText, QLocale::AlternateQuotation), QString::fromUtf8("\x27" "text" "\x27"));
+ QCOMPARE(c.quoteString(someText, QLocale::AlternateQuotation),
+ QString::fromUtf8("\x27" "text" "\x27"));
const QLocale de_CH("de_CH");
QCOMPARE(de_CH.quoteString(someText), QString::fromUtf8("\xe2\x80\x9e" "text" "\xe2\x80\x9c"));
- QCOMPARE(de_CH.quoteString(someText, QLocale::AlternateQuotation), QString::fromUtf8("\xe2\x80\x9a" "text" "\xe2\x80\x98"));
+ QCOMPARE(de_CH.quoteString(someText, QLocale::AlternateQuotation),
+ QString::fromUtf8("\xe2\x80\x9a" "text" "\xe2\x80\x98"));
}
@@ -2484,23 +2567,28 @@ void tst_QLocale::listPatterns()
QCOMPARE(zh_CN.createSeparatedList(sl1), QString(""));
QCOMPARE(zh_CN.createSeparatedList(sl2), QString("aaa"));
QCOMPARE(zh_CN.createSeparatedList(sl3), QString::fromUtf8("aaa" "\xe5\x92\x8c" "bbb"));
- QCOMPARE(zh_CN.createSeparatedList(sl4), QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe5\x92\x8c" "ccc"));
- QCOMPARE(zh_CN.createSeparatedList(sl5), QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe3\x80\x81" "ccc" "\xe5\x92\x8c" "ddd"));
+ QCOMPARE(zh_CN.createSeparatedList(sl4),
+ QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe5\x92\x8c" "ccc"));
+ QCOMPARE(zh_CN.createSeparatedList(sl5),
+ QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe3\x80\x81"
+ "ccc" "\xe5\x92\x8c" "ddd"));
}
-void tst_QLocale::measurementSystems()
+void tst_QLocale::measurementSystems_data()
{
- QLocale locale(QLocale::English, QLocale::UnitedStates);
- QCOMPARE(locale.measurementSystem(), QLocale::ImperialUSSystem);
-
- locale = QLocale(QLocale::English, QLocale::UnitedKingdom);
- QCOMPARE(locale.measurementSystem(), QLocale::ImperialUKSystem);
-
- locale = QLocale(QLocale::English, QLocale::Australia);
- QCOMPARE(locale.measurementSystem(), QLocale::MetricSystem);
+ QTest::addColumn<QLocale>("locale");
+ QTest::addColumn<QLocale::MeasurementSystem>("system");
+ QTest::newRow("en_US") << QLocale(QLocale::English, QLocale::UnitedStates) << QLocale::ImperialUSSystem;
+ QTest::newRow("en_GB") << QLocale(QLocale::English, QLocale::UnitedKingdom) << QLocale::ImperialUKSystem;
+ QTest::newRow("en_AU") << QLocale(QLocale::English, QLocale::Australia) << QLocale::MetricSystem;
+ QTest::newRow("de") << QLocale(QLocale::German) << QLocale::MetricSystem;
+}
- locale = QLocale(QLocale::German);
- QCOMPARE(locale.measurementSystem(), QLocale::MetricSystem);
+void tst_QLocale::measurementSystems()
+{
+ QFETCH(QLocale, locale);
+ QFETCH(QLocale::MeasurementSystem, system);
+ QCOMPARE(locale.measurementSystem(), system);
}
void tst_QLocale::QTBUG_26035_positivesign()
@@ -2566,7 +2654,9 @@ void tst_QLocale::textDirection_data()
case QLocale::Uighur:
case QLocale::Urdu:
case QLocale::Yiddish:
- rightToLeft = QLocale(QLocale::Language(language)).language() == QLocale::Language(language); // false if there is no locale data for language
+ // false if there is no locale data for language:
+ rightToLeft = (QLocale(QLocale::Language(language)).language()
+ == QLocale::Language(language));
break;
default:
break;
@@ -2651,6 +2741,37 @@ void tst_QLocale::formattedDataSize_data()
#undef ROWQ
#undef ROWB
}
+
+ // Languages which don't use a Latin alphabet
+
+ const QLocale::DataSizeFormats iecFormat = QLocale::DataSizeIecFormat;
+ const QLocale::DataSizeFormats traditionalFormat = QLocale::DataSizeTraditionalFormat;
+ const QLocale::DataSizeFormats siFormat = QLocale::DataSizeSIFormat;
+ const QLocale::Language lang = QLocale::Russian;
+
+ QTest::newRow("Russian-IEC-0") << lang << 2 << iecFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B");
+ QTest::newRow("Russian-IEC-10") << lang << 2 << iecFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B");
+ // CLDR doesn't provide IEC prefixes (yet?) so they aren't getting translated
+ QTest::newRow("Russian-IEC-12Ki") << lang << 2 << iecFormat << 12345 << QString("12,06 KiB");
+ QTest::newRow("Russian-IEC-16Ki") << lang << 2 << iecFormat << 16384 << QString("16,00 KiB");
+ QTest::newRow("Russian-IEC-1235k") << lang << 2 << iecFormat << 1234567 << QString("1,18 MiB");
+ QTest::newRow("Russian-IEC-1374k") << lang << 2 << iecFormat << 1374744 << QString("1,31 MiB");
+ QTest::newRow("Russian-IEC-1234M") << lang << 2 << iecFormat << 1234567890 << QString("1,15 GiB");
+
+ QTest::newRow("Russian-Trad-0") << lang << 2 << traditionalFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B");
+ QTest::newRow("Russian-Trad-10") << lang << 2 << traditionalFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B");
+ QTest::newRow("Russian-Trad-12Ki") << lang << 2 << traditionalFormat << 12345 << QString("12,06 \u043A\u0411");
+ QTest::newRow("Russian-Trad-16Ki") << lang << 2 << traditionalFormat << 16384 << QString("16,00 \u043A\u0411");
+ QTest::newRow("Russian-Trad-1235k") << lang << 2 << traditionalFormat << 1234567 << QString("1,18 \u041C\u0411");
+ QTest::newRow("Russian-Trad-1374k") << lang << 2 << traditionalFormat << 1374744 << QString("1,31 \u041C\u0411");
+ QTest::newRow("Russian-Trad-1234M") << lang << 2 << traditionalFormat << 1234567890 << QString("1,15 \u0413\u0411");
+
+ QTest::newRow("Russian-Decimal-0") << lang << 2 << siFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B");
+ QTest::newRow("Russian-Decimal-10") << lang << 2 << siFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B");
+ QTest::newRow("Russian-Decimal-16Ki") << lang << 2 << siFormat << 16384 << QString("16,38 \u043A\u0411");
+ QTest::newRow("Russian-Decimal-1234k") << lang << 2 << siFormat << 1234567 << QString("1,23 \u041C\u0411");
+ QTest::newRow("Russian-Decimal-1374k") << lang << 2 << siFormat << 1374744 << QString("1,37 \u041C\u0411");
+ QTest::newRow("Russian-Decimal-1234M") << lang << 2 << siFormat << 1234567890 << QString("1,23 \u0413\u0411");
}
void tst_QLocale::formattedDataSize()
@@ -2663,25 +2784,33 @@ void tst_QLocale::formattedDataSize()
QCOMPARE(QLocale(language).formattedDataSize(bytes, decimalPlaces, units), output);
}
-void tst_QLocale::bcp47Name()
+void tst_QLocale::bcp47Name_data()
{
- QCOMPARE(QLocale("C").bcp47Name(), QStringLiteral("en"));
- QCOMPARE(QLocale("en").bcp47Name(), QStringLiteral("en"));
- QCOMPARE(QLocale("en_US").bcp47Name(), QStringLiteral("en"));
- QCOMPARE(QLocale("en_GB").bcp47Name(), QStringLiteral("en-GB"));
- QCOMPARE(QLocale("en_DE").bcp47Name(), QStringLiteral("en-DE"));
- QCOMPARE(QLocale("de_DE").bcp47Name(), QStringLiteral("de"));
- QCOMPARE(QLocale("sr_RS").bcp47Name(), QStringLiteral("sr"));
- QCOMPARE(QLocale("sr_Cyrl_RS").bcp47Name(), QStringLiteral("sr"));
- QCOMPARE(QLocale("sr_Latn_RS").bcp47Name(), QStringLiteral("sr-Latn"));
- QCOMPARE(QLocale("sr_ME").bcp47Name(), QStringLiteral("sr-ME"));
- QCOMPARE(QLocale("sr_Cyrl_ME").bcp47Name(), QStringLiteral("sr-Cyrl-ME"));
- QCOMPARE(QLocale("sr_Latn_ME").bcp47Name(), QStringLiteral("sr-ME"));
+ QTest::addColumn<QString>("expect");
+
+ QTest::newRow("C") << QStringLiteral("en");
+ QTest::newRow("en") << QStringLiteral("en");
+ QTest::newRow("en_US") << QStringLiteral("en");
+ QTest::newRow("en_GB") << QStringLiteral("en-GB");
+ QTest::newRow("en_DE") << QStringLiteral("en-DE");
+ QTest::newRow("de_DE") << QStringLiteral("de");
+ QTest::newRow("sr_RS") << QStringLiteral("sr");
+ QTest::newRow("sr_Cyrl_RS") << QStringLiteral("sr");
+ QTest::newRow("sr_Latn_RS") << QStringLiteral("sr-Latn");
+ QTest::newRow("sr_ME") << QStringLiteral("sr-ME");
+ QTest::newRow("sr_Cyrl_ME") << QStringLiteral("sr-Cyrl-ME");
+ QTest::newRow("sr_Latn_ME") << QStringLiteral("sr-ME");
// Fall back to defaults when country isn't in CLDR for this language:
- QCOMPARE(QLocale("sr_HR").bcp47Name(), QStringLiteral("sr"));
- QCOMPARE(QLocale("sr_Cyrl_HR").bcp47Name(), QStringLiteral("sr"));
- QCOMPARE(QLocale("sr_Latn_HR").bcp47Name(), QStringLiteral("sr-Latn"));
+ QTest::newRow("sr_HR") << QStringLiteral("sr");
+ QTest::newRow("sr_Cyrl_HR") << QStringLiteral("sr");
+ QTest::newRow("sr_Latn_HR") << QStringLiteral("sr-Latn");
+}
+
+void tst_QLocale::bcp47Name()
+{
+ QFETCH(QString, expect);
+ QCOMPARE(QLocale(QLatin1String(QTest::currentDataTag())).bcp47Name(), expect);
}
class MySystemLocale : public QSystemLocale
diff --git a/tests/auto/corelib/tools/qmacautoreleasepool/qmacautoreleasepool.pro b/tests/auto/corelib/tools/qmacautoreleasepool/qmacautoreleasepool.pro
index 26b3a47472..8599596344 100644
--- a/tests/auto/corelib/tools/qmacautoreleasepool/qmacautoreleasepool.pro
+++ b/tests/auto/corelib/tools/qmacautoreleasepool/qmacautoreleasepool.pro
@@ -2,3 +2,4 @@ CONFIG += testcase
TARGET = tst_qmacautoreleasepool
QT = core testlib
SOURCES = tst_qmacautoreleasepool.mm
+LIBS += -framework Foundation
diff --git a/tests/auto/corelib/tools/qmakearray/qmakearray.pro b/tests/auto/corelib/tools/qmakearray/qmakearray.pro
new file mode 100644
index 0000000000..abb3d9fdbc
--- /dev/null
+++ b/tests/auto/corelib/tools/qmakearray/qmakearray.pro
@@ -0,0 +1,4 @@
+CONFIG += testcase
+TARGET = tst_qmakearray
+QT = core testlib core-private
+SOURCES = $$PWD/tst_qmakearray.cpp
diff --git a/tests/auto/corelib/tools/qmakearray/tst_qmakearray.cpp b/tests/auto/corelib/tools/qmakearray/tst_qmakearray.cpp
new file mode 100644
index 0000000000..e0d3f52719
--- /dev/null
+++ b/tests/auto/corelib/tools/qmakearray/tst_qmakearray.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <private/qmakearray_p.h>
+
+
+class tst_QMakeArray : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void quicksort();
+};
+
+struct Pair {
+ unsigned int key;
+ unsigned int val;
+
+ constexpr bool operator <=(const Pair &that) const noexcept
+ {
+ return key <= that.key;
+ }
+
+ constexpr bool operator<(const Pair &that) const noexcept
+ {
+ return key < that.key;
+ }
+
+ constexpr bool operator==(const Pair &that) const noexcept
+ {
+ return key == that.key;
+ }
+};
+
+template<std::size_t Key, std::size_t Val>
+struct PairQuickSortElem
+{
+ using Type = Pair;
+ static constexpr Type data() noexcept { return Type{Key, Val}; }
+};
+
+void tst_QMakeArray::quicksort()
+{
+ constexpr const auto sorted_array = qMakeArray(
+ QSortedData<
+ PairQuickSortElem<10, 0>,
+ PairQuickSortElem<5, 0>,
+ PairQuickSortElem<7, 0>,
+ PairQuickSortElem<1, 0>,
+ PairQuickSortElem<8, 0>,
+ PairQuickSortElem<6, 0>,
+ PairQuickSortElem<4, 0>,
+ PairQuickSortElem<3, 0>,
+ PairQuickSortElem<1, 0>,
+ PairQuickSortElem<2, 0>,
+ PairQuickSortElem<10, 0>,
+ PairQuickSortElem<5, 0>
+ >::Data{});
+ static_assert(sorted_array.size() == 12, "sorted_array.size() != 12");
+ QCOMPARE(sorted_array[0].key, 1u);
+ QCOMPARE(sorted_array[1].key, 1u);
+ QCOMPARE(sorted_array[2].key, 2u);
+ QCOMPARE(sorted_array[3].key, 3u);
+ QCOMPARE(sorted_array[4].key, 4u);
+ QCOMPARE(sorted_array[5].key, 5u);
+ QCOMPARE(sorted_array[6].key, 5u);
+ QCOMPARE(sorted_array[7].key, 6u);
+ QCOMPARE(sorted_array[8].key, 7u);
+ QCOMPARE(sorted_array[9].key, 8u);
+ QCOMPARE(sorted_array[10].key, 10u);
+ QCOMPARE(sorted_array[11].key, 10u);
+}
+
+
+QTEST_APPLESS_MAIN(tst_QMakeArray)
+#include "tst_qmakearray.moc"
diff --git a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro b/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro
deleted file mode 100644
index a27286ff20..0000000000
--- a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qregularexpression_alwaysoptimize
-QT = core testlib
-HEADERS = ../tst_qregularexpression.h
-SOURCES = \
- tst_qregularexpression_alwaysoptimize.cpp \
- ../tst_qregularexpression.cpp
diff --git a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro b/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro
deleted file mode 100644
index 0b36c79c1b..0000000000
--- a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qregularexpression_defaultoptimize
-QT = core testlib
-HEADERS = ../tst_qregularexpression.h
-SOURCES = \
- tst_qregularexpression_defaultoptimize.cpp \
- ../tst_qregularexpression.cpp
diff --git a/tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro b/tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro
deleted file mode 100644
index 1db77781dd..0000000000
--- a/tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qregularexpression_forceoptimize
-QT = core testlib
-HEADERS = ../tst_qregularexpression.h
-SOURCES = \
- tst_qregularexpression_forceoptimize.cpp \
- ../tst_qregularexpression.cpp
-DEFINES += forceOptimize=true
diff --git a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro
index e1840808ff..ec8189717e 100644
--- a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro
+++ b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro
@@ -1,3 +1,4 @@
-TEMPLATE = subdirs
-SUBDIRS = defaultoptimize forceoptimize
-qtConfig(private_tests): SUBDIRS += alwaysoptimize
+CONFIG += testcase
+TARGET = tst_qregularexpression
+QT = core testlib
+SOURCES = tst_qregularexpression.cpp
diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
index c828551e44..c23ee3b0ba 100644
--- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
+++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
@@ -33,11 +33,60 @@
#include <qstringlist.h>
#include <qhash.h>
-#include "tst_qregularexpression.h"
+#include <qobject.h>
+#include <qregularexpression.h>
+#include <qthread.h>
-#ifndef forceOptimize
-#define forceOptimize false
-#endif
+Q_DECLARE_METATYPE(QRegularExpression::PatternOptions)
+Q_DECLARE_METATYPE(QRegularExpression::MatchType)
+Q_DECLARE_METATYPE(QRegularExpression::MatchOptions)
+
+class tst_QRegularExpression : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void defaultConstructors();
+ void gettersSetters_data();
+ void gettersSetters();
+ void escape_data();
+ void escape();
+ void validity_data();
+ void validity();
+ void patternOptions_data();
+ void patternOptions();
+ void normalMatch_data();
+ void normalMatch();
+ void partialMatch_data();
+ void partialMatch();
+ void globalMatch_data();
+ void globalMatch();
+ void serialize_data();
+ void serialize();
+ void operatoreq_data();
+ void operatoreq();
+ void captureCount_data();
+ void captureCount();
+ void captureNames_data();
+ void captureNames();
+ void pcreJitStackUsage_data();
+ void pcreJitStackUsage();
+ void regularExpressionMatch_data();
+ void regularExpressionMatch();
+ void JOptionUsage_data();
+ void JOptionUsage();
+ void QStringAndQStringRefEquivalence();
+ void threadSafety_data();
+ void threadSafety();
+
+ void wildcard_data();
+ void wildcard();
+ void testInvalidWildcard_data();
+ void testInvalidWildcard();
+
+private:
+ void provideRegularExpressions();
+};
struct Match
{
@@ -292,9 +341,6 @@ static void testMatch(const QRegularExpression &regexp,
QRegularExpression::MatchOptions matchOptions,
const Result &result)
{
- if (forceOptimize)
- regexp.optimize();
-
// test with QString as subject type
testMatchImpl<QREMatch>(regexp, matchingMethodForString, subject, offset, matchType, matchOptions, result);
@@ -401,30 +447,22 @@ void tst_QRegularExpression::gettersSetters()
{
QRegularExpression re;
re.setPattern(pattern);
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.pattern(), pattern);
QCOMPARE(re.patternOptions(), QRegularExpression::NoPatternOption);
}
{
QRegularExpression re;
re.setPatternOptions(patternOptions);
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.pattern(), QString());
QCOMPARE(re.patternOptions(), patternOptions);
}
{
QRegularExpression re(pattern);
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.pattern(), pattern);
QCOMPARE(re.patternOptions(), QRegularExpression::NoPatternOption);
}
{
QRegularExpression re(pattern, patternOptions);
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.pattern(), pattern);
QCOMPARE(re.patternOptions(), patternOptions);
}
@@ -465,8 +503,6 @@ void tst_QRegularExpression::escape()
QFETCH(QString, escaped);
QCOMPARE(QRegularExpression::escape(string), escaped);
QRegularExpression re(escaped);
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.isValid(), true);
}
@@ -497,8 +533,6 @@ void tst_QRegularExpression::validity()
QFETCH(QString, pattern);
QFETCH(bool, validity);
QRegularExpression re(pattern);
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.isValid(), validity);
if (!validity)
QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object");
@@ -585,9 +619,6 @@ void tst_QRegularExpression::patternOptions()
QFETCH(QString, subject);
QFETCH(Match, match);
- if (forceOptimize)
- regexp.optimize();
-
QRegularExpressionMatch m = regexp.match(subject);
consistencyCheck(m);
QVERIFY(m == match);
@@ -1403,9 +1434,6 @@ void tst_QRegularExpression::serialize()
QFETCH(QRegularExpression::PatternOptions, patternOptions);
QRegularExpression outRe(pattern, patternOptions);
- if (forceOptimize)
- outRe.optimize();
-
QByteArray buffer;
{
QDataStream out(&buffer, QIODevice::WriteOnly);
@@ -1468,33 +1496,18 @@ void tst_QRegularExpression::operatoreq()
QRegularExpression re1(pattern);
QRegularExpression re2(pattern);
- if (forceOptimize)
- re1.optimize();
- if (forceOptimize)
- re2.optimize();
-
verifyEquality(re1, re2);
}
{
QRegularExpression re1(QString(), patternOptions);
QRegularExpression re2(QString(), patternOptions);
- if (forceOptimize)
- re1.optimize();
- if (forceOptimize)
- re2.optimize();
-
verifyEquality(re1, re2);
}
{
QRegularExpression re1(pattern, patternOptions);
QRegularExpression re2(pattern, patternOptions);
- if (forceOptimize)
- re1.optimize();
- if (forceOptimize)
- re2.optimize();
-
verifyEquality(re1, re2);
}
}
@@ -1524,9 +1537,6 @@ void tst_QRegularExpression::captureCount()
QFETCH(QString, pattern);
QRegularExpression re(pattern);
- if (forceOptimize)
- re.optimize();
-
QTEST(re.captureCount(), "captureCount");
if (!re.isValid())
QCOMPARE(re.captureCount(), -1);
@@ -1595,9 +1605,6 @@ void tst_QRegularExpression::captureNames()
QRegularExpression re(pattern);
- if (forceOptimize)
- re.optimize();
-
QStringList namedCaptureGroups = re.namedCaptureGroups();
int namedCaptureGroupsCount = namedCaptureGroups.size();
@@ -1633,9 +1640,6 @@ void tst_QRegularExpression::pcreJitStackUsage()
QRegularExpression re(pattern);
- if (forceOptimize)
- re.optimize();
-
QVERIFY(re.isValid());
QRegularExpressionMatch match = re.match(subject);
consistencyCheck(match);
@@ -1663,9 +1667,6 @@ void tst_QRegularExpression::regularExpressionMatch()
QRegularExpression re(pattern);
- if (forceOptimize)
- re.optimize();
-
QVERIFY(re.isValid());
QRegularExpressionMatch match = re.match(subject);
consistencyCheck(match);
@@ -1705,8 +1706,6 @@ void tst_QRegularExpression::JOptionUsage()
QRegularExpression re(pattern);
if (isValid && JOptionUsed)
QTest::ignoreMessage(QtWarningMsg, qPrintable(warningMessage.arg(pattern)));
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.isValid(), isValid);
}
@@ -2066,3 +2065,190 @@ void tst_QRegularExpression::QStringAndQStringRefEquivalence()
}
}
}
+
+class MatcherThread : public QThread
+{
+public:
+ explicit MatcherThread(const QRegularExpression &re, const QString &subject, QObject *parent = nullptr)
+ : QThread(parent),
+ m_re(re),
+ m_subject(subject)
+ {
+ }
+
+private:
+ static const int MATCH_ITERATIONS = 50;
+
+ void run() override
+ {
+ yieldCurrentThread();
+ for (int i = 0; i < MATCH_ITERATIONS; ++i)
+ m_re.match(m_subject);
+ }
+
+ const QRegularExpression &m_re;
+ const QString &m_subject;
+};
+
+void tst_QRegularExpression::threadSafety_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QString>("subject");
+
+ int i = 0;
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abcd";
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abd";
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abbbbcccd";
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abababcd";
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abcabcd";
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abccccccababd";
+
+ {
+ QString subject(512*1024, QLatin1Char('x'));
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << subject;
+ }
+
+ // pcre2 does not support JIT for winrt. As this test row takes a long time without JIT we skip
+ // it for winrt as it might time out in COIN.
+#ifndef Q_OS_WINRT
+ {
+ QString subject = "ab";
+ subject.append(QString(512*1024, QLatin1Char('x')));
+ subject.append("c");
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << subject;
+ }
+#endif // Q_OS_WINRT
+
+ {
+ QString subject = "ab";
+ subject.append(QString(512*1024, QLatin1Char('x')));
+ subject.append("cd");
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << subject;
+ }
+
+ QTest::addRow("pattern%d", ++i) << "(?(R)a*(?1)|((?R))b)" << "aaaabcde";
+ QTest::addRow("pattern%d", ++i) << "(?(R)a*(?1)|((?R))b)" << "aaaaaaabcde";
+}
+
+void tst_QRegularExpression::threadSafety()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QString, subject);
+
+ QElapsedTimer time;
+ time.start();
+ static const int THREAD_SAFETY_ITERATIONS = 50;
+ const int threadCount = qMax(QThread::idealThreadCount(), 4);
+
+ for (int threadSafetyIteration = 0; threadSafetyIteration < THREAD_SAFETY_ITERATIONS && time.elapsed() < 2000; ++threadSafetyIteration) {
+ QRegularExpression re(pattern);
+
+ QVector<MatcherThread *> threads;
+ for (int i = 0; i < threadCount; ++i) {
+ MatcherThread *thread = new MatcherThread(re, subject);
+ thread->start();
+ threads.push_back(thread);
+ }
+
+ for (int i = 0; i < threadCount; ++i)
+ threads[i]->wait();
+
+ qDeleteAll(threads);
+ }
+}
+
+void tst_QRegularExpression::wildcard_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QString>("string");
+ QTest::addColumn<int>("foundIndex");
+
+ auto addRow = [](const char *pattern, const char *string, int foundIndex) {
+ QTest::newRow(pattern) << pattern << string << foundIndex;
+ };
+
+ addRow("*.html", "test.html", 0);
+ addRow("*.html", "test.htm", -1);
+ addRow("bar*", "foobarbaz", 3);
+ addRow("*", "Qt Rocks!", 0);
+ addRow(".html", "test.html", 4);
+ addRow(".h", "test.cpp", -1);
+ addRow(".???l", "test.html", 4);
+ addRow("?", "test.html", 0);
+ addRow("?m", "test.html", 6);
+ addRow("[*]", "test.html", -1);
+ addRow("[?]","test.html", -1);
+ addRow("[?]","test.h?ml", 6);
+ addRow("[[]","test.h[ml", 6);
+ addRow("[]]","test.h]ml", 6);
+ addRow(".h[a-z]ml", "test.html", 4);
+ addRow(".h[A-Z]ml", "test.html", -1);
+ addRow(".h[A-Z]ml", "test.hTml", 4);
+ addRow(".h[!A-Z]ml", "test.hTml", -1);
+ addRow(".h[!A-Z]ml", "test.html", 4);
+ addRow(".h[!T]ml", "test.hTml", -1);
+ addRow(".h[!T]ml", "test.html", 4);
+ addRow(".h[!T]m[!L]", "test.htmL", -1);
+ addRow(".h[!T]m[!L]", "test.html", 4);
+ addRow(".h[][!]", "test.h]ml", 4);
+ addRow(".h[][!]", "test.h[ml", 4);
+ addRow(".h[][!]", "test.h!ml", 4);
+
+ addRow("foo/*/bar", "Qt/foo/baz/bar", 3);
+ addRow("foo/(*)/bar", "Qt/foo/baz/bar", -1);
+ addRow("foo/(*)/bar", "Qt/foo/(baz)/bar", 3);
+ addRow("foo/?/bar", "Qt/foo/Q/bar", 3);
+ addRow("foo/?/bar", "Qt/foo/Qt/bar", -1);
+ addRow("foo/(?)/bar", "Qt/foo/Q/bar", -1);
+ addRow("foo/(?)/bar", "Qt/foo/(Q)/bar", 3);
+
+#ifdef Q_OS_WIN
+ addRow("foo\\*\\bar", "Qt\\foo\\baz\\bar", 3);
+ addRow("foo\\(*)\\bar", "Qt\\foo\\baz\\bar", -1);
+ addRow("foo\\(*)\\bar", "Qt\\foo\\(baz)\\bar", 3);
+ addRow("foo\\?\\bar", "Qt\\foo\\Q\\bar", 3);
+ addRow("foo\\?\\bar", "Qt\\foo\\Qt\\bar", -1);
+ addRow("foo\\(?)\\bar", "Qt\\foo\\Q\\bar", -1);
+ addRow("foo\\(?)\\bar", "Qt\\foo\\(Q)\\bar", 3);
+#endif
+}
+
+void tst_QRegularExpression::wildcard()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QString, string);
+ QFETCH(int, foundIndex);
+
+ QRegularExpression re(QRegularExpression::wildcardToRegularExpression(pattern));
+ QRegularExpressionMatch match = re.match(string);
+
+ QCOMPARE(match.capturedStart(), foundIndex);
+}
+
+void tst_QRegularExpression::testInvalidWildcard_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<bool>("isValid");
+
+ QTest::newRow("valid []") << "[abc]" << true;
+ QTest::newRow("valid ending ]") << "abc]" << true;
+ QTest::newRow("invalid [") << "[abc" << false;
+ QTest::newRow("ending [") << "abc[" << false;
+ QTest::newRow("ending [^") << "abc[^" << false;
+ QTest::newRow("ending [\\") << "abc[\\" << false;
+ QTest::newRow("ending []") << "abc[]" << false;
+ QTest::newRow("ending [[") << "abc[[" << false;
+}
+
+void tst_QRegularExpression::testInvalidWildcard()
+{
+ QFETCH(QString, pattern);
+ QFETCH(bool, isValid);
+
+ QRegularExpression re(QRegularExpression::wildcardToRegularExpression(pattern));
+ QCOMPARE(re.isValid(), isValid);
+}
+
+QTEST_APPLESS_MAIN(tst_QRegularExpression)
+
+#include "tst_qregularexpression.moc"
diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h
deleted file mode 100644
index 8bb4aa0cce..0000000000
--- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
-** 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 <qobject.h>
-#include <qregularexpression.h>
-
-Q_DECLARE_METATYPE(QRegularExpression::PatternOptions)
-Q_DECLARE_METATYPE(QRegularExpression::MatchType)
-Q_DECLARE_METATYPE(QRegularExpression::MatchOptions)
-
-class tst_QRegularExpression : public QObject
-{
- Q_OBJECT
-
-private slots:
- void defaultConstructors();
- void gettersSetters_data();
- void gettersSetters();
- void escape_data();
- void escape();
- void validity_data();
- void validity();
- void patternOptions_data();
- void patternOptions();
- void normalMatch_data();
- void normalMatch();
- void partialMatch_data();
- void partialMatch();
- void globalMatch_data();
- void globalMatch();
- void serialize_data();
- void serialize();
- void operatoreq_data();
- void operatoreq();
- void captureCount_data();
- void captureCount();
- void captureNames_data();
- void captureNames();
- void pcreJitStackUsage_data();
- void pcreJitStackUsage();
- void regularExpressionMatch_data();
- void regularExpressionMatch();
- void JOptionUsage_data();
- void JOptionUsage();
- void QStringAndQStringRefEquivalence();
-
-private:
- void provideRegularExpressions();
-};
diff --git a/tests/auto/corelib/tools/qscopeguard/qscopeguard.pro b/tests/auto/corelib/tools/qscopeguard/qscopeguard.pro
new file mode 100644
index 0000000000..070d4b077c
--- /dev/null
+++ b/tests/auto/corelib/tools/qscopeguard/qscopeguard.pro
@@ -0,0 +1,4 @@
+CONFIG += testcase
+TARGET = tst_qscopeguard
+QT = core testlib
+SOURCES = tst_qscopeguard.cpp
diff --git a/tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp
index 38a3a64fa3..f95d48f042 100644
--- a/tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp
+++ b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -27,13 +27,59 @@
****************************************************************************/
#include <QtTest/QtTest>
-#include "../tst_qregularexpression.h"
+#include <QtCore/QScopeGuard>
-class tst_QRegularExpression_ForceOptimize : public tst_QRegularExpression
+/*!
+ \class tst_QScopedGuard
+ \internal
+ \since 5.11
+ \brief Tests class QScopedCleanup and function qScopeGuard
+
+ */
+class tst_QScopedGuard : public QObject
{
Q_OBJECT
+
+private Q_SLOTS:
+ void leavingScope();
+ void exceptions();
};
-QTEST_APPLESS_MAIN(tst_QRegularExpression_ForceOptimize)
+static int s_globalState = 0;
+
+void tst_QScopedGuard::leavingScope()
+{
+ auto cleanup = qScopeGuard([] { s_globalState++; QCOMPARE(s_globalState, 3); });
+ QCOMPARE(s_globalState, 0);
+
+ {
+ auto cleanup = qScopeGuard([] { s_globalState++; });
+ QCOMPARE(s_globalState, 0);
+ }
+
+ QCOMPARE(s_globalState, 1);
+ s_globalState++;
+}
+
+void tst_QScopedGuard::exceptions()
+{
+ s_globalState = 0;
+ bool caught = false;
+ QT_TRY
+ {
+ auto cleanup = qScopeGuard([&caught] { s_globalState++; });
+ QT_THROW(std::bad_alloc()); //if Qt compiled without exceptions this is noop
+ s_globalState = 100;
+ }
+ QT_CATCH(...)
+ {
+ caught = true;
+ QCOMPARE(s_globalState, 1);
+ }
+
+ QVERIFY((caught && s_globalState == 1) || (!caught && s_globalState == 101));
+
+}
-#include "tst_qregularexpression_forceoptimize.moc"
+QTEST_MAIN(tst_QScopedGuard)
+#include "tst_qscopeguard.moc"
diff --git a/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp b/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp
index 3e1668522e..4dc620e6ab 100644
--- a/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp
+++ b/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp
@@ -53,6 +53,12 @@
# include <unistd.h>
#endif
+enum {
+ QMakeTimeout = 300000, // 5 minutes
+ CompileTimeout = 600000, // 10 minutes
+ RunTimeout = 300000 // 5 minutes
+};
+
static QString makespec()
{
static const char default_makespec[] = DEFAULT_MAKESPEC;
@@ -143,7 +149,7 @@ namespace QTest {
bool prepareSourceCode(const QByteArray &body);
bool createProjectFile();
bool runQmake();
- bool runMake(Target target);
+ bool runMake(Target target, int timeout);
bool commonSetup(const QByteArray &body);
};
@@ -602,7 +608,7 @@ namespace QTest {
std_err += "qmake: ";
std_err += qmake.errorString().toLocal8Bit();
} else {
- ok = qmake.waitForFinished();
+ ok = qmake.waitForFinished(QMakeTimeout);
exitCode = qmake.exitCode();
if (!ok)
QTest::ensureStopped(qmake);
@@ -617,7 +623,7 @@ namespace QTest {
#endif // QT_CONFIG(process)
}
- bool QExternalTestPrivate::runMake(Target target)
+ bool QExternalTestPrivate::runMake(Target target, int timeout)
{
#if !QT_CONFIG(process)
return false;
@@ -670,7 +676,7 @@ namespace QTest {
}
make.closeWriteChannel();
- bool ok = make.waitForFinished(channelMode == QProcess::ForwardedChannels ? -1 : 60000);
+ bool ok = make.waitForFinished(channelMode == QProcess::ForwardedChannels ? -1 : timeout);
if (!ok)
QTest::ensureStopped(make);
exitCode = make.exitCode();
@@ -705,7 +711,7 @@ namespace QTest {
failedStage = QExternalTest::CompilationStage;
std_out += "\n### --- stdout from make (compilation) --- ###\n";
std_err += "\n### --- stderr from make (compilation) --- ###\n";
- return runMake(Compile);
+ return runMake(Compile, CompileTimeout);
}
bool QExternalTestPrivate::tryLink(const QByteArray &body)
@@ -717,7 +723,7 @@ namespace QTest {
failedStage = QExternalTest::LinkStage;
std_out += "\n### --- stdout from make (linking) --- ###\n";
std_err += "\n### --- stderr from make (linking) --- ###\n";
- return runMake(Link);
+ return runMake(Link, CompileTimeout);
}
bool QExternalTestPrivate::tryRun(const QByteArray &body)
@@ -729,7 +735,7 @@ namespace QTest {
failedStage = QExternalTest::RunStage;
std_out += "\n### --- stdout from process --- ###\n";
std_err += "\n### --- stderr from process --- ###\n";
- return runMake(Run);
+ return runMake(Run, RunTimeout);
}
}
QT_END_NAMESPACE
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
index 2074c9789a..f429bda804 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
@@ -450,6 +450,8 @@ private slots:
void trimmed();
void toUpper();
void toLower();
+ void isUpper();
+ void isLower();
void toCaseFolded();
void rightJustified();
void leftJustified();
@@ -529,10 +531,8 @@ private slots:
void integer_conversion();
void tortureSprintfDouble();
void toNum();
-#if !defined(Q_OS_WIN)
void localeAwareCompare_data();
void localeAwareCompare();
-#endif
void reverseIterators();
void split_data();
void split();
@@ -2315,6 +2315,46 @@ void tst_QString::toLower()
#endif
}
+void tst_QString::isUpper()
+{
+ QVERIFY(!QString().isUpper());
+ QVERIFY(!QString("").isUpper());
+ QVERIFY(QString("TEXT").isUpper());
+ QVERIFY(!QString("text").isUpper());
+ QVERIFY(!QString("Text").isUpper());
+ QVERIFY(!QString("tExt").isUpper());
+ QVERIFY(!QString("teXt").isUpper());
+ QVERIFY(!QString("texT").isUpper());
+ QVERIFY(!QString("TExt").isUpper());
+ QVERIFY(!QString("teXT").isUpper());
+ QVERIFY(!QString("tEXt").isUpper());
+ QVERIFY(!QString("tExT").isUpper());
+ QVERIFY(!QString("@ABYZ[").isUpper());
+ QVERIFY(!QString("@abyz[").isUpper());
+ QVERIFY(!QString("`ABYZ{").isUpper());
+ QVERIFY(!QString("`abyz{").isUpper());
+}
+
+void tst_QString::isLower()
+{
+ QVERIFY(!QString().isLower());
+ QVERIFY(!QString("").isLower());
+ QVERIFY(QString("text").isLower());
+ QVERIFY(!QString("Text").isLower());
+ QVERIFY(!QString("tExt").isLower());
+ QVERIFY(!QString("teXt").isLower());
+ QVERIFY(!QString("texT").isLower());
+ QVERIFY(!QString("TExt").isLower());
+ QVERIFY(!QString("teXT").isLower());
+ QVERIFY(!QString("tEXt").isLower());
+ QVERIFY(!QString("tExT").isLower());
+ QVERIFY(!QString("TEXT").isLower());
+ QVERIFY(!QString("@ABYZ[").isLower());
+ QVERIFY(!QString("@abyz[").isLower());
+ QVERIFY(!QString("`ABYZ{").isLower());
+ QVERIFY(!QString("`abyz{").isLower());
+}
+
void tst_QString::toCaseFolded()
{
QCOMPARE( QString().toCaseFolded(), QString() );
@@ -5468,8 +5508,6 @@ void tst_QString::tortureSprintfDouble()
#include <locale.h>
-#if !defined(Q_OS_WIN)
-// On Q_OS_WIN, we cannot set the system or user locale
void tst_QString::localeAwareCompare_data()
{
QTest::addColumn<QString>("locale");
@@ -5477,6 +5515,46 @@ void tst_QString::localeAwareCompare_data()
QTest::addColumn<QString>("s2");
QTest::addColumn<int>("result");
+ // Compare decomposed and composed form
+ {
+ // From ES6 test262 test suite (built-ins/String/prototype/localeCompare/15.5.4.9_CE.js). The test cases boil down to code like this:
+ // console.log("\u1111\u1171\u11B6".localeCompare("\ud4db")
+
+ // example from Unicode 5.0, section 3.7, definition D70
+ QTest::newRow("normalize1") << QString() << QString::fromUtf8("o\xCC\x88") << QString::fromUtf8("\xC3\xB6") << 0;
+ // examples from Unicode 5.0, chapter 3.11
+ QTest::newRow("normalize2") << QString() << QString::fromUtf8("\xC3\xA4\xCC\xA3") << QString::fromUtf8("a\xCC\xA3\xCC\x88") << 0;
+ QTest::newRow("normalize3") << QString() << QString::fromUtf8("a\xCC\x88\xCC\xA3") << QString::fromUtf8("a\xCC\xA3\xCC\x88") << 0;
+ QTest::newRow("normalize4") << QString() << QString::fromUtf8("\xE1\xBA\xA1\xCC\x88") << QString::fromUtf8("a\xCC\xA3\xCC\x88") << 0;
+ QTest::newRow("normalize5") << QString() << QString::fromUtf8("\xC3\xA4\xCC\x86") << QString::fromUtf8("a\xCC\x88\xCC\x86") << 0;
+ QTest::newRow("normalize6") << QString() << QString::fromUtf8("\xC4\x83\xCC\x88") << QString::fromUtf8("a\xCC\x86\xCC\x88") << 0;
+ // example from Unicode 5.0, chapter 3.12
+ QTest::newRow("normalize7") << QString() << QString::fromUtf8("\xE1\x84\x91\xE1\x85\xB1\xE1\x86\xB6") << QString::fromUtf8("\xED\x93\x9B") << 0;
+ // examples from UTS 10, Unicode Collation Algorithm
+ QTest::newRow("normalize8") << QString() << QString::fromUtf8("\xE2\x84\xAB") << QString::fromUtf8("\xC3\x85") << 0;
+ QTest::newRow("normalize9") << QString() << QString::fromUtf8("\xE2\x84\xAB") << QString::fromUtf8("A\xCC\x8A") << 0;
+ QTest::newRow("normalize10") << QString() << QString::fromUtf8("x\xCC\x9B\xCC\xA3") << QString::fromUtf8("x\xCC\xA3\xCC\x9B") << 0;
+ QTest::newRow("normalize11") << QString() << QString::fromUtf8("\xE1\xBB\xB1") << QString::fromUtf8("\xE1\xBB\xA5\xCC\x9B") << 0;
+ QTest::newRow("normalize12") << QString() << QString::fromUtf8("\xE1\xBB\xB1") << QString::fromUtf8("u\xCC\x9B\xCC\xA3") << 0;
+ QTest::newRow("normalize13") << QString() << QString::fromUtf8("\xE1\xBB\xB1") << QString::fromUtf8("\xC6\xB0\xCC\xA3") << 0;
+ QTest::newRow("normalize14") << QString() << QString::fromUtf8("\xE1\xBB\xB1") << QString::fromUtf8("u\xCC\xA3\xCC\x9B") << 0;
+ // examples from UAX 15, Unicode Normalization Forms
+ QTest::newRow("normalize15") << QString() << QString::fromUtf8("\xC3\x87") << QString::fromUtf8("C\xCC\xA7") << 0;
+ QTest::newRow("normalize16") << QString() << QString::fromUtf8("q\xCC\x87\xCC\xA3") << QString::fromUtf8("q\xCC\xA3\xCC\x87") << 0;
+ QTest::newRow("normalize17") << QString() << QString::fromUtf8("\xEA\xB0\x80") << QString::fromUtf8("\xE1\x84\x80\xE1\x85\xA1") << 0;
+ QTest::newRow("normalize18") << QString() << QString::fromUtf8("\xE2\x84\xAB") << QString::fromUtf8("A\xCC\x8A") << 0;
+ QTest::newRow("normalize19") << QString() << QString::fromUtf8("\xE2\x84\xA6") << QString::fromUtf8("\xCE\xA9") << 0;
+ QTest::newRow("normalize20") << QString() << QString::fromUtf8("\xC3\x85") << QString::fromUtf8("A\xCC\x8A") << 0;
+ QTest::newRow("normalize21") << QString() << QString::fromUtf8("\xC3\xB4") << QString::fromUtf8("o\xCC\x82") << 0;
+ QTest::newRow("normalize22") << QString() << QString::fromUtf8("\xE1\xB9\xA9") << QString::fromUtf8("s\xCC\xA3\xCC\x87") << 0;
+ QTest::newRow("normalize23") << QString() << QString::fromUtf8("\xE1\xB8\x8B\xCC\xA3") << QString::fromUtf8("d\xCC\xA3\xCC\x87") << 0;
+ QTest::newRow("normalize24") << QString() << QString::fromUtf8("\xE1\xB8\x8B\xCC\xA3") << QString::fromUtf8("\xE1\xB8\x8D\xCC\x87") << 0;
+ QTest::newRow("normalize25") << QString() << QString::fromUtf8("q\xCC\x87\xCC\xA3") << QString::fromUtf8("q\xCC\xA3\xCC\x87") << 0;
+
+ }
+
+#if !defined(Q_OS_WIN)
+// On Q_OS_WIN, we cannot set the system or user locale
/*
The C locale performs pure byte comparisons for
Latin-1-specific characters (I think). Compare with Swedish
@@ -5537,6 +5615,7 @@ void tst_QString::localeAwareCompare_data()
QTest::newRow("german2") << QString("de_DE") << QString::fromLatin1("\xe4") << QString::fromLatin1("\xf6") << -1;
QTest::newRow("german3") << QString("de_DE") << QString::fromLatin1("z") << QString::fromLatin1("\xf6") << 1;
#endif
+#endif //!defined(Q_OS_WIN)
}
void tst_QString::localeAwareCompare()
@@ -5549,17 +5628,17 @@ void tst_QString::localeAwareCompare()
QStringRef r1(&s1, 0, s1.length());
QStringRef r2(&s2, 0, s2.length());
+ if (!locale.isEmpty()) {
#if defined (Q_OS_DARWIN) || defined(QT_USE_ICU)
- QSKIP("Setting the locale is not supported on OS X or ICU (you can set the C locale, but that won't affect localeAwareCompare)");
+ QSKIP("Setting the locale is not supported on OS X or ICU (you can set the C locale, but that won't affect localeAwareCompare)");
#else
- if (!locale.isEmpty()) {
const char *newLocale = setlocale(LC_ALL, locale.toLatin1());
if (!newLocale) {
setlocale(LC_ALL, "");
QSKIP("Please install the proper locale on this machine to test properly");
}
- }
#endif
+ }
#ifdef QT_USE_ICU
// ### for c1, ICU disagrees with libc on how to compare
@@ -5614,7 +5693,6 @@ void tst_QString::localeAwareCompare()
if (!locale.isEmpty())
setlocale(LC_ALL, "");
}
-#endif //!defined(Q_OS_WIN)
void tst_QString::reverseIterators()
{
@@ -6160,11 +6238,14 @@ void tst_QString::compare()
QStringRef r1(&s1, 0, s1.length());
QStringRef r2(&s2, 0, s2.length());
+ const QStringView v2(s2);
+
QCOMPARE(sign(QString::compare(s1, s2)), csr);
QCOMPARE(sign(QStringRef::compare(r1, r2)), csr);
QCOMPARE(sign(s1.compare(s2)), csr);
QCOMPARE(sign(s1.compare(r2)), csr);
QCOMPARE(sign(r1.compare(r2)), csr);
+ QCOMPARE(sign(s1.compare(v2)), csr);
QCOMPARE(sign(s1.compare(s2, Qt::CaseSensitive)), csr);
QCOMPARE(sign(s1.compare(s2, Qt::CaseInsensitive)), cir);
@@ -6172,6 +6253,8 @@ void tst_QString::compare()
QCOMPARE(sign(s1.compare(r2, Qt::CaseInsensitive)), cir);
QCOMPARE(sign(r1.compare(r2, Qt::CaseSensitive)), csr);
QCOMPARE(sign(r1.compare(r2, Qt::CaseInsensitive)), cir);
+ QCOMPARE(sign(s1.compare(v2, Qt::CaseSensitive)), csr);
+ QCOMPARE(sign(s1.compare(v2, Qt::CaseInsensitive)), cir);
QCOMPARE(sign(QString::compare(s1, s2, Qt::CaseSensitive)), csr);
QCOMPARE(sign(QString::compare(s1, s2, Qt::CaseInsensitive)), cir);
diff --git a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
index 9f054190e5..a3aec4c299 100644
--- a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
+++ b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
@@ -273,6 +273,15 @@ void tst_QStringList::contains()
QVERIFY(list.contains(QLatin1String("ARTHUR"), Qt::CaseInsensitive));
QVERIFY(list.contains(QLatin1String("dent"), Qt::CaseInsensitive));
QVERIFY(!list.contains(QLatin1String("hans"), Qt::CaseInsensitive));
+
+ QVERIFY(list.contains(QStringView(QString("arthur"))));
+ QVERIFY(!list.contains(QStringView(QString("ArthuR"))));
+ QVERIFY(!list.contains(QStringView(QString("Hans"))));
+ QVERIFY(list.contains(QStringView(QString("arthur")), Qt::CaseInsensitive));
+ QVERIFY(list.contains(QStringView(QString("ArthuR")), Qt::CaseInsensitive));
+ QVERIFY(list.contains(QStringView(QString("ARTHUR")), Qt::CaseInsensitive));
+ QVERIFY(list.contains(QStringView(QString("dent")), Qt::CaseInsensitive));
+ QVERIFY(!list.contains(QStringView(QString("hans")), Qt::CaseInsensitive));
}
void tst_QStringList::removeDuplicates_data()
diff --git a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
index 4ae96005d0..e800a0d794 100644
--- a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
+++ b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
@@ -217,6 +217,8 @@ private Q_SLOTS:
#endif
}
+ void comparison();
+
private:
template <typename String>
void conversion_tests(String arg) const;
@@ -615,5 +617,23 @@ void tst_QStringView::conversion_tests(String string) const
}
}
+void tst_QStringView::comparison()
+{
+ const QStringView aa = QStringViewLiteral("aa");
+ const QStringView upperAa = QStringViewLiteral("AA");
+ const QStringView bb = QStringViewLiteral("bb");
+
+ QVERIFY(aa == aa);
+ QVERIFY(aa != bb);
+ QVERIFY(aa < bb);
+ QVERIFY(bb > aa);
+
+ QCOMPARE(aa.compare(aa), 0);
+ QVERIFY(aa.compare(upperAa) != 0);
+ QCOMPARE(aa.compare(upperAa, Qt::CaseInsensitive), 0);
+ QVERIFY(aa.compare(bb) < 0);
+ QVERIFY(bb.compare(aa) > 0);
+}
+
QTEST_APPLESS_MAIN(tst_QStringView)
#include "tst_qstringview.moc"
diff --git a/tests/auto/corelib/tools/qtimeline/BLACKLIST b/tests/auto/corelib/tools/qtimeline/BLACKLIST
index 74f84a4a6d..5611969b4d 100644
--- a/tests/auto/corelib/tools/qtimeline/BLACKLIST
+++ b/tests/auto/corelib/tools/qtimeline/BLACKLIST
@@ -1,7 +1,9 @@
[interpolation]
windows
osx-10.12
+osx-10.13
[duration]
windows
[frameRate]
osx-10.12
+osx-10.13
diff --git a/tests/auto/corelib/tools/qtimezone/qtimezone.pro b/tests/auto/corelib/tools/qtimezone/qtimezone.pro
index 19ebc13306..5ec8d008e7 100644
--- a/tests/auto/corelib/tools/qtimezone/qtimezone.pro
+++ b/tests/auto/corelib/tools/qtimezone/qtimezone.pro
@@ -3,7 +3,7 @@ TARGET = tst_qtimezone
QT = core-private testlib
SOURCES = tst_qtimezone.cpp
qtConfig(icu) {
- DEFINES += QT_USE_ICU
+ QMAKE_USE_PRIVATE += icu
}
darwin {
diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
index ed80d4528d..d335dae7bc 100644
--- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
+++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
@@ -31,6 +31,10 @@
#include <private/qtimezoneprivate_p.h>
#include <qlocale.h>
+#if defined(Q_OS_WIN) && !QT_CONFIG(icu)
+# define USING_WIN_TZ
+#endif
+
class tst_QTimeZone : public QObject
{
Q_OBJECT
@@ -413,7 +417,7 @@ void tst_QTimeZone::specificTransition_data()
QTest::addColumn<int>("dstoff");
// Moscow ditched DST on 2010-10-31 but has since changed standard offset twice.
-#ifdef Q_OS_WIN
+#ifdef USING_WIN_TZ
// Win7 is too old to know about this transition:
if (QOperatingSystemVersion::current() > QOperatingSystemVersion::Windows7)
#endif
@@ -477,8 +481,9 @@ void tst_QTimeZone::transitionEachZone_data()
};
QString name;
+ const auto zones = QTimeZone::availableTimeZoneIds();
for (int k = sizeof(table) / sizeof(table[0]); k-- > 0; ) {
- foreach (QByteArray zone, QTimeZone::availableTimeZoneIds()) {
+ for (const QByteArray &zone : zones) {
name.sprintf("%s@%d", zone.constData(), table[k].year);
QTest::newRow(name.toUtf8().constData())
<< zone
@@ -500,7 +505,7 @@ void tst_QTimeZone::transitionEachZone()
QTimeZone named(zone);
for (int i = start; i < stop; i++) {
-#ifdef Q_OS_WIN
+#ifdef USING_WIN_TZ
// See QTBUG-64985: MS's TZ APIs' misdescription of Europe/Samara leads
// to mis-disambiguation of its fall-back here.
if (QOperatingSystemVersion::current() <= QOperatingSystemVersion::Windows7
@@ -833,7 +838,7 @@ void tst_QTimeZone::utcTest()
void tst_QTimeZone::icuTest()
{
-#if defined(QT_BUILD_INTERNAL) && defined(QT_USE_ICU)
+#if defined(QT_BUILD_INTERNAL) && QT_CONFIG(icu)
// Known datetimes
qint64 std = QDateTime(QDate(2012, 1, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
qint64 dst = QDateTime(QDate(2012, 6, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
@@ -881,7 +886,7 @@ void tst_QTimeZone::icuTest()
testCetPrivate(tzp);
testEpochTranPrivate(QIcuTimeZonePrivate("America/Toronto"));
-#endif // QT_USE_ICU
+#endif // icu
}
void tst_QTimeZone::tzTest()
@@ -907,7 +912,7 @@ void tst_QTimeZone::tzTest()
QLocale enUS("en_US");
// Only test names in debug mode, names used can vary by ICU version installed
if (debug) {
-#ifdef QT_USE_ICU
+#if QT_CONFIG(icu)
QCOMPARE(tzp.displayName(QTimeZone::StandardTime, QTimeZone::LongName, enUS),
QString("Central European Standard Time"));
QCOMPARE(tzp.displayName(QTimeZone::StandardTime, QTimeZone::ShortName, enUS),
@@ -946,7 +951,7 @@ void tst_QTimeZone::tzTest()
QString("CET"));
QCOMPARE(tzp.displayName(QTimeZone::GenericTime, QTimeZone::OffsetName, enUS),
QString("CET"));
-#endif // QT_USE_ICU
+#endif // icu
// Test Abbreviations
QCOMPARE(tzp.abbreviation(std), QString("CET"));
@@ -1123,7 +1128,7 @@ void tst_QTimeZone::darwinTypes()
void tst_QTimeZone::winTest()
{
-#if defined(QT_BUILD_INTERNAL) && defined(Q_OS_WIN)
+#if defined(QT_BUILD_INTERNAL) && defined(USING_WIN_TZ)
// Known datetimes
qint64 std = QDateTime(QDate(2012, 1, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
qint64 dst = QDateTime(QDate(2012, 6, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
@@ -1174,7 +1179,7 @@ void tst_QTimeZone::winTest()
testCetPrivate(tzp);
testEpochTranPrivate(QWinTimeZonePrivate("America/Toronto"));
-#endif // Q_OS_WIN
+#endif // QT_BUILD_INTERNAL && USING_WIN_TZ
}
#ifdef QT_BUILD_INTERNAL
@@ -1286,7 +1291,7 @@ void tst_QTimeZone::testEpochTranPrivate(const QTimeZonePrivate &tzp)
// 1970-04-26 02:00 EST, -5 -> -4
const QDateTime after = QDateTime(QDate(1970, 4, 26), QTime(2, 0), Qt::OffsetFromUTC, -5 * 3600);
const QDateTime found = QDateTime::fromMSecsSinceEpoch(tran.atMSecsSinceEpoch, Qt::UTC);
-#ifdef Q_OS_WIN // MS gets the date wrong: 5th April instead of 26th.
+#ifdef USING_WIN_TZ // MS gets the date wrong: 5th April instead of 26th.
QCOMPARE(found.toOffsetFromUtc(-5 * 3600).time(), after.time());
#else
QCOMPARE(found, after);
diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro
index f35ed026ac..f28cf21b8b 100644
--- a/tests/auto/corelib/tools/tools.pro
+++ b/tests/auto/corelib/tools/tools.pro
@@ -30,6 +30,7 @@ SUBDIRS=\
qlist \
qlist_strictiterators \
qlocale \
+ qmakearray \
qmap \
qmap_strictiterators \
qmargins \